import { act, fireEvent, render } from '@testing-library/react'; import LeafletMapInner from '@/components/LeafletMapInner'; import { primaryFixture } from '../support/schoolFixtures'; import type { School } from '@/lib/types'; /* * The results map's own logic, against real Leaflet in jsdom: which pin is * selected, whether the card opens, and what the card offers. jsdom lays out * nothing, so this pins behaviour, never positions. */ const base = primaryFixture.schoolInfo; const a: School = { ...base, urn: 1, school_name: 'Southmead Primary School', latitude: 51.43, longitude: -0.21, distance: 0.2, rwm_expected_pct: 52 }; const b: School = { ...base, urn: 2, school_name: 'Greenmead School', latitude: 51.431, longitude: -0.205, distance: 0.2, school_type: 'Community special school', rwm_expected_pct: 0, reading_expected_pct: 0, writing_expected_pct: 0, maths_expected_pct: 0 }; const schools = [a, b]; const centre: [number, number] = [51.43, -0.21]; function setWide(wide: boolean) { window.matchMedia = ((q: string) => ({ matches: wide, media: q, addEventListener() {}, removeEventListener() {}, })) as unknown as typeof window.matchMedia; } function renderMap(props: Partial> = {}) { const all = { schools, center: centre, zoom: 13, referencePoint: centre, radiusMiles: 1, nationalAvgRwm: 62, ...props, }; const view = render(); return { ...view, rerender: (next: Partial) => view.rerender() }; } beforeEach(() => setWide(true)); it('draws a pin per school, the search location and the radius', () => { const { container } = renderMap(); expect(container.querySelectorAll('.sc-pin')).toHaveLength(2); expect(container.querySelector('.sc-home')).not.toBeNull(); expect(container.querySelector('.sc-radius-label')).toHaveTextContent('1 mile'); }); it('reports a pin click, and marks and opens the selected school', () => { const onMarkerClick = jest.fn(); const { container, rerender } = renderMap({ onMarkerClick }); fireEvent.click(container.querySelectorAll('.sc-pin')[0]); expect(onMarkerClick).toHaveBeenCalledWith(a); rerender({ onMarkerClick, selectedUrn: 1 }); expect(container.querySelectorAll('.sc-pin--selected')).toHaveLength(1); expect(container.querySelector('.sc-popup')).toHaveTextContent('Southmead Primary School'); expect(container.querySelector('.sc-popup')).toHaveTextContent('52% RWM -10 pts'); }); it('keeps the special-school card free of a benchmark and a placeholder 0%', () => { const { container } = renderMap({ selectedUrn: 2 }); const card = container.querySelector('.sc-popup')!; expect(card).toHaveTextContent('Greenmead School'); expect(card).not.toHaveTextContent(/%|pts/); }); it('adds to compare from the card, and the card follows the basket', () => { const onAddToCompare = jest.fn(); const { container, rerender } = renderMap({ onAddToCompare, selectedUrn: 1, compareUrns: [] }); fireEvent.click(container.querySelector('[data-compare]')!); expect(onAddToCompare).toHaveBeenCalledWith(a); rerender({ onAddToCompare, selectedUrn: 1, compareUrns: [1] }); expect(container.querySelector('[data-compare]')).toHaveTextContent('✓ Comparing'); fireEvent.click(container.querySelector('[data-compare]')!); expect(onAddToCompare).toHaveBeenCalledTimes(2); }); it('tells the page when the card is closed from the map, but not when replaced', () => { const onDeselect = jest.fn(); const { container, rerender } = renderMap({ onDeselect, selectedUrn: 1 }); rerender({ onDeselect, selectedUrn: 2 }); expect(onDeselect).not.toHaveBeenCalled(); fireEvent.click(container.querySelector('.leaflet-popup-close-button')!); expect(onDeselect).toHaveBeenCalledTimes(1); }); it('keeps the selection when the results reload under it', () => { const onDeselect = jest.fn(); const { container, rerender } = renderMap({ onDeselect, selectedUrn: 1 }); act(() => rerender({ onDeselect, selectedUrn: 1, schools: [...schools] })); expect(onDeselect).not.toHaveBeenCalled(); expect(container.querySelector('.sc-popup')).toHaveTextContent('Southmead Primary School'); }); it('opens no card on a narrow screen, where the page shows a bottom sheet', () => { setWide(false); const { container } = renderMap({ selectedUrn: 1 }); expect(container.querySelectorAll('.sc-pin--selected')).toHaveLength(1); expect(container.querySelector('.sc-popup')).toBeNull(); }); it('puts the card back when the pins are rebuilt for a reason other than the schools', () => { const onDeselect = jest.fn(); const { container, rerender } = renderMap({ onDeselect, selectedUrn: 1 }); act(() => rerender({ onDeselect, selectedUrn: 1, radiusMiles: 3, referencePoint: [51.43, -0.21] })); expect(onDeselect).not.toHaveBeenCalled(); expect(container.querySelector('.sc-radius-label')).toHaveTextContent('3 miles'); expect(container.querySelector('.sc-popup')).toHaveTextContent('Southmead Primary School'); expect(container.querySelectorAll('.sc-pin--selected')).toHaveLength(1); });