# 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 without accounts >> a host without Authentik keeps the header Graph button
- Location: tests/ui/entity-graph.spec.ts:218:7

# Error details

```
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://10.1.105.22/committees/a75a9110-f1db-a945-39a8-7503ed3c04da/
Call log:
  - navigating to "http://10.1.105.22/committees/a75a9110-f1db-a945-39a8-7503ed3c04da/", waiting until "load"

```

# Test source

```ts
  120 | });
  121 | 
  122 | /**
  123 |  * Where the host has accounts the graph is a member control in the identity bar
  124 |  * (sites#355), locked for anonymous visitors (preview's e2e run is anonymous);
  125 |  * the drawing tests sign in a mocked member. hosts without accounts keep the
  126 |  * header button (last test).
  127 |  */
  128 | async function asMember(page: import('@playwright/test').Page): Promise<void> {
  129 |   await page.route('**/auth/whoami*', r => r.fulfill({ json: { enabled: 'true', email: 'e2e-member@example.org', elevated: false, entitlements: {} } }));
  130 |   await page.route('**/auth/account/me*', r => r.fulfill({ json: { requests: [], agreement: null, granted: [] } }));
  131 | }
  132 | 
  133 | test.describe('entity-graph pop-over', () => {
  134 |   for (const path of [DNC, HARRIS]) {
  135 |     test(`opens and draws on ${path}`, async ({ page }) => {
  136 |       const errors: string[] = [];
  137 |       page.on('pageerror', (e) => errors.push(String(e)));
  138 |       await asMember(page);
  139 |       await page.goto(path);
  140 |       const button = page.locator('#auth-slot [data-control="graph"]');
  141 |       await expect(button).toHaveCount(1, { timeout: 15000 });
  142 |       await expect(button).not.toHaveAttribute('aria-disabled', 'true');
  143 |       await button.click();
  144 |       const dialog = page.locator('dialog.eg-dialog');
  145 |       await expect(dialog).toBeVisible();
  146 |       await expect(dialog.locator('.eg-canvas canvas').first()).toBeVisible({ timeout: 60000 });
  147 |       // centred in the viewport, horizontally and vertically
  148 |       const box = (await dialog.boundingBox())!;
  149 |       const vp = page.viewportSize()!;
  150 |       expect(Math.abs(box.x - (vp.width - box.x - box.width))).toBeLessThanOrEqual(2);
  151 |       expect(Math.abs(box.y - (vp.height - box.y - box.height))).toBeLessThanOrEqual(2);
  152 |       await page.keyboard.press('Escape');
  153 |       await expect(dialog).toBeHidden();
  154 |       expect(errors).toEqual([]);
  155 |     });
  156 |   }
  157 | });
  158 | 
  159 | test.describe('graph pop-over on geography and leaf pages', () => {
  160 |   for (const path of [AK, LA_TRACT]) {
  161 |     test(`opens and draws on ${path}`, async ({ page, request }) => {
  162 |       const probe = await nodeGraph(request, 'County', LA_COUNTY);
  163 |       test.skip(probe.missing, 'the API has no nodeGraph yet');
  164 |       if (path === AK) test.skip(!(await (await request.get(AK)).text()).includes('data-graph-id'), 'the us-pages renderer predates GraphScript');
  165 |       const errors: string[] = [];
  166 |       page.on('pageerror', (e) => errors.push(String(e)));
  167 |       await asMember(page);
  168 |       await page.goto(path);
  169 |       const button = page.locator('#auth-slot [data-control="graph"]');
  170 |       await expect(button).toHaveCount(1, { timeout: 30000 });
  171 |       // the real control, not the placeholder hint (the leaf page registers it after rendering)
  172 |       await expect.poll(async () => {
  173 |         await button.click();
  174 |         return page.locator('dialog.eg-dialog').count();
  175 |       }, { timeout: 30000 }).toBe(1);
  176 |       const dialog = page.locator('dialog.eg-dialog');
  177 |       await expect(dialog.locator('.eg-canvas canvas').first()).toBeVisible({ timeout: 60000 });
  178 |       await page.keyboard.press('Escape');
  179 |       await expect(dialog).toBeHidden();
  180 |       expect(errors).toEqual([]);
  181 |     });
  182 |   }
  183 | });
  184 | 
  185 | test.describe('expanding the graph one hop at a time', () => {
  186 |   test(`a county in ${AK}'s graph expands into the drawing`, async ({ page, request }) => {
  187 |     const probe = await nodeGraph(request, 'State', AK_ID);
  188 |     test.skip(probe.missing, 'the API has no nodeGraph yet');
  189 |     test.skip(!(await (await request.get(AK)).text()).includes('data-graph-id'), 'the us-pages renderer predates GraphScript');
  190 |     const county = probe.body?.data?.nodeGraph?.nodes?.find((n: { label: string }) => n.label === 'County');
  191 |     expect(county, 'Alaska has a county neighbour').toBeTruthy();
  192 | 
  193 |     const errors: string[] = [];
  194 |     page.on('pageerror', (e) => errors.push(String(e)));
  195 |     await asMember(page);
  196 |     await page.goto(AK);
  197 |     await page.locator('#auth-slot [data-control="graph"]').click({ timeout: 30000 });
  198 |     const dialog = page.locator('dialog.eg-dialog');
  199 |     await expect(dialog.locator('.eg-canvas canvas').first()).toBeVisible({ timeout: 60000 });
  200 |     type Hook = { electinfoGraph?: { nodeIds(): string[]; renderedPosition(id: string): { x: number; y: number } | null } };
  201 |     const count = () => page.evaluate(() => (document.querySelector('dialog.eg-dialog') as unknown as Hook).electinfoGraph!.nodeIds().length);
  202 |     const before = await count();
  203 |     const at = await page.evaluate((id) => (document.querySelector('dialog.eg-dialog') as unknown as Hook).electinfoGraph!.renderedPosition(id), county.id);
  204 |     expect(at).toBeTruthy();
  205 |     const box = (await dialog.locator('.eg-canvas').boundingBox())!;
  206 |     await page.mouse.click(box.x + at!.x, box.y + at!.y);
  207 |     const menu = dialog.locator('.eg-menu');
  208 |     await expect(menu).toContainText('County');
  209 |     await menu.locator('[data-eg-action="expand"]').click();
  210 |     await expect(menu.locator('[data-eg-status]')).toContainText(/added|No new connections/, { timeout: 60000 });
  211 |     expect(await count()).toBeGreaterThan(before);
  212 |     await expect(dialog.locator('.eg-foot')).toContainText(`Expanded: ${county.displayName}`);
  213 |     expect(errors).toEqual([]);
  214 |   });
  215 | });
  216 | 
  217 | test.describe('entity-graph without accounts', () => {
  218 |   test('a host without Authentik keeps the header Graph button', async ({ page }) => {
  219 |     await page.route('**/auth/whoami*', r => r.fulfill({ json: { enabled: 'false', email: '', elevated: false, entitlements: {} } }));
> 220 |     await page.goto(DNC);
      |                ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://10.1.105.22/committees/a75a9110-f1db-a945-39a8-7503ed3c04da/
  221 |     await expect(page.locator('button.eg-open')).toHaveCount(1, { timeout: 15000 });
  222 |     await expect(page.locator('#auth-slot [data-control="graph"]')).toHaveCount(0);
  223 |   });
  224 | });
  225 | 
```