80 lines
3.2 KiB
TypeScript
80 lines
3.2 KiB
TypeScript
/**
|
|||
|
|
* 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 } from '@/components/school/lastDistanceOffered';
|
||
|
|
import type { SchoolAdmissionDistance } from '@/lib/types';
|
||
|
|
|
||
|
|
const distance = (over: Partial<SchoolAdmissionDistance> = {}): 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();
|
||
|
|
});
|
||
|
|
});
|