Files
TREK/client/src/hooks/useReportedHeight.test.tsx
T
Maurice 4c0583845a fix(map): keep the selected place findable on the map
Selecting a place no longer spiderfies a city-sized cluster: the reveal
only fans open bubbles of up to 12 stops, or stacks whose stops all share
one coordinate, so a zoomed-out trip with hundreds of places stays usable
(#2990).

The selected pin now carries a white border inside a pulsing blue ring on
both renderers (static under reduced motion), and the map measures the
place card instead of assuming a fixed 320px, so the selection pans the
pin above even a tall card on portrait tablets and eases it back out when
the card grows over it later (#2991).

Closes #2990
Closes #2991
2026-11-06 12:50:02 +01:00

69 lines
2.5 KiB
TypeScript

import { render } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { useMeasuredHeight, useReportedHeight } from './useReportedHeight';
function Card({ onHeight, open = true }: { onHeight?: (height: number) => void; open?: boolean }) {
const ref = useReportedHeight(onHeight);
return open ? <div ref={ref}>card</div> : null;
}
const original = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight');
afterEach(() => {
if (original) Object.defineProperty(HTMLElement.prototype, 'offsetHeight', original);
vi.unstubAllGlobals();
});
describe('useReportedHeight', () => {
it('REPORTED-HEIGHT-001: reports the height on mount and 0 once the element is gone', () => {
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { configurable: true, get: () => 412 });
const onHeight = vi.fn();
const { rerender } = render(<Card onHeight={onHeight} />);
expect(onHeight).toHaveBeenLastCalledWith(412);
rerender(<Card onHeight={onHeight} open={false} />);
expect(onHeight).toHaveBeenLastCalledWith(0);
});
it('REPORTED-HEIGHT-002: reports again whenever the element resizes', () => {
let height = 300;
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { configurable: true, get: () => height });
const observed: { resize?: () => void } = {};
const disconnect = vi.fn();
vi.stubGlobal(
'ResizeObserver',
class {
constructor(cb: () => void) {
observed.resize = cb;
}
observe() {}
disconnect = disconnect;
}
);
const onHeight = vi.fn();
const { unmount } = render(<Card onHeight={onHeight} />);
height = 820;
expect(observed.resize).toBeTypeOf('function');
observed.resize?.();
expect(onHeight).toHaveBeenLastCalledWith(820);
unmount();
expect(disconnect).toHaveBeenCalled();
});
it('REPORTED-HEIGHT-003: does nothing without a listener', () => {
expect(() => render(<Card />)).not.toThrow();
});
});
describe('useMeasuredHeight', () => {
it('REPORTED-HEIGHT-004: holds the measured height as state', () => {
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { configurable: true, get: () => 512 });
function Probe() {
const { height, measure } = useMeasuredHeight();
return <div ref={measure} data-height={height} />;
}
const { container } = render(<Probe />);
expect(container.firstElementChild?.getAttribute('data-height')).toBe('512');
});
});