Files
school_compare/nextjs-app/__tests__/components/CompareOfsted.test.tsx
T
TudorandClaude Fable 5 66bc5523f6
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m2s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 11s
PR Checks / Build Frontend (no push) (pull_request) Successful in 41s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 2m57s
fix(compare): mobile measure-first cards to match the mockup
The grid sections (At a glance, Ofsted, Getting a place, Who goes there)
collapsed generically on mobile — grey label pills, full names wrapping
to 3 lines, no dots — making the page ~2x the mockup's height and
'significantly different' from the mobile design.

Each measure is now wrapped in a <Measure> that is display:contents on
desktop (so the label + cells still flow into the shared aligned grid,
unchanged) and a white card on mobile with compact [dot][short name]
[value] rows — matching the mobile mockup. The sticky school bar becomes
scrollable short-name pills on mobile too. Adds a shortName() util.

Desktop layout is unchanged (display:contents dissolves the wrapper).
Validated the card mechanism and real content shapes (report-card cell,
badges, %+chip rows) via static previews at both widths.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB
2026-07-15 07:50:01 +01:00

107 lines
3.9 KiB
TypeScript

import { render, screen } from '@testing-library/react';
import { CompareOfsted } from '@/components/compare/CompareOfsted';
import type { ComparisonData, OfstedInspection, School } from '@/lib/types';
function school(urn: number, name: string): School {
return { urn, school_name: name } as School;
}
function ofsted(partial: Partial<OfstedInspection>): OfstedInspection {
return {
framework: null,
inspection_date: '2021-10-07',
inspection_type: null,
overall_effectiveness: null,
quality_of_education: null,
behaviour_attitudes: null,
personal_development: null,
leadership_management: null,
early_years_provision: null,
previous_overall: null,
rc_safeguarding_met: null,
rc_inclusion: null,
rc_curriculum_teaching: null,
rc_achievement: null,
rc_attendance_behaviour: null,
rc_personal_development: null,
rc_leadership_governance: null,
rc_early_years: null,
rc_sixth_form: null,
ofsted_page_url: 'https://reports.ofsted.gov.uk/provider/21/1',
...partial,
};
}
const schools = [school(1, 'Graded School'), school(2, 'Carried School'), school(3, 'Card School')];
const data: Record<string, ComparisonData> = {
'1': {
school_info: schools[0],
yearly_data: [],
ofsted: ofsted({ overall_effectiveness: 1, grade_source: 'graded' }),
},
'2': {
school_info: schools[1],
yearly_data: [],
ofsted: ofsted({ overall_effectiveness: 2, grade_source: 'ungraded_carried_forward' }),
},
'3': {
school_info: schools[2],
yearly_data: [],
ofsted: ofsted({
inspection_date: '2025-11-14',
rc_safeguarding_met: true,
report_card: {
rc_achievement: { code: 2, label: 'Strong standard' },
rc_attendance_behaviour: { code: 4, label: 'Needs attention' },
},
}),
},
};
describe('CompareOfsted', () => {
it('renders the three regimes without inventing an overall grade for report cards', () => {
render(<CompareOfsted schools={schools} data={data} />);
expect(screen.getByText('Outstanding')).toBeInTheDocument();
// Carried-forward grade is shown but marked as such
expect(screen.getByText('Good')).toBeInTheDocument();
expect(screen.getByText(/carried forward/i)).toBeInTheDocument();
// Report card: label present, no overall-grade badge for that school
expect(screen.getByText('Report card')).toBeInTheDocument();
expect(screen.getByText(/no overall grade/i)).toBeInTheDocument();
});
it('uses one chip-list grammar for both regimes in judgement detail', () => {
render(<CompareOfsted schools={schools} data={data} />);
// report-card area chip
expect(screen.getByText('Attendance & behaviour')).toBeInTheDocument();
expect(screen.getByText('Needs attention')).toBeInTheDocument();
// graded school without published subgrades → honest dataset statement
expect(
screen.getAllByText(/We don't hold area-by-area detail/i).length,
).toBeGreaterThanOrEqual(1);
});
it('shows the mixed-regime comparability note only when regimes differ', () => {
render(<CompareOfsted schools={schools} data={data} />);
expect(screen.getByText(/aren't directly comparable/i)).toBeInTheDocument();
});
it('links every school to its Ofsted page', () => {
render(<CompareOfsted schools={schools} data={data} />);
const links = screen.getAllByRole('link', { name: /Ofsted page/i });
expect(links).toHaveLength(3);
expect(links[0]).toHaveAttribute('href', 'https://reports.ofsted.gov.uk/provider/21/1');
});
it('renders a per-measure mobile tag with the short school name', () => {
render(<CompareOfsted schools={schools} data={data} />);
// Each measure repeats the schools, so the short name ("Graded" from
// "Graded School") appears once per measure (4) via the cell tag.
expect(screen.getAllByText('Graded').length).toBe(4);
expect(screen.getAllByText('Card').length).toBe(4);
});
});