125 lines
6.0 KiB
TypeScript
125 lines
6.0 KiB
TypeScript
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<React.ComponentProps<typeof LeafletMapInner>> = {}) {
|
|
const all = {
|
|
schools, center: centre, zoom: 13, referencePoint: centre, radiusMiles: 1,
|
|
nationalAvgRwm: 62, ...props,
|
|
};
|
|
const view = render(<LeafletMapInner {...all} />);
|
|
return { ...view, rerender: (next: Partial<typeof all>) => view.rerender(<LeafletMapInner {...all} {...next} />) };
|
|
}
|
|
|
|
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);
|
|
});
|
|
|
|
it('compares a state secondary with its LA average on the card, but not an independent one', () => {
|
|
const state: School = { ...base, urn: 3, school_name: 'Holland Park School', school_type: 'Academy converter',
|
|
phase: 'Secondary', local_authority: 'Kensington and Chelsea', attainment_8_score: 60,
|
|
latitude: 51.5, longitude: -0.2, distance: 0.3 };
|
|
const independent: School = { ...state, urn: 4, school_name: 'Abbey Gate College',
|
|
school_type: 'Other independent school', attainment_8_score: 20.4 };
|
|
const laAverages = { 'Kensington and Chelsea': 54.5 };
|
|
|
|
const { container, rerender } = renderMap({ schools: [state, independent], laAverages, selectedUrn: 3 });
|
|
expect(container.querySelector('.sc-popup')).toHaveTextContent('60.0 Att 8 +5.5 vs LA');
|
|
|
|
rerender({ schools: [state, independent], laAverages, selectedUrn: 4 });
|
|
const card = container.querySelector('.sc-popup')!;
|
|
expect(card).toHaveTextContent('20.4 Att 8');
|
|
expect(card).not.toHaveTextContent(/vs LA/);
|
|
});
|