Merge pull request 'fix(e2e): scope the Distance-tab assertion, and separate the tile figures' (#106) from fix/e2e-distance-locator into main
Stage (build -> staging -> E2E gate) / Build Backend (FastAPI) (push) Successful in 13s
Stage (build -> staging -> E2E gate) / Build Frontend (Next.js) (push) Successful in 50s
Stage (build -> staging -> E2E gate) / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Stage (build -> staging -> E2E gate) / Deploy to Staging (push) Successful in 1s
Stage (build -> staging -> E2E gate) / E2E Journeys against Staging (push) Successful in 1m26s
Stage (build -> staging -> E2E gate) / Build Backend (FastAPI) (push) Successful in 13s
Stage (build -> staging -> E2E gate) / Build Frontend (Next.js) (push) Successful in 50s
Stage (build -> staging -> E2E gate) / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Stage (build -> staging -> E2E gate) / Deploy to Staging (push) Successful in 1s
Stage (build -> staging -> E2E gate) / E2E Journeys against Staging (push) Successful in 1m26s
Reviewed-on: #106
This commit was merged in pull request #106.
This commit is contained in:
commit
8f211577c8
4 files changed
+46
-5
No files matched your search
@@ -1252,7 +1252,11 @@ test('a published cut-off distance is shown with the year it belongs to', async
|
|||||||
await expect(label).toContainText(`September ${found!.distance.year}`);
|
await expect(label).toContainText(`September ${found!.distance.year}`);
|
||||||
|
|
||||||
// And the figure itself, in the unit councils publish in.
|
// And the figure itself, in the unit councils publish in.
|
||||||
await expect(page.getByText(/\d+(\.\d+)? (miles|m)\b/).first()).toBeVisible();
|
// No trailing \b: the tile's support figure is an adjacent text node, so
|
||||||
|
// the element reads "0.88 miles 1.4 km" and a word boundary after "miles"
|
||||||
|
// is not guaranteed. The leading shape is what matters — a decimal figure
|
||||||
|
// in miles, never a metric one.
|
||||||
|
await expect(page.getByText(/\d+\.\d+ miles/).first()).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('a cut-off distance is never shown without saying it is not a catchment', async ({ page }) => {
|
test('a cut-off distance is never shown without saying it is not a catchment', async ({ page }) => {
|
||||||
@@ -1340,7 +1344,27 @@ test('a school page shows no year-by-year cut-off record', async ({ page }) => {
|
|||||||
// history back without the API.
|
// history back without the API.
|
||||||
await expect(page.getByText(/Last distance offered, by year/)).toHaveCount(0);
|
await expect(page.getByText(/Last distance offered, by year/)).toHaveCount(0);
|
||||||
await expect(page.getByText(/too few to read as a trend/)).toHaveCount(0);
|
await expect(page.getByText(/too few to read as a trend/)).toHaveCount(0);
|
||||||
await expect(page.getByRole('button', { name: 'Distance' })).toHaveCount(0);
|
|
||||||
|
/*
|
||||||
|
* No "Distance" tab in the admissions segmented control.
|
||||||
|
*
|
||||||
|
* Scoped to the control, and exact, because getByRole matches accessible
|
||||||
|
* names by case-insensitive SUBSTRING: an unscoped { name: 'Distance' }
|
||||||
|
* matched "Show this distance on a map" — the map toggle added by this same
|
||||||
|
* feature — and failed a page that was entirely correct. Naming the group
|
||||||
|
* this assertion is about also means unrelated copy elsewhere on the page
|
||||||
|
* can never break it again.
|
||||||
|
*/
|
||||||
|
const viewToggle = page.getByRole('group', { name: 'Admissions view' });
|
||||||
|
const tabs = await viewToggle.getByRole('button').allTextContents();
|
||||||
|
|
||||||
|
// Read the tabs positively rather than asserting an absence against a
|
||||||
|
// locator that might resolve to nothing: if the group selector ever stops
|
||||||
|
// matching, an absence check passes for the wrong reason, which is how the
|
||||||
|
// bug this test is guarding would slip back in unnoticed.
|
||||||
|
expect(tabs, 'admissions view toggle did not resolve').toContain('This year');
|
||||||
|
expect(tabs.map((s) => s.trim()), `admissions tabs: ${tabs.join(', ')}`)
|
||||||
|
.not.toContain('Distance');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('the postcode check answers for the published year, and names it', async ({ page }) => {
|
test('the postcode check answers for the published year, and names it', async ({ page }) => {
|
||||||
@@ -1354,7 +1378,7 @@ test('the postcode check answers for the published year, and names it', async ({
|
|||||||
await expect(section).toBeVisible({ timeout: 15_000 });
|
await expect(section).toBeVisible({ timeout: 15_000 });
|
||||||
|
|
||||||
await page.getByLabel('Your postcode').fill('SW1A 1AA');
|
await page.getByLabel('Your postcode').fill('SW1A 1AA');
|
||||||
await page.getByRole('button', { name: 'Check' }).click();
|
await page.getByRole('button', { name: 'Check', exact: true }).click();
|
||||||
|
|
||||||
const result = page.getByRole('status');
|
const result = page.getByRole('status');
|
||||||
const error = page.getByRole('alert');
|
const error = page.getByRole('alert');
|
||||||
|
|||||||
@@ -30,6 +30,17 @@ describe('primary detail page', () => {
|
|||||||
expect(screen.getByText(/Last distance offered/)).toHaveTextContent('September 2024');
|
expect(screen.getByText(/Last distance offered/)).toHaveTextContent('September 2024');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps the figure and its metric support readable as two numbers', () => {
|
||||||
|
// They are flex children with a CSS gap and nothing between them in the
|
||||||
|
// text layer, which read as "0.48 miles770 m" to a screen reader and to any
|
||||||
|
// text matcher. Cheap to lose again, so pinned.
|
||||||
|
renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff({ distance_m: 772.49 }) });
|
||||||
|
|
||||||
|
const tile = document.querySelector('[class*="admissionsTileDistance"]')!;
|
||||||
|
expect(tile.textContent).toMatch(/0\.48 miles\s+770 m/);
|
||||||
|
expect(tile.textContent).not.toMatch(/miles\d/);
|
||||||
|
});
|
||||||
|
|
||||||
it('never shows the figure without saying it is not a catchment', () => {
|
it('never shows the figure without saying it is not a catchment', () => {
|
||||||
renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff() });
|
renderSchoolDetail({ ...primaryFixture, admissionDistance: cutoff() });
|
||||||
|
|
||||||
|
|||||||
@@ -70,10 +70,16 @@ export function AdmissionsSection({
|
|||||||
{/* Spans both columns rather than taking a half-width cell. This is the
|
{/* Spans both columns rather than taking a half-width cell. This is the
|
||||||
figure parents come to the page for, and at tile width the two-line
|
figure parents come to the page for, and at tile width the two-line
|
||||||
"0.31 miles / September 2025" pairing wraps badly. */}
|
"0.31 miles / September 2025" pairing wraps badly. */}
|
||||||
|
{/* The {' '} between the figure and its metric support is not decoration.
|
||||||
|
The two are flex children, so the gap is drawn by CSS and the text layer
|
||||||
|
had nothing between them: textContent read "0.88 miles1.4 km", which is
|
||||||
|
what a screen reader announces and what any text matcher sees. Whitespace
|
||||||
|
text nodes are not rendered as flex items, so this changes the reading
|
||||||
|
without changing the layout. */}
|
||||||
const distanceTile = cutoff && (
|
const distanceTile = cutoff && (
|
||||||
<div className={`${styles.admissionsTile} ${styles.admissionsTileDistance}`}>
|
<div className={`${styles.admissionsTile} ${styles.admissionsTileDistance}`}>
|
||||||
<dd className={styles.admissionsTileNum}>
|
<dd className={styles.admissionsTileNum}>
|
||||||
{cutoff.primary}
|
{cutoff.primary}{' '}
|
||||||
<span className={styles.admissionsTileSub}>{cutoff.secondary}</span>
|
<span className={styles.admissionsTileSub}>{cutoff.secondary}</span>
|
||||||
</dd>
|
</dd>
|
||||||
<dt className={styles.admissionsTileLabel}>
|
<dt className={styles.admissionsTileLabel}>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export function SecondaryAdmissionsSection({
|
|||||||
Last distance offered · {cutoff.entryYear}
|
Last distance offered · {cutoff.entryYear}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.metricValue}>
|
<div className={styles.metricValue}>
|
||||||
{cutoff.primary}
|
{cutoff.primary}{' '}
|
||||||
<span className={styles.metricValueSub}>{cutoff.secondary}</span>
|
<span className={styles.metricValueSub}>{cutoff.secondary}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user