/** * Last distance offered — formatting and the caveats attached to the figure. * * The assertions about the route note and the year are not cosmetic. A cut-off * shown without its year, or a banded school's widest cut-off shown as if it * were the only one, tells a parent something false about their chances of a * place — so both are pinned here rather than left to the component. */ import { formatCutoffDistance, formatEntryYear } from '@/lib/utils'; import { describeCutoff, describeCutoffAbsence, compareToCutoff, CUTOFF_UNCERTAINTY_M, } from '@/components/school/lastDistanceOffered'; import type { SchoolAdmissionDistance } from '@/lib/types'; const distance = (over: Partial = {}): SchoolAdmissionDistance => ({ year: 2025, distance_m: 500, route_count: 1, la_name: 'Camden', distance_unit_raw: 'miles', ...over, }); describe('formatCutoffDistance', () => { it('leads with miles, the unit councils publish in', () => { expect(formatCutoffDistance(500)).toEqual({ primary: '0.31 miles', secondary: '500 m' }); expect(formatCutoffDistance(1609.344)).toEqual({ primary: '1.00 miles', secondary: '1.6 km' }); }); it('switches to kilometres for the support figure above a kilometre', () => { expect(formatCutoffDistance(3472.96)!.secondary).toBe('3.5 km'); }); it('leads with metres below 100 m, where a miles figure carries nothing', () => { expect(formatCutoffDistance(27)).toEqual({ primary: '27 m', secondary: '0.02 miles' }); }); it('returns null rather than a zero cut-off', () => { // 0.0 miles appears in the source where a school filled on a higher // criterion. Rendered as "0.00 miles" it would read as the opposite. expect(formatCutoffDistance(0)).toBeNull(); expect(formatCutoffDistance(null)).toBeNull(); expect(formatCutoffDistance(undefined)).toBeNull(); expect(formatCutoffDistance(Number.NaN)).toBeNull(); }); }); describe('formatEntryYear', () => { it('names the intake, not the academic year', () => { // formatAcademicYear would render 2025 as "2025/26", which reads as a // school year rather than the September a child started. expect(formatEntryYear(2025)).toBe('September 2025'); expect(formatEntryYear(null)).toBe(''); }); }); describe('describeCutoff', () => { it('always carries the entry year alongside the figure', () => { const d = describeCutoff(distance({ distance_m: 772.49, year: 2024 })); expect(d).not.toBeNull(); expect(d!.primary).toBe('0.48 miles'); expect(d!.entryYear).toBe('September 2024'); }); it('says nothing about routes for a school with one', () => { expect(describeCutoff(distance({ route_count: 1 }))!.routeNote).toBeNull(); expect(describeCutoff(distance({ route_count: null }))!.routeNote).toBeNull(); }); it('warns that a banded school\'s figure is the widest of several', () => { const note = describeCutoff(distance({ route_count: 4 }))!.routeNote; expect(note).toContain('4 admission routes'); expect(note).toContain('shorter cut-off'); }); it('is null when there is nothing publishable', () => { expect(describeCutoff(null)).toBeNull(); expect(describeCutoff(undefined)).toBeNull(); expect(describeCutoff(distance({ distance_m: null }))).toBeNull(); }); }); // ── "Would we have got in?" ──────────────────────────────────────────── describe('compareToCutoff', () => { it('calls a clearly nearer home inside, and names the year', () => { const r = compareToCutoff(300, 800, 2026); expect(r.verdict).toBe('inside'); expect(r.headline).toContain('September 2026'); }); it('calls a clearly further home beyond', () => { expect(compareToCutoff(4000, 800, 2026).verdict).toBe('outside'); }); it('refuses to call a result inside the measurement error, either way', () => { // A postcode centroid covers several addresses, so a margin this fine is // noise. With one published year there is no other year to fall back on, // which makes this band the only thing standing between a parent and a // place they do not have. expect(compareToCutoff(800 - CUTOFF_UNCERTAINTY_M / 2, 800, 2026).verdict).toBe('too-close'); expect(compareToCutoff(800 + CUTOFF_UNCERTAINTY_M / 2, 800, 2026).verdict).toBe('too-close'); expect(compareToCutoff(800, 800, 2026).detail).toContain('measurement error'); // The explanation is not welded to the headline, so it does not run at // headline weight in the result block. expect(compareToCutoff(800, 800, 2026).headline).not.toContain('measurement error'); expect(compareToCutoff(300, 800, 2026).detail).toBeNull(); }); it('treats the band as exclusive at its edge', () => { // Exactly on the boundary is still too close; one metre past it is not. expect(compareToCutoff(800 - CUTOFF_UNCERTAINTY_M, 800, 2026).verdict).toBe('too-close'); expect(compareToCutoff(800 - CUTOFF_UNCERTAINTY_M - 1, 800, 2026).verdict).toBe('inside'); }); }); describe('describeCutoffAbsence', () => { it('explains a selective school by how it admits, not as missing data', () => { const s = describeCutoffAbsence({ localAuthority: 'Kent', admissionsPolicy: 'Selective' }); expect(s).toContain('entrance test'); expect(s).not.toContain('has not published'); }); it('reads a consistently undersubscribed school as good news', () => { const s = describeCutoffAbsence({ localAuthority: 'Camden', admissionsHistory: [ { year: 2022, oversubscribed: false }, { year: 2023, oversubscribed: false }, { year: 2024, oversubscribed: false }, ], }); expect(s).toContain('has not needed a distance cut-off'); }); it('otherwise names the authority that would hold the figure', () => { expect(describeCutoffAbsence({ localAuthority: 'Camden' })) .toContain('Camden has not published'); }); });