# Instructions

- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.

# Test info

- Name: tests/ui/district-delegates.spec.ts >> GU delegate district has a current00 canonical and historical98 redirect
- Location: tests/ui/district-delegates.spec.ts:11:7

# Error details

```
Error: GU:98 must redirect rather than retire or retain an old owner

expect(received).toBe(expected) // Object.is equality

Expected: 301
Received: 410
```

# Page snapshot

```yaml
- generic [active] [ref=f1e1]:
  - banner [ref=f1e2]:
    - heading "Guam At-Large Congressional District" [level=1] [ref=f1e3]
    - paragraph [ref=f1e4]: Congressional District Profile
  - generic [ref=f1e5]:
    - generic [ref=f1e6]:
      - generic [ref=f1e7]: Not signed in
      - generic [ref=f1e9]:
        - link "Log in" [ref=f1e10] [cursor=pointer]:
          - /url: /outpost.goauthentik.io/start?rd=https%3A%2F%2Fus.elect.info%2Fdistricts%2Fgu-00%2F
        - link "Create an account" [ref=f1e11] [cursor=pointer]:
          - /url: /signin/register?rd=https%3A%2F%2Fus.elect.info%2Fdistricts%2Fgu-00%2F
    - toolbar "Member tools" [ref=f1e12]:
      - button "All cycles (Sign in to use the cycle facet)" [disabled] [ref=f1e13] [cursor=pointer]:
        - generic [ref=f1e17]: All cycles
      - button "Graph (Sign in to use Graph)" [disabled] [ref=f1e20] [cursor=pointer]:
        - generic [ref=f1e29]: Graph
  - generic [ref=f1e32]:
    - heading "Overview" [level=2] [ref=f1e33]
    - generic [ref=f1e34]:
      - term [ref=f1e35]: District ID
      - definition [ref=f1e36]: GU-00
      - term [ref=f1e37]: State
      - definition [ref=f1e38]:
        - link "Guam" [ref=f1e39] [cursor=pointer]:
          - /url: https://us.elect.info/states/
      - term [ref=f1e40]: District Number
      - definition [ref=f1e41]: "00"
      - term [ref=f1e42]: Total Candidates
      - definition [ref=f1e43]: "30"
      - term [ref=f1e44]: Election Cycles
      - definition [ref=f1e45]:
        - generic [ref=f1e46]:
          - link "2026" [ref=f1e47] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2026/
          - text: ","
          - link "2024" [ref=f1e48] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2024/
          - text: ","
          - link "2022" [ref=f1e49] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2022/
          - text: ","
          - link "2020" [ref=f1e50] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2020/
          - text: ","
          - link "2018" [ref=f1e51] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2018/
          - text: ","
          - link "2016" [ref=f1e52] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2016/
          - text: ","
          - link "2014" [ref=f1e53] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2014/
          - text: ","
          - link "2012" [ref=f1e54] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2012/
          - text: ","
          - link "2010" [ref=f1e55] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2010/
          - text: ","
          - link "2008" [ref=f1e56] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2008/
          - text: ","
          - link "2006" [ref=f1e57] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2006/
          - text: ","
          - link "2004" [ref=f1e58] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2004/
          - text: ","
          - link "2002" [ref=f1e59] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2002/
          - text: ","
          - link "2000" [ref=f1e60] [cursor=pointer]:
            - /url: https://us.elect.info/elections/2000/
          - text: ","
          - link "1998" [ref=f1e61] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1998/
          - text: ","
          - link "1996" [ref=f1e62] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1996/
          - text: ","
          - link "1994" [ref=f1e63] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1994/
          - text: ","
          - link "1992" [ref=f1e64] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1992/
          - text: ","
          - link "1990" [ref=f1e65] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1990/
          - text: ","
          - link "1988" [ref=f1e66] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1988/
          - text: ","
          - link "1986" [ref=f1e67] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1986/
          - text: ","
          - link "1984" [ref=f1e68] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1984/
          - text: ","
          - link "1982" [ref=f1e69] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1982/
          - text: ","
          - link "1980" [ref=f1e70] [cursor=pointer]:
            - /url: https://us.elect.info/elections/1980/
    - paragraph [ref=f1e71]:
      - link "View office details for U.S. Representative - Guam District 00" [ref=f1e72] [cursor=pointer]:
        - /url: https://us.elect.info/offices/house/gu-00/
  - generic [ref=f1e73]:
    - heading "Candidates" [level=2] [ref=f1e74]
    - generic [ref=f1e76]:
      - generic [ref=f1e77]:
        - generic [ref=f1e78]:
          - combobox "Search entities" [ref=f1e79]
          - status [ref=f1e80]
        - button "Search" [ref=f1e81] [cursor=pointer]
      - generic [ref=f1e82]:
        - heading "Candidates" [level=3] [ref=f1e84]
        - generic [ref=f1e85]:
          - link "BORDALLO, MADELEINE Z. MS. DEM | $273,910" [ref=f1e86] [cursor=pointer]:
            - /url: /politicians/9adc7fde-f37d-b364-14e1-3d367dd754c9/
            - generic [ref=f1e87]: BORDALLO, MADELEINE Z. MS.
            - generic [ref=f1e88]: DEM | $273,910
          - link "MOYLAN, JAMES C. REP | $126,700" [ref=f1e89] [cursor=pointer]:
            - /url: /politicians/21533dbd-3c96-f859-917d-a58346aaad95/
            - generic [ref=f1e90]: MOYLAN, JAMES C.
            - generic [ref=f1e91]: REP | $126,700
          - link "BLAZ, BEN GARRIDO REP | $116,642" [ref=f1e92] [cursor=pointer]:
            - /url: /politicians/ab11e1ec-c4ca-565e-d370-8550c2aa5b11/
            - generic [ref=f1e93]: BLAZ, BEN GARRIDO
            - generic [ref=f1e94]: REP | $116,642
          - link "WON PAT, ANTONIO BORJA DEM | $32,651" [ref=f1e95] [cursor=pointer]:
            - /url: /politicians/9bcc0622-2fa2-5a17-dbdf-0a58e44da371/
            - generic [ref=f1e96]: WON PAT, ANTONIO BORJA
            - generic [ref=f1e97]: DEM | $32,651
          - link "SAN NICOLAS, MICHAEL F.Q. MR. DEM | $26,500" [ref=f1e98] [cursor=pointer]:
            - /url: /politicians/1e2ef26f-24f1-1d1c-7ba4-f892956bdc48/
            - generic [ref=f1e99]: SAN NICOLAS, MICHAEL F.Q. MR.
            - generic [ref=f1e100]: DEM | $26,500
          - link "UNDERWOOD, ROBERT ANACLETUS DEM | $23,248" [ref=f1e101] [cursor=pointer]:
            - /url: /politicians/80b000e0-d9b1-7cda-2550-580b54663ab4/
            - generic [ref=f1e102]: UNDERWOOD, ROBERT ANACLETUS
            - generic [ref=f1e103]: DEM | $23,248
          - link "CRUZ, GINGER DEM | $7,500" [ref=f1e104] [cursor=pointer]:
            - /url: /politicians/3876152d-e95a-9a3c-ee70-69bf639306d3/
            - generic [ref=f1e105]: CRUZ, GINGER
            - generic [ref=f1e106]: DEM | $7,500
          - link "PAT, JUDITH T WON DEM | $4,500" [ref=f1e107] [cursor=pointer]:
            - /url: /politicians/66bb4273-ac44-6874-2229-b06218c1b128/
            - generic [ref=f1e108]: PAT, JUDITH T WON
            - generic [ref=f1e109]: DEM | $4,500
          - link "BABAUTA, ANTHONY M DEM | $3,000" [ref=f1e110] [cursor=pointer]:
            - /url: /politicians/994a9c41-271e-daf5-d160-d5d0f5ebb77a/
            - generic [ref=f1e111]: BABAUTA, ANTHONY M
            - generic [ref=f1e112]: DEM | $3,000
          - link "TORRES, FRANK C JR DEM | $1,150" [ref=f1e113] [cursor=pointer]:
            - /url: /politicians/e42cb9a2-3593-a11b-bbd5-caa82bd9a39d/
            - generic [ref=f1e114]: TORRES, FRANK C JR
            - generic [ref=f1e115]: DEM | $1,150
          - link "CAMACHO, FELIX P GOVERNOR REP | $1,000" [ref=f1e116] [cursor=pointer]:
            - /url: /politicians/0b890987-c8ff-e75d-eb35-120003b30980/
            - generic [ref=f1e117]: CAMACHO, FELIX P GOVERNOR
            - generic [ref=f1e118]: REP | $1,000
          - link "UNDERWOOD, ROBERT ANACLETUS DEM | $1,000" [ref=f1e119] [cursor=pointer]:
            - /url: /politicians/c556d3d7-b670-8683-c884-9360d38fa8cf/
            - generic [ref=f1e120]: UNDERWOOD, ROBERT ANACLETUS
            - generic [ref=f1e121]: DEM | $1,000
          - link "PANGELINAN, VICENTE C DEM | $540" [ref=f1e122] [cursor=pointer]:
            - /url: /politicians/2261af50-171a-53a0-2a31-96e598e9a898/
            - generic [ref=f1e123]: PANGELINAN, VICENTE C
            - generic [ref=f1e124]: DEM | $540
          - link "BROOKS, DORIS FLORES REP | $500" [ref=f1e125] [cursor=pointer]:
            - /url: /politicians/3e2a79fa-0cba-b195-f603-fbe5854971e9/
            - generic [ref=f1e126]: BROOKS, DORIS FLORES
            - generic [ref=f1e127]: REP | $500
          - link "SHELTON, AMANDA LEE DEM | $500" [ref=f1e128] [cursor=pointer]:
            - /url: /politicians/147fa85e-96d0-1bf9-afd7-8bbb57e742d5/
            - generic [ref=f1e129]: SHELTON, AMANDA LEE
            - generic [ref=f1e130]: DEM | $500
          - link "BLAS, FRANK FLORES JR REP | $500" [ref=f1e131] [cursor=pointer]:
            - /url: /politicians/16fd0f34-5439-4c7e-91f6-cc21be2ec108/
            - generic [ref=f1e132]: BLAS, FRANK FLORES JR
            - generic [ref=f1e133]: REP | $500
          - link "CRUZ, MANUEL QUITUGUA REP | $300" [ref=f1e134] [cursor=pointer]:
            - /url: /politicians/da6e57fc-d882-ec7c-0773-484a4c7a2e74/
            - generic [ref=f1e135]: CRUZ, MANUEL QUITUGUA
            - generic [ref=f1e136]: REP | $300
          - link "PALOMO, ANTONIO M REP | $129" [ref=f1e137] [cursor=pointer]:
            - /url: /politicians/14f40306-26d8-7d37-8a2c-6839370df62e/
            - generic [ref=f1e138]: PALOMO, ANTONIO M
            - generic [ref=f1e139]: REP | $129
          - link "NELSON, TELENA C. DEM" [ref=f1e140] [cursor=pointer]:
            - /url: /politicians/168361fe-7420-ba9a-ecd1-f62856e09c48/
            - generic [ref=f1e141]: NELSON, TELENA C.
            - generic [ref=f1e142]: DEM
          - link "CASTRO, WILLIAM MENDIOLA REP" [ref=f1e143] [cursor=pointer]:
            - /url: /politicians/9b17a3c0-537e-ec68-2d13-9e7f02f8f7fe/
            - generic [ref=f1e144]: CASTRO, WILLIAM MENDIOLA
            - generic [ref=f1e145]: REP
          - link "LIN, ERIC DR. REP" [ref=f1e146] [cursor=pointer]:
            - /url: /politicians/a365fcac-8976-4ffd-510b-471613aacaf3/
            - generic [ref=f1e147]: LIN, ERIC DR.
            - generic [ref=f1e148]: REP
          - link "DIAZ, JONATHAN FRANK BLAS IND" [ref=f1e149] [cursor=pointer]:
            - /url: /politicians/3600a7b1-b51f-0283-7b00-768485569312/
            - generic [ref=f1e150]: DIAZ, JONATHAN FRANK BLAS
            - generic [ref=f1e151]: IND
          - link "LIMTIACO, ALICIA ANNE GARRIDO DEM" [ref=f1e152] [cursor=pointer]:
            - /url: /politicians/6155779b-7a54-fb20-e2ae-01e31e8567a4/
            - generic [ref=f1e153]: LIMTIACO, ALICIA ANNE GARRIDO
            - generic [ref=f1e154]: DEM
          - link "TREIBERT, JAMES K W" [ref=f1e155] [cursor=pointer]:
            - /url: /politicians/62508e77-00a8-917d-249a-bfe226532b0d/
            - generic [ref=f1e156]: TREIBERT, JAMES K
            - generic [ref=f1e157]: W
          - link "METCALFE, MARGARET REP" [ref=f1e158] [cursor=pointer]:
            - /url: /politicians/ad99d0d9-3ed9-1abd-1060-8a829b400e9d/
            - generic [ref=f1e159]: METCALFE, MARGARET
            - generic [ref=f1e160]: REP
          - link "ARTERO, MATTHEW PASCUAL DEM" [ref=f1e161] [cursor=pointer]:
            - /url: /politicians/13117bbb-5121-fa2f-15fb-5984466207a9/
            - generic [ref=f1e162]: ARTERO, MATTHEW PASCUAL
            - generic [ref=f1e163]: DEM
          - link "DIZON, KARLO ISAIAS JORGE DEM" [ref=f1e164] [cursor=pointer]:
            - /url: /politicians/eecec48d-b75f-905f-8a0f-10f4962d2531/
            - generic [ref=f1e165]: DIZON, KARLO ISAIAS JORGE
            - generic [ref=f1e166]: DEM
          - link "ADA, JOSEPH F REP" [ref=f1e167] [cursor=pointer]:
            - /url: /politicians/389bec82-1cf2-0379-3a21-ede961c3538f/
            - generic [ref=f1e168]: ADA, JOSEPH F
            - generic [ref=f1e169]: REP
          - link "WON PAT, JUDITH T PEREZ DEM" [ref=f1e170] [cursor=pointer]:
            - /url: /politicians/db07ef80-96ef-7b89-74af-c28250485d55/
            - generic [ref=f1e171]: WON PAT, JUDITH T PEREZ
            - generic [ref=f1e172]: DEM
        - generic [ref=f1e173]: Showing all 29 results
  - contentinfo [ref=f1e175]:
    - paragraph [ref=f1e176]:
      - link "elect.info" [ref=f1e177] [cursor=pointer]:
        - /url: https://us.elect.info/
      - text: "| Data from"
      - link "Federal Election Commission" [ref=f1e178] [cursor=pointer]:
        - /url: https://us.elect.info/datasources/fec.gov/
      - text: "| Generated 2026-10-23"
```

# Test source

```ts
  1  | import { test, expect } from '@playwright/test';
  2  | import { canonicalPath, toRelativePath } from './helpers';
  3  | 
  4  | // Release contract after the coordinated graph + PagePaths cutover (#462): all six
  5  | // delegates exist as current00 entities; the index and00 alias serve them, their
  6  | // live UUID pages canonicalize to00, and historical98 aliases redirect to00.
  7  | // This is intentionally red on the old98 graph / stale alias snapshot. The local
  8  | // district-categories fixture still proves98 rows keep safe current-UUID links;
  9  | // neither that fixture nor these inventory assertions may be skipped for missing rows.
  10 | for (const state of ['AS', 'GU', 'MP', 'VI', 'DC', 'PR']) {
  11 |   test(`${state} delegate district has a current00 canonical and historical98 redirect`, async ({ page, request }) => {
  12 |     const dataResponse = page.waitForResponse(response => {
  13 |       if (!response.url().includes('/api/graphql') || response.request().method() !== 'POST') return false;
  14 |       try {
  15 |         const body = response.request().postDataJSON();
  16 |         const variables = body?.variables;
  17 |         const filters = String(variables?.filter).split(',');
  18 |         return /\bbrowseEntities\s*\(/.test(body?.query || '') && variables?.entityType === 'District' &&
  19 |           filters.includes('district_type:cd') && filters.includes(`state:${state}`);
  20 |       } catch { return false; }
  21 |     });
  22 |     await page.goto(`/districts/?state=${state}&tab=congressional`);
  23 |     const payload = await (await dataResponse).json();
  24 |     expect(payload.errors, `${state}: current inventory query must succeed`).toBeUndefined();
  25 |     const inventory = payload.data?.browseEntities;
  26 |     expect(inventory?.total, `${state}: full congressional inventory must contain exactly one delegate`).toBe(1);
  27 |     expect(inventory?.hasMore, `${state}: delegate inventory must not be truncated`).toBe(false);
  28 |     const rows = inventory?.results;
  29 |     expect(rows, `${state}: exactly one delegate must remain in the graph`).toHaveLength(1);
  30 |     const row = rows[0];
  31 |     expect(row.state).toBe(state);
  32 |     expect(row.district).toBe('00');
  33 |     const metadata = JSON.parse(row.metadata || '{}');
  34 |     expect(metadata.district_type).toBe('cd');
  35 |     expect(metadata.district_slug.toLowerCase()).toBe(`${state.toLowerCase()}-00`);
  36 |     expect(row.id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
  37 | 
  38 |     await expect(page.locator('#district-state-select')).toHaveValue(state);
  39 |     const result = page.locator('.entity-search-result');
  40 |     await expect(result).toHaveCount(1, { timeout: 15000 });
  41 |     await expect(result).toContainText(`${state}-00`);
  42 |     const canonical = `/districts/${state.toLowerCase()}-00/`;
  43 |     await expect(result).toHaveAttribute('href', canonical);
  44 |     const response = await page.goto(canonical);
  45 |     expect(response?.status(), `${state}:00 must serve, not redirect or miss`).toBe(200);
  46 |     await expect(page.locator('h1')).toBeVisible();
  47 |     expect(canonicalPath(await page.content())).toBe(canonical);
  48 | 
  49 |     const storage = await request.get(`/districts/${row.id}/`, { maxRedirects: 0 });
  50 |     expect(storage.status(), `${state}: graph-current UUID page must serve`).toBe(200);
  51 |     expect(canonicalPath(await storage.text()), `${state}: current UUID must share00 canonical`).toBe(canonical);
  52 |     const historical = await request.get(`/districts/${state.toLowerCase()}-98/`, { maxRedirects: 0 });
> 53 |     expect(historical.status(), `${state}:98 must redirect rather than retire or retain an old owner`).toBe(301);
     |                                                                                                        ^ Error: GU:98 must redirect rather than retire or retain an old owner
  54 |     expect(toRelativePath(historical.headers()['location'] || '')).toBe(canonical);
  55 |   });
  56 | }
  57 | 
```