# 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: admin.spec.js >> Admin — HTML Structure >> zones screen and modal exist in DOM
- Location: tests/admin.spec.js:41:3

# Error details

```
Error: expect(received).toContain(expected) // indexOf

Expected substring: "id=\"scr-zones\""
Received string:    "404 page not found
"
```

# Test source

```ts
  1   | // admin.spec.js — Admin PWA
  2   | const { test, expect, devices, request } = require('@playwright/test');
  3   | 
  4   | const PWA_NAME = 'Admin';
  5   | const BASE_URL  = 'https://srv1111289.hstgr.cloud/admin/';
  6   | 
  7   | test.use({ ...devices['Pixel 6'] });
  8   | 
  9   | // ── Smoke ─────────────────────────────────────────────────────────────────────
  10  | test.describe(`${PWA_NAME} — Smoke`, () => {
  11  |   test('page loads with login screen', async ({ page }) => {
  12  |     await page.goto(BASE_URL);
  13  |     const body = await page.locator('body').innerText();
  14  |     expect(body.length).toBeGreaterThan(0);
  15  |     await expect(page.locator('#scr-login')).toBeVisible({ timeout: 8000 });
  16  |   });
  17  | 
  18  |   test('manifest.json returns 200', async ({ page }) => {
  19  |     const resp = await page.goto(BASE_URL + 'manifest.json');
  20  |     expect(resp?.status()).toBe(200);
  21  |   });
  22  | 
  23  |   test('sw.js contains current version', async ({ page }) => {
  24  |     const resp = await page.goto(BASE_URL + 'sw.js');
  25  |     const text = await resp?.text() || '';
  26  |     expect(text).toMatch(/360admin-v\d+/);
  27  |   });
  28  | });
  29  | 
  30  | // ── HTML Structure ─────────────────────────────────────────────────────────────
  31  | test.describe(`${PWA_NAME} — HTML Structure`, () => {
  32  |   test('Client Zones tile exists on home screen', async ({}) => {
  33  |     const ctx = await request.newContext();
  34  |     const resp = await ctx.get(BASE_URL);
  35  |     const html = await resp.text();
  36  |     expect(html).toContain('Client Zones');
  37  |     expect(html).toContain('showZones()');
  38  |     expect(html).toContain('Zones &amp; city mapping');
  39  |   });
  40  | 
  41  |   test('zones screen and modal exist in DOM', async ({}) => {
  42  |     const ctx = await request.newContext();
  43  |     const resp = await ctx.get(BASE_URL);
  44  |     const html = await resp.text();
> 45  |     expect(html).toContain('id="scr-zones"');
      |                  ^ Error: expect(received).toContain(expected) // indexOf
  46  |     expect(html).toContain('id="zones-list"');
  47  |     expect(html).toContain('id="modal-zone"');
  48  |     expect(html).toContain('id="zone-name-input"');
  49  |     expect(html).toContain('id="zone-cities-chips"');
  50  |     expect(html).toContain('id="zone-city-input"');
  51  |   });
  52  | 
  53  |   test('city chip CSS classes present', async ({}) => {
  54  |     const ctx = await request.newContext();
  55  |     const resp = await ctx.get(BASE_URL);
  56  |     const html = await resp.text();
  57  |     expect(html).toContain('.city-chip');
  58  |     expect(html).toContain('.city-chip-del');
  59  |     expect(html).toContain('.city-chips-wrap');
  60  |   });
  61  | 
  62  |   test('existing screens still present (no regression)', async ({}) => {
  63  |     const ctx = await request.newContext();
  64  |     const resp = await ctx.get(BASE_URL);
  65  |     const html = await resp.text();
  66  |     expect(html).toContain('id="scr-companies"');
  67  |     expect(html).toContain('id="scr-employees"');
  68  |     expect(html).toContain('id="scr-access"');
  69  |     expect(html).toContain('id="scr-pwa-registry"');
  70  |     expect(html).toContain('id="scr-hr-settings"');
  71  |   });
  72  | });
  73  | 
  74  | // ── JS Source: zone CRUD ──────────────────────────────────────────────────────
  75  | test.describe(`${PWA_NAME} — Client Zone CRUD`, () => {
  76  |   test('source contains all zone management functions', async ({}) => {
  77  |     const ctx = await request.newContext();
  78  |     const resp = await ctx.get(BASE_URL);
  79  |     const src = await resp.text();
  80  |     expect(src).toContain('showZones');
  81  |     expect(src).toContain('refreshZones');
  82  |     expect(src).toContain('openZoneModal');
  83  |     expect(src).toContain('saveZone');
  84  |     expect(src).toContain('deleteZone');
  85  |     expect(src).toContain('renderZoneCityChips');
  86  |     expect(src).toContain('removeCity');
  87  |     expect(src).toContain('addCityFromInput');
  88  |     expect(src).toContain('onCityKeydown');
  89  |   });
  90  | 
  91  |   test('source contains CLI_H and CLI_RD client schema headers', async ({}) => {
  92  |     const ctx = await request.newContext();
  93  |     const resp = await ctx.get(BASE_URL);
  94  |     const src = await resp.text();
  95  |     expect(src).toContain('CLI_H');
  96  |     expect(src).toContain('CLI_RD');
  97  |     expect(src).toContain("'Accept-Profile':'client'");
  98  |     expect(src).toContain("'Content-Profile':'client'");
  99  |   });
  100 | 
  101 |   test('delete guard checks client.accounts before deleting zone', async ({}) => {
  102 |     const ctx = await request.newContext();
  103 |     const resp = await ctx.get(BASE_URL);
  104 |     const src = await resp.text();
  105 |     expect(src).toContain('accounts?zone=eq.');
  106 |     expect(src).toContain('it is assigned to one or more client accounts');
  107 |   });
  108 | 
  109 |   test('zone modal auto-uppercases name input', async ({}) => {
  110 |     const ctx = await request.newContext();
  111 |     const resp = await ctx.get(BASE_URL);
  112 |     const src = await resp.text();
  113 |     expect(src).toContain('.toUpperCase()');
  114 |     expect(src).toContain('zone-name-input');
  115 |   });
  116 | 
  117 |   test('zone screen is accessible with admin session', async ({ page }) => {
  118 |     await page.addInitScript(() => {
  119 |       localStorage.setItem('lm360-admin-session', JSON.stringify({
  120 |         id: 'harish', name: 'Harish Kumar Lal', role: 'admin',
  121 |         loginAt: new Date().toISOString()
  122 |       }));
  123 |     });
  124 |     await page.goto(BASE_URL);
  125 |     // Should be on home screen
  126 |     await expect(page.locator('#scr-home')).toBeVisible({ timeout: 8000 });
  127 |     // Zones screen should exist in DOM
  128 |     await expect(page.locator('#scr-zones')).toHaveCount(1);
  129 |   });
  130 | 
  131 |   test('zone modal is hidden by default', async ({ page }) => {
  132 |     await page.goto(BASE_URL);
  133 |     await expect(page.locator('#modal-zone')).not.toHaveClass(/open/, { timeout: 4000 });
  134 |   });
  135 | });
  136 | 
  137 | // ── DB objects created in Step 1 ─────────────────────────────────────────────
  138 | test.describe(`${PWA_NAME} — DB Schema (Step 1 migrations)`, () => {
  139 |   test('client.zones table exists and is accessible via PostgREST', async ({ page }) => {
  140 |     const resp = await page.request.get(
  141 |       'https://srv1111289.hstgr.cloud/db/zones',
  142 |       { headers: { 'Accept-Profile': 'client', 'Accept': 'application/json' } }
  143 |     );
  144 |     expect(resp.status()).toBe(200);
  145 |     const body = await resp.json();
```