# 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/entities.spec.ts >> us.elect.info entity sections - additional index + detail >> tracts section - state/county filter and random detail pages
- Location: tests/ui/entities.spec.ts:597:7

# Error details

```
TimeoutError: page.waitForSelector: Timeout 15000ms exceeded.
Call log:
  - waiting for locator('.tract-result, .tract-error') to be visible

```

# Page snapshot

```yaml
- generic [ref=e1]:
  - link "← Back to Home" [ref=e2] [cursor=pointer]:
    - /url: /
  - banner [ref=e3]:
    - heading "Census Tracts" [level=1] [ref=e4]
    - paragraph [ref=e5]: Browse census tracts with ACS demographic data
  - generic [ref=e6]:
    - button "Map" [ref=e7] [cursor=pointer]
    - button "List" [active] [ref=e8] [cursor=pointer]
  - main [ref=e9]:
    - generic [ref=e11]:
      - generic [ref=e12]:
        - generic [ref=e13]: "State:"
        - combobox "State:" [ref=e14] [cursor=pointer]:
          - option "Select a state..."
          - option "Alabama"
          - option "Alaska"
          - option "Arizona"
          - option "Arkansas"
          - option "California"
          - option "Colorado"
          - option "Connecticut"
          - option "Delaware"
          - option "District of Columbia"
          - option "Florida"
          - option "Georgia"
          - option "Hawaii"
          - option "Idaho"
          - option "Illinois"
          - option "Indiana"
          - option "Iowa"
          - option "Kansas"
          - option "Kentucky"
          - option "Louisiana"
          - option "Maine"
          - option "Maryland"
          - option "Massachusetts"
          - option "Michigan"
          - option "Minnesota"
          - option "Mississippi"
          - option "Missouri"
          - option "Montana"
          - option "Nebraska"
          - option "Nevada"
          - option "New Hampshire"
          - option "New Jersey"
          - option "New Mexico"
          - option "New York"
          - option "North Carolina"
          - option "North Dakota"
          - option "Ohio"
          - option "Oklahoma"
          - option "Oregon"
          - option "Pennsylvania"
          - option "Puerto Rico"
          - option "Rhode Island"
          - option "South Carolina"
          - option "South Dakota"
          - option "Tennessee"
          - option "Texas" [selected]
          - option "Utah"
          - option "Vermont"
          - option "Virginia"
          - option "Washington"
          - option "West Virginia"
          - option "Wisconsin"
          - option "Wyoming"
        - generic [ref=e15]: "County:"
        - combobox "County:" [ref=e16] [cursor=pointer]:
          - option "All Counties (254)"
          - option "Anderson County" [selected]
          - option "Andrews County"
          - option "Angelina County"
          - option "Aransas County"
          - option "Archer County"
          - option "Armstrong County"
          - option "Atascosa County"
          - option "Austin County"
          - option "Bailey County"
          - option "Bandera County"
          - option "Bastrop County"
          - option "Baylor County"
          - option "Bee County"
          - option "Bell County"
          - option "Bexar County"
          - option "Blanco County"
          - option "Borden County"
          - option "Bosque County"
          - option "Bowie County"
          - option "Brazoria County"
          - option "Brazos County"
          - option "Brewster County"
          - option "Briscoe County"
          - option "Brooks County"
          - option "Brown County"
          - option "Burleson County"
          - option "Burnet County"
          - option "Caldwell County"
          - option "Calhoun County"
          - option "Callahan County"
          - option "Cameron County"
          - option "Camp County"
          - option "Carson County"
          - option "Cass County"
          - option "Castro County"
          - option "Chambers County"
          - option "Cherokee County"
          - option "Childress County"
          - option "Clay County"
          - option "Cochran County"
          - option "Coke County"
          - option "Coleman County"
          - option "Collin County"
          - option "Collingsworth County"
          - option "Colorado County"
          - option "Comal County"
          - option "Comanche County"
          - option "Concho County"
          - option "Cooke County"
          - option "Coryell County"
          - option "Cottle County"
          - option "Crane County"
          - option "Crockett County"
          - option "Crosby County"
          - option "Culberson County"
          - option "Dallam County"
          - option "Dallas County"
          - option "Dawson County"
          - option "DeWitt County"
          - option "Deaf Smith County"
          - option "Delta County"
          - option "Denton County"
          - option "Dickens County"
          - option "Dimmit County"
          - option "Donley County"
          - option "Duval County"
          - option "Eastland County"
          - option "Ector County"
          - option "Edwards County"
          - option "El Paso County"
          - option "Ellis County"
          - option "Erath County"
          - option "Falls County"
          - option "Fannin County"
          - option "Fayette County"
          - option "Fisher County"
          - option "Floyd County"
          - option "Foard County"
          - option "Fort Bend County"
          - option "Franklin County"
          - option "Freestone County"
          - option "Frio County"
          - option "Gaines County"
          - option "Galveston County"
          - option "Garza County"
          - option "Gillespie County"
          - option "Glasscock County"
          - option "Goliad County"
          - option "Gonzales County"
          - option "Gray County"
          - option "Grayson County"
          - option "Gregg County"
          - option "Grimes County"
          - option "Guadalupe County"
          - option "Hale County"
          - option "Hall County"
          - option "Hamilton County"
          - option "Hansford County"
          - option "Hardeman County"
          - option "Hardin County"
          - option "Harris County"
          - option "Harrison County"
          - option "Hartley County"
          - option "Haskell County"
          - option "Hays County"
          - option "Hemphill County"
          - option "Henderson County"
          - option "Hidalgo County"
          - option "Hill County"
          - option "Hockley County"
          - option "Hood County"
          - option "Hopkins County"
          - option "Houston County"
          - option "Howard County"
          - option "Hudspeth County"
          - option "Hunt County"
          - option "Hutchinson County"
          - option "Irion County"
          - option "Jack County"
          - option "Jackson County"
          - option "Jasper County"
          - option "Jeff Davis County"
          - option "Jefferson County"
          - option "Jim Hogg County"
          - option "Jim Wells County"
          - option "Johnson County"
          - option "Jones County"
          - option "Karnes County"
          - option "Kaufman County"
          - option "Kendall County"
          - option "Kenedy County"
          - option "Kent County"
          - option "Kerr County"
          - option "Kimble County"
          - option "King County"
          - option "Kinney County"
          - option "Kleberg County"
          - option "Knox County"
          - option "La Salle County"
          - option "Lamar County"
          - option "Lamb County"
          - option "Lampasas County"
          - option "Lavaca County"
          - option "Lee County"
          - option "Leon County"
          - option "Liberty County"
          - option "Limestone County"
          - option "Lipscomb County"
          - option "Live Oak County"
          - option "Llano County"
          - option "Loving County"
          - option "Lubbock County"
          - option "Lynn County"
          - option "Madison County"
          - option "Marion County"
          - option "Martin County"
          - option "Mason County"
          - option "Matagorda County"
          - option "Maverick County"
          - option "McCulloch County"
          - option "McLennan County"
          - option "McMullen County"
          - option "Medina County"
          - option "Menard County"
          - option "Midland County"
          - option "Milam County"
          - option "Mills County"
          - option "Mitchell County"
          - option "Montague County"
          - option "Montgomery County"
          - option "Moore County"
          - option "Morris County"
          - option "Motley County"
          - option "Nacogdoches County"
          - option "Navarro County"
          - option "Newton County"
          - option "Nolan County"
          - option "Nueces County"
          - option "Ochiltree County"
          - option "Oldham County"
          - option "Orange County"
          - option "Palo Pinto County"
          - option "Panola County"
          - option "Parker County"
          - option "Parmer County"
          - option "Pecos County"
          - option "Polk County"
          - option "Potter County"
          - option "Presidio County"
          - option "Rains County"
          - option "Randall County"
          - option "Reagan County"
          - option "Real County"
          - option "Red River County"
          - option "Reeves County"
          - option "Refugio County"
          - option "Roberts County"
          - option "Robertson County"
          - option "Rockwall County"
          - option "Runnels County"
          - option "Rusk County"
          - option "Sabine County"
          - option "San Augustine County"
          - option "San Jacinto County"
          - option "San Patricio County"
          - option "San Saba County"
          - option "Schleicher County"
          - option "Scurry County"
          - option "Shackelford County"
          - option "Shelby County"
          - option "Sherman County"
          - option "Smith County"
          - option "Somervell County"
          - option "Starr County"
          - option "Stephens County"
          - option "Sterling County"
          - option "Stonewall County"
          - option "Sutton County"
          - option "Swisher County"
          - option "Tarrant County"
          - option "Taylor County"
          - option "Terrell County"
          - option "Terry County"
          - option "Throckmorton County"
          - option "Titus County"
          - option "Tom Green County"
          - option "Travis County"
          - option "Trinity County"
          - option "Tyler County"
          - option "Upshur County"
          - option "Upton County"
          - option "Uvalde County"
          - option "Val Verde County"
          - option "Van Zandt County"
          - option "Victoria County"
          - option "Walker County"
          - option "Waller County"
          - option "Ward County"
          - option "Washington County"
          - option "Webb County"
          - option "Wharton County"
          - option "Wheeler County"
          - option "Wichita County"
          - option "Wilbarger County"
          - option "Willacy County"
          - option "Williamson County"
          - option "Wilson County"
          - option "Winkler County"
          - option "Wise County"
          - option "Wood County"
          - option "Yoakum County"
          - option "Young County"
          - option "Zapata County"
          - option "Zavala County"
        - generic [ref=e17]:
          - textbox "Search by GEOID..." [ref=e18]
          - button "Search" [ref=e19] [cursor=pointer]
      - generic [ref=e20]:
        - generic [ref=e21]:
          - heading "Census Tracts" [level=3] [ref=e22]
          - button "Clear Filters" [ref=e23] [cursor=pointer]
        - paragraph [ref=e25]: No census tracts found.
```

# Test source

```ts
  530 |     }
  531 |   });
  532 | 
  533 |   test('postalcodes section - index and random detail pages', async ({ page }) => {
  534 |     await page.goto('/postalcodes/');
  535 | 
  536 |     // Map view is default — verify Leaflet map renders with GeoJSON state shapes
  537 |     await expect(page.locator('#map.leaflet-container')).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });
  538 |     await expect(page.locator('#map .leaflet-interactive').first()).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });
  539 |     const shapes = await page.locator('#map .leaflet-interactive').all();
  540 |     expect(shapes.length).toBeGreaterThan(0);
  541 | 
  542 |     // Switch to List view to test postal code results and detail navigation
  543 |     await page.locator('.toggle-btn[data-view="list"]').click();
  544 | 
  545 |     // Wait for results to load
  546 |     await page.waitForSelector('.postal-result, .postal-error', { timeout: DATA_LOAD_TIMEOUT });
  547 |     const results = await page.locator('.postal-result').all();
  548 |     expect(results.length).toBeGreaterThan(0);
  549 | 
  550 |     // Pick random results and visit detail pages
  551 |     const hrefs = await Promise.all(results.slice(0, 20).map(r => r.getAttribute('href')));
  552 |     const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);
  553 | 
  554 |     for (const href of randomLinks) {
  555 |       const entityResponse = await page.goto(toRelativePath(href));
  556 |       expect(entityResponse?.status()).toBe(200);
  557 |       await expect(page.locator('h1')).toBeVisible();
  558 |     }
  559 |   });
  560 | 
  561 |   test('precincts section - map view and state filter', async ({ page }) => {
  562 |     await page.goto('/precincts/');
  563 | 
  564 |     // Map view is default — verify Leaflet map renders with GeoJSON state shapes
  565 |     await expect(page.locator('#map.leaflet-container')).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });
  566 |     await expect(page.locator('#map .leaflet-interactive').first()).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });
  567 |     const shapes = await page.locator('#map .leaflet-interactive').all();
  568 |     expect(shapes.length).toBeGreaterThan(0);
  569 | 
  570 |     // Switch to List view to test state filter and precinct results
  571 |     await page.locator('.toggle-btn[data-view="list"]').click();
  572 | 
  573 |     // Select a state first (precincts require state selection)
  574 |     const stateSelect = page.locator('#precinct-state-select');
  575 |     await expect(stateSelect).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });
  576 |     await stateSelect.selectOption('TX');
  577 | 
  578 |     // Wait for precinct results to load
  579 |     await page.waitForSelector('.precinct-result, .precinct-error', { timeout: DATA_LOAD_TIMEOUT });
  580 |     const results = await page.locator('.precinct-result').all();
  581 |     expect(results.length).toBeGreaterThan(0);
  582 | 
  583 |     // Pick random results and visit detail pages
  584 |     const hrefs = await Promise.all(results.slice(0, 20).map(r => r.getAttribute('href')));
  585 |     const validHrefs = hrefs.filter(Boolean) as string[];
  586 | 
  587 |     if (validHrefs.length > 0) {
  588 |       const randomLinks = getRandomItems(validHrefs, 3);
  589 |       for (const href of randomLinks) {
  590 |         const entityResponse = await page.goto(toRelativePath(href));
  591 |         expect(entityResponse?.status()).toBe(200);
  592 |         await expect(page.locator('h1')).toBeVisible();
  593 |       }
  594 |     }
  595 |   });
  596 | 
  597 |   test('tracts section - state/county filter and random detail pages', async ({ page }) => {
  598 |     test.setTimeout(120000); // Tracts require sequential state→county→tract interactions with GraphQL
  599 |     await page.goto('/tracts/');
  600 | 
  601 |     // Switch to List view — tract-index.js loads dynamically on list view activation
  602 |     await page.locator('.toggle-btn[data-view="list"]').click();
  603 | 
  604 |     // Wait for state dropdown to populate (tract-index.js loads states via GraphQL)
  605 |     const stateSelect = page.locator('#tract-state-select');
  606 |     await page.waitForFunction(() => {
  607 |       const select = document.querySelector('#tract-state-select') as HTMLSelectElement;
  608 |       return select && select.options.length > 1;
  609 |     }, { timeout: 45000 });
  610 | 
  611 |     // Select Texas
  612 |     await stateSelect.selectOption('TX');
  613 | 
  614 |     // Wait for county dropdown to populate
  615 |     const countySelect = page.locator('#tract-county-select');
  616 |     await expect(countySelect).toBeEnabled({ timeout: DATA_LOAD_TIMEOUT });
  617 |     await page.waitForFunction(() => {
  618 |       const select = document.querySelector('#tract-county-select') as HTMLSelectElement;
  619 |       return select && select.options.length > 1;
  620 |     }, { timeout: DATA_LOAD_TIMEOUT });
  621 | 
  622 |     // Select first county
  623 |     const options = await countySelect.locator('option').all();
  624 |     if (options.length > 1) {
  625 |       const value = await options[1].getAttribute('value');
  626 |       if (value) await countySelect.selectOption(value);
  627 |     }
  628 | 
  629 |     // Wait for tract results to load
> 630 |     await page.waitForSelector('.tract-result, .tract-error', { timeout: DATA_LOAD_TIMEOUT });
      |                ^ TimeoutError: page.waitForSelector: Timeout 15000ms exceeded.
  631 |     const results = await page.locator('.tract-result').all();
  632 |     expect(results.length).toBeGreaterThan(0);
  633 | 
  634 |     // Pick random results and visit detail pages
  635 |     const hrefs = await Promise.all(results.slice(0, 20).map(r => r.getAttribute('href')));
  636 |     const validHrefs = hrefs.filter(Boolean) as string[];
  637 | 
  638 |     if (validHrefs.length > 0) {
  639 |       const randomLinks = getRandomItems(validHrefs, 3);
  640 |       for (const href of randomLinks) {
  641 |         const entityResponse = await page.goto(toRelativePath(href));
  642 |         expect(entityResponse?.status()).toBe(200);
  643 |         await expect(page.locator('h1')).toBeVisible();
  644 |       }
  645 |     }
  646 |   });
  647 | 
  648 | });
  649 | 
  650 | test.describe('us.elect.info entity sections - individuals (premium)', () => {
  651 |   test.use({
  652 |     httpCredentials: hasAuthCredentials ? {
  653 |       username: process.env.PLAYWRIGHT_AUTH_USER!,
  654 |       password: process.env.PLAYWRIGHT_AUTH_PASS || '',
  655 |     } : undefined
  656 |   });
  657 | 
  658 |   test('individuals section - index and random pages', async ({ page }) => {
  659 |     test.skip(!hasAuthCredentials, 'Requires PLAYWRIGHT_AUTH_USER/PLAYWRIGHT_AUTH_PASS');
  660 | 
  661 |     const indexResponse = await page.goto('/individuals/');
  662 |     expect(indexResponse?.status()).toBe(200);
  663 |     await expect(page.locator('h1')).toContainText(/Individual/i);
  664 | 
  665 |     await expect(page.locator('.entity-search-result').first()).toBeVisible({ timeout: DATA_LOAD_TIMEOUT });
  666 | 
  667 |     const links = await page.locator('.entity-search-result').all();
  668 |     expect(links.length).toBeGreaterThan(0);
  669 | 
  670 |     const hrefs = await Promise.all(links.slice(0, 20).map(l => l.getAttribute('href')));
  671 |     const randomLinks = getRandomItems(hrefs.filter(Boolean) as string[], 3);
  672 | 
  673 |     for (const href of randomLinks) {
  674 |       const entityResponse = await page.goto(toRelativePath(href));
  675 |       expect(entityResponse?.status()).toBe(200);
  676 |       await expect(page.locator('h1')).toBeVisible();
  677 |     }
  678 |   });
  679 | });
  680 | 
```