import { test, expect, Route } from '@playwright/test'; test('the deployed frontend and backend report the tested build', async ({ request }) => { const response = await request.get('/release.json'); expect(response.ok()).toBeTruthy(); expect(response.headers()['cache-control']).toContain('no-store'); const identity = await response.json(); expect(identity.frontend).toEqual(identity.backend); expect(identity.frontend.sha).toMatch(/^[a-f0-9]{40}$/); expect(identity.frontend.build_id).toMatch(/^[a-f0-9]{32}$/); if (process.env.EXPECTED_SHA) expect(identity.frontend.sha).toBe(process.env.EXPECTED_SHA); if (process.env.EXPECTED_BUILD_ID) expect(identity.frontend.build_id).toBe(process.env.EXPECTED_BUILD_ID); }); test('changing search while loading another page does not append old results', async ({ page }) => { await page.goto('/?phase=primary'); await expect(page.getByRole('button', { name: 'Load more schools' })).toBeVisible(); let received!: (route: Route) => void; const pending = new Promise(resolve => { received = resolve; }); await page.route('**/api/schools?**', async route => { if (new URL(route.request().url()).searchParams.get('page') === '2') { received(route); return; } await route.continue(); }); await page.getByRole('button', { name: 'Load more schools' }).click(); const oldRequest = await pending; const search = page.getByPlaceholder('School name or postcode').first(); await search.fill('secondary'); await search.press('Enter'); await page.waitForURL(/search=secondary/); // A cancelled fetch may prevent route fulfilment altogether; either way, // this deliberately late response must not become part of the new results. await oldRequest.fulfill({ json: { schools: [{ urn: 999998, school_name: 'P1 stale result sentinel', phase: 'Primary' }], total: 2, page: 2, page_size: 1, total_pages: 2, } }).catch(() => {}); await expect(page.getByText('P1 stale result sentinel')).toHaveCount(0); await expect(page.getByRole('button', { name: 'Loading...' })).toHaveCount(0); });