# 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/auth.spec.ts >> sign-in panel >> the shared identity bar is served and revalidated
- Location: tests/ui/auth.spec.ts:180:7

# Error details

```
Error: apiRequestContext.get: connect ECONNREFUSED 10.1.105.22:80
Call log:
  - → GET http://10.1.105.22/identity/identity-bar.js
    - user-agent: Playwright/1.64.1 (x64; ubuntu 22.04) node/20.9 CI/1
    - accept: */*
    - accept-encoding: gzip,deflate,br

```

# Test source

```ts
  82  |   for (const { path } of PREMIUM) {
  83  |     test(`${path} answers 200 for the test identity, or asks a signed-out one to sign in`, async ({ page, request }) => {
  84  |       const me = await whoami(request);
  85  |       // Where /auth/ asks an anonymous visitor to sign in, so must the premium sections.
  86  |       if (me.redirected) {
  87  |         expect(await premiumGated(request, path), `${path} sends a signed-out visitor to sign-in`).toBe(true);
  88  |         return;
  89  |       }
  90  |       test.skip(me.enabled === 'true' && !me.elevated, 'signed in without elevated access');
  91  |       const response = await page.goto(path);
  92  |       expect(response?.status()).toBe(200);
  93  |     });
  94  |   }
  95  | 
  96  |   // The placeholder became the voter search page (sites#277, tests/voters.spec.ts).
  97  |   test('/voters/ is the voter search page', async ({ page, request }) => {
  98  |     const me = await whoami(request);
  99  |     // A signed-in visitor without the voters entitlement (the front door as preview-e2e, ops#703) gets the premium notice.
  100 |     test.skip(me.enabled === 'true' && !me.entitlements.voters, 'no voters access (signed out, or signed in without it)');
  101 |     await page.goto('/voters/');
  102 |     await expect(page.locator('h1')).toHaveText('Voters');
  103 |     await expect(page.locator('script[src="/js/voter-index.js"]')).toHaveCount(1);
  104 |     await expect(page.locator('.coming-soon')).toHaveCount(0);
  105 |   });
  106 | 
  107 |   test('the premium notice page is not directly reachable', async ({ page }) => {
  108 |     const response = await page.goto('/premium-required.html');
  109 |     expect(response?.status()).toBe(404);
  110 |   });
  111 | 
  112 |   test('homepage premium cards follow the account', async ({ page, request }) => {
  113 |     const me = await whoami(request);
  114 |     await page.goto('/');
  115 |     for (const { path, label } of PREMIUM) {
  116 |       const card = page.locator(`[data-premium-href="${path}"]`);
  117 |       await expect(card).toHaveCount(1);
  118 |       await expect(card).toContainText(label);
  119 |       const area = path.replace(/\//g, '') as 'voters' | 'individuals' | 'blocks';
  120 |       if (me.enabled === 'true' && me.entitlements[area]) {
  121 |         await expect(page.locator(`a[data-premium-href="${path}"]`)).toHaveAttribute('href', path);
  122 |         await expect(card).not.toHaveClass(/entity-card--disabled/);
  123 |       } else {
  124 |         await expect(card).toHaveClass(/entity-card--disabled/);
  125 |         await expect(page.locator(`a[data-premium-href="${path}"]`)).toHaveCount(0);
  126 |       }
  127 |     }
  128 |   });
  129 | 
  130 |   test('account slot shows the signed-in email where Authentik is on', async ({ page, request }) => {
  131 |     const me = await whoami(request);
  132 |     await page.goto('/');
  133 |     const slot = page.locator('#auth-slot');
  134 |     if (me.enabled !== 'true') {
  135 |       await expect(slot).toBeEmpty();
  136 |       return;
  137 |     }
  138 |     if (me.email) {
  139 |       await expect(slot.locator('.auth-email')).toHaveText(me.email);
  140 |       await expect(slot.locator('a.auth-link', { hasText: 'Log out' })).toHaveAttribute('href', '/outpost.goauthentik.io/sign_out');
  141 |       await expect(slot.locator('.ei-chip').first()).toHaveText('Registered');
  142 |     } else {
  143 |       await expect(slot.locator('a.auth-link')).toHaveText('Log in');
  144 |     }
  145 |   });
  146 | });
  147 | 
  148 | // Sign-in panel (electinfo/sites#303): Log In opens the site's own dialog;
  149 | // "Continue with Google" is /signin/google (njs/signin.js), "Continue with
  150 | // email" the outpost's /start.
  151 | test.describe('sign-in panel', () => {
  152 |   test('/signin/google redirects to the Google flow, or falls back to the sign-in page', async ({ request }) => {
  153 |     const res = await request.get('/signin/google?rd=%2Fvoters%2F', { maxRedirects: 0 });
  154 |     expect(res.status()).toBe(302);
  155 |     expect(res.headers()['cache-control']).toContain('no-store');
  156 |     const location = res.headers()['location'] || '';
  157 |     // With an outpost for this host: Authentik's Google-only flow, the
  158 |     // outpost's authorize URL as a relative next. Anywhere else (CI pods):
  159 |     // the outpost's own /start, i.e. the normal sign-in page.
  160 |     if (location.startsWith('https://auth.elect.info/')) {
  161 |       const url = new URL(location);
  162 |       expect(url.pathname).toBe('/if/flow/elect-info-google/');
  163 |       expect(url.searchParams.get('next') || '').toMatch(/^\/application\/o\/authorize\/\?/);
  164 |     } else {
  165 |       expect(location).toMatch(/^https:\/\/[^/]+\/outpost\.goauthentik\.io\/start\?rd=https%3A%2F%2F[^%]+%2Fvoters%2F$/);
  166 |     }
  167 |   });
  168 | 
  169 |   test('/signin/register goes to the sign-up flow, or falls back to the sign-in page', async ({ request }) => {
  170 |     const res = await request.get('/signin/register?rd=%2F', { maxRedirects: 0 });
  171 |     expect(res.status()).toBe(302);
  172 |     const location = res.headers()['location'] || '';
  173 |     if (location.startsWith('https://auth.elect.info/')) {
  174 |       expect(new URL(location).pathname).toBe('/if/flow/elect-info-enrollment/');
  175 |     } else {
  176 |       expect(location).toMatch(/^https:\/\/[^/]+\/outpost\.goauthentik\.io\/start\?rd=/);
  177 |     }
  178 |   });
  179 | 
  180 |   test('the shared identity bar is served and revalidated', async ({ request }) => {
  181 |     for (const asset of ['/identity/identity-bar.js', '/identity/identity-bar.css']) {
> 182 |       const res = await request.get(asset);
      |                                 ^ Error: apiRequestContext.get: connect ECONNREFUSED 10.1.105.22:80
  183 |       expect(res.status(), asset).toBe(200);
  184 |       expect(res.headers()['cache-control'] || '').toContain('no-cache');
  185 |     }
  186 |   });
  187 | 
  188 |   test('/signin/google only answers GET, and the outpost hop is internal', async ({ request }) => {
  189 |     expect((await request.post('/signin/google', { maxRedirects: 0 })).status()).toBe(405);
  190 |     expect((await request.post('/signin/register', { maxRedirects: 0 })).status()).toBe(405);
  191 |     expect((await request.get('/_outpost_start?rd=%2F', { maxRedirects: 0 })).status()).toBe(404);
  192 |   });
  193 | 
  194 |   test('Log In opens the sign-in panel with Google and email', async ({ page, request }) => {
  195 |     const me = await whoami(request);
  196 |     test.skip(me.enabled !== 'true' || me.email !== '', 'needs Authentik on and a signed-out visitor');
  197 |     await page.goto('/');
  198 |     await page.locator('#auth-slot a.auth-link', { hasText: 'Log in' }).click();
  199 |     const panel = page.locator('dialog#ei-signin');
  200 |     await expect(panel).toBeVisible();
  201 |     await expect(panel.locator('[data-signin="google"]')).toHaveAttribute('href', /^\/signin\/google\?rd=/);
  202 |     await expect(panel.locator('[data-signin="email"]')).toHaveAttribute('href', /^\/outpost\.goauthentik\.io\/start\?rd=/);
  203 |     await expect(panel.locator('[data-signin="register"]')).toHaveAttribute('href', /^\/signin\/register\?rd=/);
  204 |     await page.keyboard.press('Escape');
  205 |     await expect(panel).toBeHidden();
  206 |   });
  207 | });
  208 | 
```