# 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/layout.spec.ts >> entity index layout - search UI above results >> /blocks/ has no static search description in main
- Location: tests/ui/layout.spec.ts:45:9

# Error details

```
Error: expect(locator).toContainText(expected) failed

Locator: locator('h1')
Expected pattern: /Blocks/i
Received string:  "Premium data"
Timeout: 5000ms

Call log:
  - Expect "toContainText" locator('h1') with timeout 5000ms
  - waiting for locator('h1')
    14 × locator resolved to <h1>Premium data</h1>
       - unexpected value "Premium data"

```

```yaml
- heading "Premium data" [level=1]
```

# Test source

```ts
  1  | import { test, expect } from '@playwright/test';
  2  | 
  3  | // Wait timeout for async data loading (GraphQL browseEntities)
  4  | const DATA_LOAD_TIMEOUT = 15000;
  5  | 
  6  | // Entity index pages that use insertSearchUI from base.ts
  7  | const ENTITY_INDEX_PAGES = [
  8  |   { path: '/offices/', heading: /Offices/i },
  9  |   { path: '/candidates/', heading: /Candidates/i },
  10 |   { path: '/committees/', heading: /Committees/i },
  11 |   { path: '/districts/', heading: /Districts/i },
  12 |   { path: '/elections/', heading: /Election/i },
  13 |   { path: '/employers/', heading: /Employers/i },
  14 |   { path: '/individuals/', heading: /Individual/i },
  15 |   { path: '/parties/', heading: /Parties/i },
  16 |   { path: '/vendors/', heading: /Vendors/i },
  17 |   { path: '/counties/', heading: /Counties/i },
  18 |   { path: '/places/', heading: /Places/i },
  19 |   { path: '/precincts/', heading: /Precincts/i },
  20 |   { path: '/tracts/', heading: /Tracts/i },
  21 |   { path: '/postalcodes/', heading: /Postal/i },
  22 |   { path: '/blocks/', heading: /Blocks/i },
  23 | ];
  24 | 
  25 | // All landing pages including special pages
  26 | // (/codesources/ and /contributors/ are disabled - see disabled-pages.spec.ts)
  27 | const ALL_LANDING_PAGES = [
  28 |   ...ENTITY_INDEX_PAGES,
  29 |   { path: '/states/', heading: /States/i },
  30 |   { path: '/datasources/', heading: /Data Sources/i },
  31 |   { path: '/', heading: /US Elections/i },
  32 | ];
  33 | 
  34 | test.describe('landing page layout', () => {
  35 |   for (const { path, heading } of ALL_LANDING_PAGES) {
  36 |     test(`${path} loads with correct heading`, async ({ page }) => {
  37 |       await page.goto(path);
  38 |       await expect(page.locator('h1')).toContainText(heading);
  39 |     });
  40 |   }
  41 | });
  42 | 
  43 | test.describe('entity index layout - search UI above results', () => {
  44 |   for (const { path, heading } of ENTITY_INDEX_PAGES) {
  45 |     test(`${path} has no static search description in main`, async ({ page }) => {
  46 |       await page.goto(path);
> 47 |       await expect(page.locator('h1')).toContainText(heading);
     |                                        ^ Error: expect(locator).toContainText(expected) failed
  48 | 
  49 |       // The <main> element should have no <section> or <p> children
  50 |       // (the search UI is injected by JS before <main>, not inside it)
  51 |       const mainSections = page.locator('main > section');
  52 |       await expect(mainSections).toHaveCount(0);
  53 |     });
  54 |   }
  55 | 
  56 |   test('offices - search container appears before main in DOM', async ({ page }) => {
  57 |     await page.goto('/offices/');
  58 |     await expect(page.locator('.entity-search-container')).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });
  59 | 
  60 |     // Verify search container is a sibling before <main>, not inside it
  61 |     const searchIsBeforeMain = await page.evaluate(() => {
  62 |       const searchContainer = document.querySelector('.entity-search-container');
  63 |       const main = document.querySelector('main');
  64 |       if (!searchContainer || !main) return false;
  65 |       // compareDocumentPosition bit 4 = DOCUMENT_POSITION_FOLLOWING
  66 |       return (searchContainer.compareDocumentPosition(main) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
  67 |     });
  68 |     expect(searchIsBeforeMain).toBe(true);
  69 |   });
  70 | 
  71 |   test('candidates - search container appears before main in DOM', async ({ page }) => {
  72 |     await page.goto('/candidates/');
  73 |     await expect(page.locator('.entity-search-container')).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });
  74 | 
  75 |     const searchIsBeforeMain = await page.evaluate(() => {
  76 |       const searchContainer = document.querySelector('.entity-search-container');
  77 |       const main = document.querySelector('main');
  78 |       if (!searchContainer || !main) return false;
  79 |       return (searchContainer.compareDocumentPosition(main) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
  80 |     });
  81 |     expect(searchIsBeforeMain).toBe(true);
  82 |   });
  83 | });
  84 | 
```