feat(school): state the header's facts in one line, and flag what applies
The row of grey chips under the name mixed the council, a GIAS governance term, the age range and provision, with no labels. Parents could not tell what "Wandsworth" or "Nursery" meant, and selective, faith and fees were missing or buried in the details. The header now prints one fact line (phase pill · ages · type · pupils), then flags only for what applies, in a fixed order: who can apply or what it costs (Fee-paying, Selective, Girls'/Boys' school, the religious character as recorded), then what the school offers (Nursery class, Sixth form). Flags carry no hue: they are facts, not verdicts. The council joins the address unless the address already names it. The details keep headteacher, website, phone, academy trust (hidden when it has the school's own name) and capacity; county, constituency and religious character leave the header. The proposed-to-close strip is unchanged. lib/schoolFacts holds the type label and the flags so the search rows can print the same words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
62a6bfaf0c
commit
ca47d08186
7 files changed
+352
-86
No files matched your search
@@ -1,12 +1,13 @@
|
||||
/**
|
||||
* The facts row under the school name.
|
||||
* The school header: one fact line (phase, ages, type, pupils), then flags
|
||||
* only for what applies, then the address and the details.
|
||||
*
|
||||
* nursery_provision is GIAS text, not a boolean: "Has Nursery Classes",
|
||||
* "No Nursery Classes" or "Not applicable". Tested for truthiness, every one
|
||||
* of those read as a nursery, so secondaries aged 11–18 showed "Nursery".
|
||||
*/
|
||||
|
||||
import { screen } from '@testing-library/react';
|
||||
import { screen, within } from '@testing-library/react';
|
||||
import type { School } from '@/lib/types';
|
||||
import { primaryFixture, secondaryFixture } from '../support/schoolFixtures';
|
||||
import { renderSchoolDetail, renderSecondarySchoolDetail } from '../support/renderSchoolDetail';
|
||||
@@ -35,22 +36,54 @@ function withSchool<T extends { schoolInfo: School }>(fixture: T, info: Partial<
|
||||
return { ...fixture, schoolInfo: { ...fixture.schoolInfo, ...info } };
|
||||
}
|
||||
|
||||
describe('school header nursery chip', () => {
|
||||
it('shows Nursery when GIAS says the school has nursery classes', () => {
|
||||
const flagList = () => screen.queryByRole('list', { name: 'Admission and provision' });
|
||||
const flagLabels = () => within(flagList()!).getAllByRole('listitem').map((li) => li.textContent);
|
||||
|
||||
describe('school header fact line', () => {
|
||||
it('states phase, ages, type and pupils, in that order', () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, { type_group: 'state' }));
|
||||
const line = screen.getByText('Ages 4–11').parentElement!;
|
||||
expect(line).toHaveTextContent(/^PrimaryAges 4–11State school420 pupils$/);
|
||||
});
|
||||
|
||||
it("prints the register's type name for a type in no group", () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, { type_group: null, school_type: 'Secure units' }));
|
||||
expect(screen.getByText('Secure units')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('no longer prints the GIAS establishment type', () => {
|
||||
renderSecondarySchoolDetail(withSchool(secondaryFixture, { type_group: 'state' }));
|
||||
expect(screen.queryByText('Academy converter')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('school header flags', () => {
|
||||
it('shows no flag list for a school with nothing to flag', () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, { type_group: 'state' }));
|
||||
expect(flagList()).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('lists who-can-apply flags, then what the school offers', () => {
|
||||
renderSecondarySchoolDetail(withSchool(secondaryFixture, {
|
||||
type_group: 'independent', admissions_policy: 'Selective', gender: 'Girls',
|
||||
religious_denomination: 'Church of England', has_sixth_form: true,
|
||||
}));
|
||||
expect(flagLabels()).toEqual(['Fee-paying', 'Selective', "Girls' school", 'Church of England', 'Sixth form']);
|
||||
});
|
||||
|
||||
it('shows Nursery class when GIAS says the school has nursery classes', () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, { nursery_provision: 'Has Nursery Classes' }));
|
||||
expect(screen.getByText('Nursery', { selector: 'span' })).toBeInTheDocument();
|
||||
expect(flagLabels()).toEqual(['Nursery class']);
|
||||
});
|
||||
|
||||
it.each(['No Nursery Classes', 'Not applicable', null])(
|
||||
'hides Nursery when GIAS says %p',
|
||||
'shows no nursery flag when GIAS says %p',
|
||||
(value) => {
|
||||
renderSecondarySchoolDetail(withSchool(secondaryFixture, { nursery_provision: value }));
|
||||
expect(screen.queryByText('Nursery', { selector: 'span' })).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/^Nursery/)).not.toBeInTheDocument();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('school header single-sex chip', () => {
|
||||
it.each([['Girls', "Girls' school"], ['Boys', "Boys' school"]])(
|
||||
'labels a %s school with a plural possessive',
|
||||
(gender, label) => {
|
||||
@@ -65,3 +98,44 @@ describe('school header single-sex chip', () => {
|
||||
expect(screen.queryByText(/^(Girls|Boys|Mixed)'s? school$/)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('school header address', () => {
|
||||
it('names the council after the postcode', () => {
|
||||
renderSchoolDetail(primaryFixture);
|
||||
expect(screen.getByText(/TE1 1ST · Westshire/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('leaves the council out when the address already names it', () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, { local_authority: 'Testville' }));
|
||||
expect(screen.queryByText(/· Testville/)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('school header details', () => {
|
||||
const detailed = {
|
||||
headteacher_name: 'Mrs A Head', capacity: 426, county: 'Surrey',
|
||||
parliamentary_constituency: 'Putney', religious_denomination: 'Church of England',
|
||||
};
|
||||
|
||||
it('drops county, constituency and religious character', () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, detailed));
|
||||
expect(screen.queryByText('County:')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('Constituency:')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('Religious character:')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the capacity', () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, detailed));
|
||||
expect(screen.getByText('Capacity:').parentElement).toHaveTextContent('Capacity: 426');
|
||||
});
|
||||
|
||||
it('names an academy trust', () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, { trust_name: 'BURNTWOOD TRUST' }));
|
||||
expect(screen.getByText('Academy trust:').parentElement).toHaveTextContent('BURNTWOOD TRUST');
|
||||
});
|
||||
|
||||
it("hides a trust that has the school's own name", () => {
|
||||
renderSchoolDetail(withSchool(primaryFixture, { trust_name: 'TEST PRIMARY SCHOOL' }));
|
||||
expect(screen.queryByText('Academy trust:')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -43,14 +43,13 @@ function withoutCensus(schoolTotal: number | null) {
|
||||
describe('pupil count without a census record', () => {
|
||||
it('uses the register count in the header, not the results cohort', () => {
|
||||
renderSecondarySchoolDetail(withoutCensus(1462));
|
||||
const pupils = screen.getByText('Pupils:').parentElement!;
|
||||
expect(pupils).toHaveTextContent('1,462');
|
||||
expect(pupils).not.toHaveTextContent('245');
|
||||
expect(screen.getByText('1,462 pupils')).toBeInTheDocument();
|
||||
expect(screen.queryByText('245 pupils')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows no count rather than the results cohort when the register has none', () => {
|
||||
renderSecondarySchoolDetail(withoutCensus(null));
|
||||
expect(screen.queryByText('Pupils:')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/^[\d,]+ pupils$/)).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('Total pupils')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user