import { render, screen } from '@testing-library/react'; import { PlaceView } from '@/components/places/PlaceView'; import type { PlaceDetail } from '@/lib/places'; const detail: PlaceDetail = { place: { kind: 'town', slug: 'brentwood', name: 'Brentwood', count: 29, parent_authority: 'Essex', phases: ['primary'] }, schools: [ { urn: 1, school_name: 'Alpha Primary', rwm_expected_pct: 82, ofsted_grade: 1, phase: 'Primary' } as never, { urn: 2, school_name: 'Beta Primary', rwm_expected_pct: 44, ofsted_grade: 3, phase: 'Primary' } as never, ], averages: { rwm_expected_pct: 63, attainment_8_score: null }, }; describe('PlaceView', () => { it('leads with an H1 that matches how the place is searched', () => { render(); expect(screen.getByRole('heading', { level: 1 })) .toHaveTextContent(/primary schools in brentwood/i); }); it('states the count so the page says something before the table', () => { render(); expect(screen.getByText(/29 schools/i)).toBeInTheDocument(); }); it('compares the local average against England, which a list cannot', () => { render(); expect(screen.getByTestId('local-vs-england')).toHaveTextContent('63'); expect(screen.getByTestId('local-vs-england')).toHaveTextContent('61'); }); it('links every school in scope, which is what de-orphans them', () => { render(); expect(screen.getAllByRole('link', { name: /Primary$/ })).toHaveLength(2); }); it('links to the parent authority so the place sits in a hierarchy', () => { render(); expect(screen.getByRole('link', { name: /Essex/i })) .toHaveAttribute('href', '/schools/authority/essex'); }); it('shows the Ofsted distribution, not just a count of Outstanding', () => { render(); expect(screen.getByTestId('ofsted-distribution')).toBeInTheDocument(); }); it('links to neighbouring places so the page is not a dead end', () => { render(); expect(screen.getByRole('link', { name: /Romford/ })) .toHaveAttribute('href', '/schools/romford'); }); it('says nothing about an average it does not have', () => { render(); expect(screen.queryByTestId('local-vs-england')).not.toBeInTheDocument(); }); }); describe('PlaceView structured data', () => { function jsonLd() { const { container } = render(); const el = container.querySelector('script[type="application/ld+json"]'); return JSON.parse(el!.textContent!); } it('declares the page as a ranked list, not prose', () => { const types = jsonLd()['@graph'].map((n: { '@type': string }) => n['@type']); expect(types).toContain('ItemList'); expect(types).toContain('BreadcrumbList'); }); it('gives every listed school an absolute URL on the canonical host', () => { const list = jsonLd()['@graph'].find((n: { '@type': string }) => n['@type'] === 'ItemList'); expect(list.itemListElement).toHaveLength(2); for (const item of list.itemListElement) { expect(item.url).toMatch(/^https:\/\/www\.schoolcompare\.co\.uk\/school\//); } }); }); describe('PlaceView phase variants', () => { it('links the phase variants that exist', () => { render(); expect(screen.getByRole('link', { name: /Primary schools in Brentwood/i })) .toHaveAttribute('href', '/schools/brentwood/primary'); }); it('links no variant for a phase below its own threshold', () => { render(); expect(screen.queryByRole('link', { name: /Secondary schools in Brentwood/i })) .not.toBeInTheDocument(); }); it('does not link sideways from a variant page to itself', () => { render(); expect(screen.queryByRole('link', { name: /Primary schools in Brentwood/i })) .not.toBeInTheDocument(); }); }); describe('PlaceView presentation', () => { // /schools/brentwood shipped with 8 of 27 rows blank: an unphased page shows // one primary-only measure for a list that also holds secondaries. const mixed: PlaceDetail = { place: { kind: 'town', slug: 'brentwood', name: 'Brentwood', count: 4, parent_authority: 'Essex', phases: ['primary', 'secondary'] }, schools: [ { urn: 1, school_name: 'Alpha Primary', phase: 'Primary', rwm_expected_pct: 82, attainment_8_score: null } as never, { urn: 2, school_name: 'Beta High', phase: 'Secondary', rwm_expected_pct: null, attainment_8_score: 47 } as never, ], averages: { rwm_expected_pct: 63, attainment_8_score: 45 }, }; it('gives each phase its own table rather than one column of blanks', () => { render(); expect(screen.getByRole('heading', { name: /^Primary schools/ })).toBeInTheDocument(); expect(screen.getByRole('heading', { name: /^Secondary schools/ })).toBeInTheDocument(); expect(screen.getByText('82%')).toBeInTheDocument(); expect(screen.getByText('47')).toBeInTheDocument(); }); it('names the measure in plain words, not jargon', () => { // The first cut said "RWM expected", which appears nowhere else on the site. render(); expect(screen.getByText('Reading, writing & maths')).toBeInTheDocument(); expect(screen.getByText('Attainment 8')).toBeInTheDocument(); expect(screen.queryByText(/RWM expected/i)).not.toBeInTheDocument(); }); it('says a missing result is unpublished rather than showing a bare dash', () => { const noResult: PlaceDetail = { ...mixed, schools: [{ urn: 3, school_name: 'New Primary', phase: 'Primary', rwm_expected_pct: null, attainment_8_score: null } as never], }; render(); expect(screen.getByText('Not published')).toBeInTheDocument(); }); it('styles school links to the site convention rather than browser default', () => { const { container } = render(); const link = container.querySelector('a[href^="/school/"]'); expect(link?.className).toBeTruthy(); }); it('a phased page shows one table and no phase headings', () => { render(); expect(screen.queryByRole('heading', { name: /^Secondary schools/ })) .not.toBeInTheDocument(); }); });