PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m14s
PR Checks / Backend Smoke (pull_request) Successful in 10s
PR Checks / Build Backend (no push) (pull_request) Successful in 19s
PR Checks / Build Frontend (no push) (pull_request) Successful in 1m19s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 11s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 1m20s
Rewrites every visitor-facing string that used an em dash, choosing the punctuation for what the dash was doing: a colon before a list or explanation, a comma for an aside, a full stop between two thoughts, parentheses for an aside mid-sentence. Covers page titles and meta descriptions, the home and admissions guide copy, school page headings and notes, the compare page, metric labels and tooltips. Two rewrites also fix the sentence around them: the closure banner no longer repeats "proposed for closure", and the cut-off caveat's list of priorities now parses. A lone dash marking a missing value in a table cell stays: it is a data convention, not prose. A Jest guard walks the source with the TypeScript parser and fails on any other em dash in a string or JSX text node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
141 lines
5.0 KiB
TypeScript
141 lines
5.0 KiB
TypeScript
/**
|
|
* Getting a place — phase and school-type correctness (expert sign-off
|
|
* must-fixes M1/M3):
|
|
* - an all-through school's Year 7 round must never render on the primary
|
|
* tab as if it were Reception odds;
|
|
* - selective schools get entrance-test framing, and the secondary tab
|
|
* never shows the primaries' distance template.
|
|
*/
|
|
|
|
import { render, screen } from '@testing-library/react';
|
|
|
|
import { CompareAdmissions } from '@/components/compare/CompareAdmissions';
|
|
import type { ComparisonData, School, SchoolAdmissions } from '@/lib/types';
|
|
|
|
function school(urn: number, name: string, extra: Partial<School> = {}): School {
|
|
return { urn, school_name: name, ...extra } as School;
|
|
}
|
|
|
|
function admissions(partial: Partial<SchoolAdmissions>): SchoolAdmissions {
|
|
return {
|
|
year: 202627,
|
|
school_phase: 'Secondary',
|
|
places_offered: 173,
|
|
total_applications: 433,
|
|
first_preference_offer_pct: 83,
|
|
oversubscribed: true,
|
|
...partial,
|
|
} as SchoolAdmissions;
|
|
}
|
|
|
|
function entry(info: School, a: SchoolAdmissions | null): ComparisonData {
|
|
return {
|
|
school_info: info,
|
|
yearly_data: [],
|
|
ofsted: null,
|
|
census: null,
|
|
admissions: a,
|
|
admissions_history: a ? [a] : [],
|
|
deprivation: null,
|
|
};
|
|
}
|
|
|
|
describe('CompareAdmissions', () => {
|
|
it("does not show an all-through school's Year 7 round on the primary tab", () => {
|
|
// The real M1 scenario: an all-through school (Year 7 round only) beside
|
|
// a primary with a Reception round.
|
|
const allThrough = school(137306, 'Hessle High and Penshurst Primary');
|
|
const primary = school(138690, 'Barclay Primary School');
|
|
const data = {
|
|
'137306': entry(allThrough, admissions({ school_phase: 'Secondary' })),
|
|
'138690': entry(
|
|
primary,
|
|
admissions({
|
|
school_phase: 'Primary',
|
|
total_applications: 300,
|
|
places_offered: 120,
|
|
first_preference_offer_pct: 96,
|
|
}),
|
|
),
|
|
};
|
|
|
|
render(<CompareAdmissions schools={[allThrough, primary]} data={data} isSecondary={false} />);
|
|
|
|
// Hessle's Year 7 figures must not appear…
|
|
expect(screen.queryByText('433')).toBeNull();
|
|
expect(
|
|
screen.getByText(/We don't hold Reception admissions data for this school/),
|
|
).toBeInTheDocument();
|
|
// …while Barclay's Reception round renders normally.
|
|
expect(screen.getByText('300')).toBeInTheDocument();
|
|
});
|
|
|
|
it('phase-labels the section empty state when no matching round exists at all', () => {
|
|
const allThrough = school(137306, 'Hessle High and Penshurst Primary');
|
|
const data = { '137306': entry(allThrough, admissions({ school_phase: 'Secondary' })) };
|
|
|
|
render(<CompareAdmissions schools={[allThrough]} data={data} isSecondary={false} />);
|
|
|
|
expect(
|
|
screen.getByText(/No Reception admissions data is available for these schools yet/),
|
|
).toBeInTheDocument();
|
|
expect(screen.queryByText('433')).toBeNull();
|
|
});
|
|
|
|
it('shows the Year 7 round on the secondary tab', () => {
|
|
const allThrough = school(137306, 'Hessle High and Penshurst Primary');
|
|
const data = { '137306': entry(allThrough, admissions({ school_phase: 'Secondary' })) };
|
|
|
|
render(<CompareAdmissions schools={[allThrough]} data={data} isSecondary={true} />);
|
|
|
|
expect(screen.getByText('433')).toBeInTheDocument();
|
|
expect(screen.getByText('173')).toBeInTheDocument();
|
|
});
|
|
|
|
it('gives selective schools entrance-test framing, never the distance template', () => {
|
|
const grammar = school(136276, 'Watford Grammar School for Boys', {
|
|
admissions_policy: 'Selective',
|
|
religious_denomination: 'Church of England',
|
|
});
|
|
const data = {
|
|
'136276': entry(grammar, admissions({ first_preference_offer_pct: 43.7 })),
|
|
};
|
|
|
|
render(<CompareAdmissions schools={[grammar]} data={data} isSecondary={true} />);
|
|
|
|
expect(
|
|
screen.getByText(/Entry is by entrance test\. The school is selective/),
|
|
).toBeInTheDocument();
|
|
expect(screen.queryByText(/non-faith primaries/)).toBeNull();
|
|
});
|
|
|
|
it('secondary faith school gets faith-aware copy, not the primaries template', () => {
|
|
const faithSchool = school(102052, "Bishop Stopford's School", {
|
|
admissions_policy: 'Non-selective',
|
|
religious_denomination: 'Church of England',
|
|
});
|
|
const data = {
|
|
'102052': entry(faithSchool, admissions({ first_preference_offer_pct: 68 })),
|
|
};
|
|
|
|
render(<CompareAdmissions schools={[faithSchool]} data={data} isSecondary={true} />);
|
|
|
|
expect(screen.getByText(/faith-based criteria may apply/)).toBeInTheDocument();
|
|
expect(screen.queryByText(/non-faith primaries/)).toBeNull();
|
|
});
|
|
|
|
it('keeps the reviewed distance copy for oversubscribed non-faith primaries', () => {
|
|
const primary = school(100140, 'Plumcroft Primary School');
|
|
const data = {
|
|
'100140': entry(
|
|
primary,
|
|
admissions({ school_phase: 'Primary', first_preference_offer_pct: 73.4 }),
|
|
),
|
|
};
|
|
|
|
render(<CompareAdmissions schools={[primary]} data={data} isSecondary={false} />);
|
|
|
|
expect(screen.getByText(/for most non-faith primaries, distance decides/)).toBeInTheDocument();
|
|
});
|
|
});
|