/** * Last distance offered, rendered on both detail templates. * * The figure is the one number on these pages that a parent may act on — it is * easy to read as "we live inside the catchment, we will get a place". These * tests pin the things that stop it being read that way: the year is always * present, the caveat is always present, and the blanket "not available" * sentence appears only when it is actually true. */ import { screen, fireEvent } from '@testing-library/react'; import { renderSchoolDetail, renderSecondarySchoolDetail } from '../support/renderSchoolDetail'; import { primaryFixture, secondaryFixture } from '../support/schoolFixtures'; import type { SchoolAdmissionDistance } from '@/lib/types'; const cutoff = (over: Partial = {}): SchoolAdmissionDistance => ({ year: 2025, distance_m: 500, route_count: 1, la_name: 'Camden', distance_unit_raw: 'miles', ...over, }); describe('primary detail page', () => { it('shows the figure with the year it belongs to', () => { renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff({ distance_m: 772.49, year: 2024 }) }); expect(screen.getByText('0.48 miles')).toBeInTheDocument(); expect(screen.getByText(/Last distance offered/)).toHaveTextContent('September 2024'); }); it('never shows the figure without saying it is not a catchment', () => { renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff() }); expect(screen.getByText(/not a fixed catchment/)).toBeInTheDocument(); expect(screen.getByText(/moves every year/)).toBeInTheDocument(); }); it('flags that a banded school\'s figure is the widest of several routes', () => { renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff({ route_count: 4 }) }); expect(screen.getByText(/4 admission routes/)).toBeInTheDocument(); }); it('renders nothing distance-related when the LA publishes none', () => { renderSchoolDetail({ ...primaryFixture, admissionDistance: null }); expect(screen.queryByText(/Last distance offered/)).not.toBeInTheDocument(); expect(screen.queryByText(/not a fixed catchment/)).not.toBeInTheDocument(); }); it('carries the figure even with no EES admissions row', () => { // The two sources are independent; this school has a cut-off and no // admissions figures. Before this feature the section did not render at all. renderSchoolDetail({ ...primaryFixture, admissions: null, admissionsHistory: [], admissionDistance: cutoff({ distance_m: 1421.05 }), }); expect(screen.getByText('0.88 miles')).toBeInTheDocument(); }); }); describe('secondary detail page', () => { it('shows the figure with the year it belongs to', () => { renderSecondarySchoolDetail({ ...secondaryFixture, admissionDistance: cutoff({ distance_m: 3472.96 }) }); expect(screen.getByText('2.16 miles')).toBeInTheDocument(); expect(screen.getByText(/Last distance offered/)).toHaveTextContent('September 2025'); }); it('drops the blanket "not available" line once a distance exists', () => { renderSecondarySchoolDetail({ ...secondaryFixture, admissionDistance: cutoff() }); expect(screen.queryByText(/has not published a cut-off distance/)).not.toBeInTheDocument(); expect(screen.getByText(/not a fixed catchment/)).toBeInTheDocument(); }); it('names the authority that would hold the data when there is none', () => { // The old copy asserted "Historical distance cut-off data is not available // for this school" on every secondary page, including the ones whose // council does publish it. renderSecondarySchoolDetail({ ...secondaryFixture, admissionDistance: null }); expect(screen.getByText(/has not published a cut-off distance/)).toBeInTheDocument(); }); }); // ── The Distance view ────────────────────────────────────────────────── const history = (pts: [number, number][]): SchoolAdmissionDistance[] => pts.map(([year, distance_m]) => ({ year, distance_m, route_count: 1, la_name: 'Camden', distance_unit_raw: 'miles', })); describe('primary Distance view', () => { it('appears once there are two or more published years', () => { renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff({ distance_m: 700, year: 2024 }), admissionDistanceHistory: history([[2021, 1000], [2022, 900], [2023, 800], [2024, 700]]), }); expect(screen.getByRole('button', { name: 'Distance' })).toBeInTheDocument(); }); it('stays hidden on a single published year', () => { // One point is a fact, not a history; a chart of it invites a trend reading // that is not there. renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff({ distance_m: 700, year: 2024 }), admissionDistanceHistory: history([[2024, 700]]), }); expect(screen.queryByRole('button', { name: 'Distance' })).not.toBeInTheDocument(); }); it('lists every year in the span, including the ones with no figure', () => { renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff({ distance_m: 700, year: 2024 }), admissionDistanceHistory: history([[2021, 1000], [2024, 700]]), }); // The view is server-rendered but starts hidden behind its tab, and role // queries skip hidden subtrees — so open it the way a reader would. fireEvent.click(screen.getByRole('button', { name: 'Distance' })); // 2022 and 2023 were never published but must still appear as rows, or the // gap in the chart has nothing explaining it. for (const year of ['2021', '2022', '2023', '2024']) { expect(screen.getByRole('rowheader', { name: year })).toBeInTheDocument(); } expect(screen.getAllByText('Not published').length).toBe(2); }); it('never claims everyone was offered a place', () => { // fact_admissions.oversubscribed is about first preferences only, so the // stronger claim is not supported by the data behind it. renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff({ distance_m: 700, year: 2024 }), admissionDistanceHistory: history([[2021, 1000], [2024, 700]]), admissionsHistory: [ ...primaryFixture.admissionsHistory, { year: 2022, oversubscribed: false, places_offered: 60 }, ], }); expect(screen.getByText(/Places available on first preferences/)).toBeInTheDocument(); expect(screen.queryByText(/every applicant/i)).not.toBeInTheDocument(); expect(screen.queryByText(/all offered/i)).not.toBeInTheDocument(); }); it('withholds a trend reading while the record is thin', () => { renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff({ distance_m: 700, year: 2024 }), admissionDistanceHistory: history([[2023, 800], [2024, 700]]), }); expect(screen.getByText(/too few to read as a trend/)).toBeInTheDocument(); expect(screen.queryByText(/Across \d+ published years/)).not.toBeInTheDocument(); }); }); describe('secondary Distance detail', () => { it('renders inline, with no extra tab, once there are two published years', () => { renderSecondarySchoolDetail({ ...secondaryFixture, admissionDistance: cutoff({ distance_m: 3472.96 }), admissionDistanceHistory: history([[2023, 3800], [2024, 3472.96]]), }); expect(screen.getByText(/Last distance offered, by year/)).toBeInTheDocument(); expect(screen.getByRole('rowheader', { name: '2023' })).toBeInTheDocument(); }); it('explains a selective school by how it admits rather than as missing data', () => { renderSecondarySchoolDetail({ ...secondaryFixture, schoolInfo: { ...secondaryFixture.schoolInfo, admissions_policy: 'Selective' }, admissionDistance: null, admissionDistanceHistory: [], }); expect(screen.getByText(/ranked by the entrance test/)).toBeInTheDocument(); expect(screen.queryByText(/has not published a cut-off distance/)).not.toBeInTheDocument(); }); it('reads a consistently undersubscribed school as good news', () => { renderSecondarySchoolDetail({ ...secondaryFixture, admissionDistance: null, admissionDistanceHistory: [], admissionsHistory: [ { year: 2022, oversubscribed: false }, { year: 2023, oversubscribed: false }, { year: 2024, oversubscribed: false }, ], }); expect(screen.getByText(/has not needed a distance cut-off/)).toBeInTheDocument(); }); });