# 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/entity-graph.spec.ts >> entity-graph pop-over >> opens and draws on /candidates/a8897257-430c-2bf3-4498-349021b09ca3/
- Location: tests/ui/entity-graph.spec.ts:62:9

# Error details

```
Test timeout of 30000ms exceeded.
```

```
Error: expect(locator).toBeVisible() failed

Locator: locator('dialog.eg-dialog').locator('.eg-canvas canvas').first()
Expected: visible
Error: element(s) not found

Call log:
  - Expect "toBeVisible" locator('dialog.eg-dialog').locator('.eg-canvas canvas').first() with timeout 60000ms
  - waiting for locator('dialog.eg-dialog').locator('.eg-canvas canvas').first()
  - Test timeout of 30000ms exceeded.

```

```yaml
- banner:
  - heading "HARRIS, KAMALA" [level=1]
  - paragraph: Democratic Party candidate for President of the United States
  - paragraph: "FEC ID: P00009423"
  - button "Graph"
- link "Log In":
  - /url: /outpost.goauthentik.io/start?rd=http%3A%2F%2Fpreview-us-elect-info.electinfo.svc.cluster.local%2Fcandidates%2Fa8897257-430c-2bf3-4498-349021b09ca3%2F
- heading "Profile" [level=2]
- term: Party
- definition:
  - link "Democratic Party":
    - /url: https://preview.elect.info/parties/democratic/
- term: Office
- definition:
  - link "President of the United States":
    - /url: https://preview.elect.info/offices/president/
- term: Status
- definition: Prior Candidate (Not Current) (Challenger)
- term: Home Location
- definition: PHILADELPHIA, Pennsylvania 19102
- heading "Campaign Timeline" [level=2]
- term: Election Years
- definition:
  - link "2026":
    - /url: https://preview.elect.info/elections/2026/
  - text: ","
  - link "2024":
    - /url: https://preview.elect.info/elections/2024/
  - text: ","
  - link "2022":
    - /url: https://preview.elect.info/elections/2022/
  - text: ","
  - link "2020":
    - /url: https://preview.elect.info/elections/2020/
- term: First Campaign
- definition: "2020"
- term: Most Recent
- definition: "2024"
- heading "Campaign Funding" [level=2]
- term: Total Received
- definition:
  - strong: $4.6M
- term: Contributing Committees
- definition: "6715"
- heading "Top Contributors" [level=3]
- table:
  - rowgroup:
    - row "Committee Amount Contributions Cycles":
      - columnheader "Committee"
      - columnheader "Amount"
      - columnheader "Contributions"
      - columnheader "Cycles"
  - rowgroup:
    - row "DNC SERVICES CORP / DEMOCRATIC NATIONAL COMMITTEE $3.8M 39 2024, 2026":
      - cell "DNC SERVICES CORP / DEMOCRATIC NATIONAL COMMITTEE":
        - link "DNC SERVICES CORP / DEMOCRATIC NATIONAL COMMITTEE":
          - /url: https://preview.elect.info/committees/dnc-services-corp-democratic-national-committee-c00010603/
      - cell "$3.8M"
      - cell "39"
      - cell "2024, 2026":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
        - text: ","
        - link "2026":
          - /url: https://preview.elect.info/elections/2026/
    - row "ALPHA KAPPA ALPHA SORORITY PAC, INC. (AKA AKA 1908 PAC) $457K 6,403 2024":
      - cell "ALPHA KAPPA ALPHA SORORITY PAC, INC. (AKA AKA 1908 PAC)":
        - link "ALPHA KAPPA ALPHA SORORITY PAC, INC. (AKA AKA 1908 PAC)":
          - /url: https://preview.elect.info/committees/alpha-kappa-alpha-sorority-pac-inc-aka-aka-1908-pac-c00886036/
      - cell "$457K"
      - cell "6,403"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "PROGRESSIVE VICTORY PAC $49K 3 2024":
      - cell "PROGRESSIVE VICTORY PAC":
        - link "PROGRESSIVE VICTORY PAC":
          - /url: https://preview.elect.info/committees/progressive-victory-pac-c00821348/
      - cell "$49K"
      - cell "3"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "DEMOCRATIC WOMEN OF SANTA BARBARA COUNTY $20K 1 2024":
      - cell "DEMOCRATIC WOMEN OF SANTA BARBARA COUNTY":
        - link "DEMOCRATIC WOMEN OF SANTA BARBARA COUNTY":
          - /url: https://preview.elect.info/committees/democratic-women-of-santa-barbara-county-c00399444/
      - cell "$20K"
      - cell "1"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "JSTREETPAC $17K 88 2024":
      - cell "JSTREETPAC":
        - link "JSTREETPAC":
          - /url: https://preview.elect.info/committees/jstreetpac-c00441949/
      - cell "$17K"
      - cell "88"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "MI FAMILIA DECIDE PAC $10K 1 2024":
      - cell "MI FAMILIA DECIDE PAC":
        - link "MI FAMILIA DECIDE PAC":
          - /url: https://preview.elect.info/committees/mi-familia-decide-pac-c00882019/
      - cell "$10K"
      - cell "1"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "PLANNED PARENTHOOD ACTION FUND INC PAC, DBA PLANNED PARENTHOOD FEDERAL PAC $8K 25 2024":
      - cell "PLANNED PARENTHOOD ACTION FUND INC PAC, DBA PLANNED PARENTHOOD FEDERAL PAC":
        - link "PLANNED PARENTHOOD ACTION FUND INC PAC, DBA PLANNED PARENTHOOD FEDERAL PAC":
          - /url: https://preview.elect.info/committees/planned-parenthood-action-fund-inc-pac-dba-planned-parenthood-federal-pac-c00314617/
      - cell "$8K"
      - cell "25"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "TOM STEYER 2020 $8K 2 2020":
      - cell "TOM STEYER 2020":
        - link "TOM STEYER 2020":
          - /url: https://preview.elect.info/committees/tom-steyer-2020-c00711614/
      - cell "$8K"
      - cell "2"
      - cell "2020":
        - link "2020":
          - /url: https://preview.elect.info/elections/2020/
    - row "PROFESSIONAL ENGINEERS IN CALIFORNIA GOVERNMENT FEDERAL PAC (PECG FED-PAC) $8K 4 2024, 2020":
      - cell "PROFESSIONAL ENGINEERS IN CALIFORNIA GOVERNMENT FEDERAL PAC (PECG FED-PAC)":
        - link "PROFESSIONAL ENGINEERS IN CALIFORNIA GOVERNMENT FEDERAL PAC (PECG FED-PAC)":
          - /url: https://preview.elect.info/committees/professional-engineers-in-california-government-federal-pac-pecg-fed-pac-c00459800/
      - cell "$8K"
      - cell "4"
      - cell "2024, 2020":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
        - text: ","
        - link "2020":
          - /url: https://preview.elect.info/elections/2020/
    - row "END CITIZENS UNITED $6K 5 2024, 2020":
      - cell "END CITIZENS UNITED":
        - link "END CITIZENS UNITED":
          - /url: https://preview.elect.info/committees/end-citizens-united-c00573261/
      - cell "$6K"
      - cell "5"
      - cell "2024, 2020":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
        - text: ","
        - link "2020":
          - /url: https://preview.elect.info/elections/2020/
- paragraph: Showing top 10 of 78
- heading "Independent Expenditures Supporting" [level=2]
- paragraph: Spending by outside groups for this candidate, made independently of the campaign. Not a contribution to the campaign.
- table:
  - rowgroup:
    - row "Committee Amount Contributions Cycles":
      - columnheader "Committee"
      - columnheader "Amount"
      - columnheader "Contributions"
      - columnheader "Cycles"
  - rowgroup:
    - row "FF PAC $443.5M 362 2024":
      - cell "FF PAC":
        - link "FF PAC":
          - /url: https://preview.elect.info/committees/ff-pac-c00669259/
      - cell "$443.5M"
      - cell "362"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "BLACKPAC $19.1M 89 2024":
      - cell "BLACKPAC":
        - link "BLACKPAC":
          - /url: https://preview.elect.info/committees/blackpac-c00609388/
      - cell "$19.1M"
      - cell "89"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "LF PAC $14.4M 349 2024":
      - cell "LF PAC":
        - link "LF PAC":
          - /url: https://preview.elect.info/committees/lf-pac-c00804856/
      - cell "$14.4M"
      - cell "349"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "YOUR COMMUNITY PAC $12.7M 17 2024":
      - cell "YOUR COMMUNITY PAC":
        - link "YOUR COMMUNITY PAC":
          - /url: https://preview.elect.info/committees/your-community-pac-c00886614/
      - cell "$12.7M"
      - cell "17"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "SOMOS PAC $12.3M 113 2024":
      - cell "SOMOS PAC":
        - link "SOMOS PAC":
          - /url: https://preview.elect.info/committees/somos-pac-c00724203/
      - cell "$12.3M"
      - cell "113"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "ONE FOR ALL COMMITTEE $10.3M 24 2024":
      - cell "ONE FOR ALL COMMITTEE":
        - link "ONE FOR ALL COMMITTEE":
          - /url: https://preview.elect.info/committees/one-for-all-committee-c00752691/
      - cell "$10.3M"
      - cell "24"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "CFFE PAC $7.3M 79 2024":
      - cell "CFFE PAC":
        - link "CFFE PAC":
          - /url: https://preview.elect.info/committees/cffe-pac-c00744920/
      - cell "$7.3M"
      - cell "79"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "LCV VICTORY FUND $6.5M 117 2024":
      - cell "LCV VICTORY FUND":
        - link "LCV VICTORY FUND":
          - /url: https://preview.elect.info/committees/lcv-victory-fund-c00486845/
      - cell "$6.5M"
      - cell "117"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "NATIONAL NURSES UNITED FOR PATIENT PROTECTION $4.8M 50 2024, 2026":
      - cell "NATIONAL NURSES UNITED FOR PATIENT PROTECTION":
        - link "NATIONAL NURSES UNITED FOR PATIENT PROTECTION":
          - /url: https://preview.elect.info/committees/national-nurses-united-for-patient-protection-c00490375/
      - cell "$4.8M"
      - cell "50"
      - cell "2024, 2026":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
        - text: ","
        - link "2026":
          - /url: https://preview.elect.info/elections/2026/
    - row "SEIU COPE (SERVICE EMPLOYEES INTERNATIONAL UNION COMMITTEE ON POLITICAL EDUCATION) $4.1M 90 2024, 2026":
      - cell "SEIU COPE (SERVICE EMPLOYEES INTERNATIONAL UNION COMMITTEE ON POLITICAL EDUCATION)":
        - link "SEIU COPE (SERVICE EMPLOYEES INTERNATIONAL UNION COMMITTEE ON POLITICAL EDUCATION)":
          - /url: https://preview.elect.info/committees/seiu-cope-service-employees-international-union-committee-on-political-education-c00004036/
      - cell "$4.1M"
      - cell "90"
      - cell "2024, 2026":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
        - text: ","
        - link "2026":
          - /url: https://preview.elect.info/elections/2026/
- paragraph: Showing top 10 of 292
- heading "Independent Expenditures Opposing" [level=2]
- paragraph: Spending by outside groups against this candidate, made independently of any campaign.
- table:
  - rowgroup:
    - row "Committee Amount Contributions Cycles":
      - columnheader "Committee"
      - columnheader "Amount"
      - columnheader "Contributions"
      - columnheader "Cycles"
  - rowgroup:
    - row "MAKE AMERICA GREAT AGAIN INC. $251.8M 119 2024":
      - cell "MAKE AMERICA GREAT AGAIN INC.":
        - link "MAKE AMERICA GREAT AGAIN INC.":
          - /url: https://preview.elect.info/committees/make-america-great-again-inc-c00825851/
      - cell "$251.8M"
      - cell "119"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "PRESERVE AMERICA PAC $112.3M 29 2024":
      - cell "PRESERVE AMERICA PAC":
        - link "PRESERVE AMERICA PAC":
          - /url: https://preview.elect.info/committees/preserve-america-pac-c00878801/
      - cell "$112.3M"
      - cell "29"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "AMERICA PAC $54.2M 212 2024":
      - cell "AMERICA PAC":
        - link "AMERICA PAC":
          - /url: https://preview.elect.info/committees/america-pac-c00879510/
      - cell "$54.2M"
      - cell "212"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "RIGHT FOR AMERICA $51.1M 34 2024":
      - cell "RIGHT FOR AMERICA":
        - link "RIGHT FOR AMERICA":
          - /url: https://preview.elect.info/committees/right-for-america-c00867036/
      - cell "$51.1M"
      - cell "34"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "RESTORATION OF AMERICA PAC $27.0M 23 2024":
      - cell "RESTORATION OF AMERICA PAC":
        - link "RESTORATION OF AMERICA PAC":
          - /url: https://preview.elect.info/committees/restoration-of-america-pac-c00571588/
      - cell "$27.0M"
      - cell "23"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "DUTY TO AMERICA PAC $23.2M 36 2024":
      - cell "DUTY TO AMERICA PAC":
        - link "DUTY TO AMERICA PAC":
          - /url: https://preview.elect.info/committees/duty-to-america-pac-c00881987/
      - cell "$23.2M"
      - cell "36"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "RJC VICTORY FUND $10.0M 18 2024":
      - cell "RJC VICTORY FUND":
        - link "RJC VICTORY FUND":
          - /url: https://preview.elect.info/committees/rjc-victory-fund-c00528554/
      - cell "$10.0M"
      - cell "18"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "BUCKEYE VALUES PAC $5.6M 5 2024":
      - cell "BUCKEYE VALUES PAC":
        - link "BUCKEYE VALUES PAC":
          - /url: https://preview.elect.info/committees/buckeye-values-pac-c00834630/
      - cell "$5.6M"
      - cell "5"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "WOMEN SPEAK OUT PAC $2.6M 69 2024":
      - cell "WOMEN SPEAK OUT PAC":
        - link "WOMEN SPEAK OUT PAC":
          - /url: https://preview.elect.info/committees/women-speak-out-pac-c00530766/
      - cell "$2.6M"
      - cell "69"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
    - row "MAHA ALLIANCE $2.0M 15 2024":
      - cell "MAHA ALLIANCE":
        - link "MAHA ALLIANCE":
          - /url: https://preview.elect.info/committees/maha-alliance-c00888172/
      - cell "$2.0M"
      - cell "15"
      - cell "2024":
        - link "2024":
          - /url: https://preview.elect.info/elections/2024/
- paragraph: Showing top 10 of 79
- contentinfo:
  - paragraph:
    - link "elect.info":
      - /url: https://preview.elect.info/
    - text: "| Data from"
    - link "Federal Election Commission":
      - /url: https://preview.elect.info/datasources/fec_bulk/
    - text: "| Generated 2026-10-13"
- 'dialog "HARRIS, KAMALA: graph of connected entities"':
  - heading "HARRIS, KAMALA — connected entities" [level=2]
  - button "Fit"
  - button "Close graph": Close
  - img "Network graph of HARRIS, KAMALA and its most significant connections": The graph could not be loaded. Please try again later.
  - text: Committee Candidate Vendor Party State / place Office Cycle Committees and candidates are tinted by party
```

# Test source

```ts
  1  | import { test, expect } from '@playwright/test';
  2  | 
  3  | // Entity graph pop-over (electinfo/sites#249). nginx injects /js/entity-graph.js
  4  | // next to money-flow.js on Candidate and Committee detail pages. The script
  5  | // adds a "Graph" button to the header; opening it fetches entityGraph from
  6  | // /api/graphql, loads /js/entity-graph-view.js (Cytoscape) and draws the node
  7  | // and its most significant neighbours in a modal dialog.
  8  | //
  9  | // Same targets and pages as money-flow.spec.ts.
  10 | 
  11 | const SCRIPT = '<script src="/js/entity-graph.js" defer></script>';
  12 | const DNC = '/committees/a75a9110-f1db-a945-39a8-7503ed3c04da/'; // C00010603
  13 | const HARRIS = '/candidates/a8897257-430c-2bf3-4498-349021b09ca3/'; // P00009423
  14 | const OTHER_PAGES = [
  15 |   '/states/032f8d61-f554-f435-2a6d-50b3c8cc01d7/', // AK
  16 |   '/elections/2024/',
  17 |   '/offices/president/',
  18 | ];
  19 | 
  20 | test.describe('entity-graph script injection', () => {
  21 |   for (const path of [DNC, HARRIS]) {
  22 |     test(`injected once on ${path}`, async ({ request }) => {
  23 |       const res = await request.get(path);
  24 |       expect(res.status()).toBe(200);
  25 |       expect((await res.text()).split(SCRIPT).length - 1).toBe(1);
  26 |     });
  27 |   }
  28 | 
  29 |   for (const path of OTHER_PAGES) {
  30 |     test(`not injected on ${path}`, async ({ request }) => {
  31 |       const res = await request.get(path);
  32 |       expect(res.status()).toBe(200);
  33 |       expect(await res.text()).not.toContain('entity-graph.js');
  34 |     });
  35 |   }
  36 | });
  37 | 
  38 | test.describe('entityGraph API', () => {
  39 |   for (const fecId of ['C00010603', 'P00009423']) {
  40 |     test(`${fecId}: neighbours without individuals, money edges with amounts`, async ({ request }) => {
  41 |       const res = await request.post('/api/graphql', {
  42 |         data: {
  43 |           query: 'query($f: String!) { entityGraph(fecId: $f) { focalId nodes { id label labels focal displayName } edges { type amount } } }',
  44 |           variables: { f: fecId },
  45 |         },
  46 |         timeout: 60000,
  47 |       });
  48 |       expect(res.status()).toBe(200);
  49 |       const g = (await res.json())?.data?.entityGraph;
  50 |       expect(g).toBeTruthy();
  51 |       expect(g.nodes.filter((n: { focal: boolean }) => n.focal)).toHaveLength(1);
  52 |       expect(g.nodes.length).toBeGreaterThan(5);
  53 |       expect(g.nodes.some((n: { labels: string[] }) => n.labels.includes('Individual'))).toBe(false);
  54 |       expect(g.nodes.every((n: { displayName: string }) => !!n.displayName)).toBe(true);
  55 |       expect(g.edges.some((e: { amount: number | null }) => e.amount != null && e.amount > 0)).toBe(true);
  56 |     });
  57 |   }
  58 | });
  59 | 
  60 | test.describe('entity-graph pop-over', () => {
  61 |   for (const path of [DNC, HARRIS]) {
  62 |     test(`opens and draws on ${path}`, async ({ page }) => {
  63 |       const errors: string[] = [];
  64 |       page.on('pageerror', (e) => errors.push(String(e)));
  65 |       await page.goto(path);
  66 |       const button = page.locator('button.eg-open');
  67 |       await expect(button).toHaveCount(1, { timeout: 15000 });
  68 |       await button.click();
  69 |       const dialog = page.locator('dialog.eg-dialog');
  70 |       await expect(dialog).toBeVisible();
> 71 |       await expect(dialog.locator('.eg-canvas canvas').first()).toBeVisible({ timeout: 60000 });
     |                                                                 ^ Error: expect(locator).toBeVisible() failed
  72 |       // centred in the viewport, horizontally and vertically
  73 |       const box = (await dialog.boundingBox())!;
  74 |       const vp = page.viewportSize()!;
  75 |       expect(Math.abs(box.x - (vp.width - box.x - box.width))).toBeLessThanOrEqual(2);
  76 |       expect(Math.abs(box.y - (vp.height - box.y - box.height))).toBeLessThanOrEqual(2);
  77 |       await page.keyboard.press('Escape');
  78 |       await expect(dialog).toBeHidden();
  79 |       expect(errors).toEqual([]);
  80 |     });
  81 |   }
  82 | });
  83 | 
```