whisper-money/resources/js/components/ui/chart-tooltip-portal.test.tsx

59 lines
2.2 KiB
TypeScript

import { fireEvent, render } from '@testing-library/react';
import * as React from 'react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { ChartTooltipPortal } from './chart';
/**
* Renders the portal inside a `.recharts-wrapper` (the ancestor its layout
* effect looks up) and exposes a button that bumps unrelated state to force a
* re-render without touching `coordinate`.
*/
function Harness({ coordinate }: { coordinate: { x: number; y: number } }) {
const [, setTick] = React.useState(0);
return (
<div className="recharts-wrapper">
<button onClick={() => setTick((t) => t + 1)}>rerender</button>
<ChartTooltipPortal coordinate={coordinate}>
<span>tooltip</span>
</ChartTooltipPortal>
</div>
);
}
describe('ChartTooltipPortal', () => {
afterEach(() => {
vi.restoreAllMocks();
});
// The positioning effect reads the wrapper's rect, so a call to
// getBoundingClientRect is a proxy for "the effect ran".
it('does not recompute its position on a re-render with an unchanged coordinate (regression: PHP-LARAVEL-3B render loop)', () => {
const rectSpy = vi.spyOn(Element.prototype, 'getBoundingClientRect');
const { getByText } = render(<Harness coordinate={{ x: 10, y: 20 }} />);
const afterMount = rectSpy.mock.calls.length;
expect(afterMount).toBeGreaterThan(0);
fireEvent.click(getByText('rerender'));
fireEvent.click(getByText('rerender'));
// With the pre-fix dependency-less effect this count would climb on
// every render and the setPos feedback loop would eventually throw
// "Maximum update depth exceeded".
expect(rectSpy.mock.calls.length).toBe(afterMount);
});
it('recomputes its position when the coordinate changes', () => {
const rectSpy = vi.spyOn(Element.prototype, 'getBoundingClientRect');
const { rerender } = render(<Harness coordinate={{ x: 10, y: 20 }} />);
const afterMount = rectSpy.mock.calls.length;
rerender(<Harness coordinate={{ x: 200, y: 300 }} />);
expect(rectSpy.mock.calls.length).toBeGreaterThan(afterMount);
});
});