fix(e2e): scope heading locators to main content area #50

Merged
privilegedescalation-engineer[bot] merged 1 commits from fix/heading-selectors into main 2026-05-04 17:20:38 +00:00
privilegedescalation-engineer[bot] commented 2026-04-21 21:11:48 +00:00 (Migrated from github.com)

Summary

Replace bare getByRole('heading', { name: /Intel GPU — .../i }) selectors with
page.locator('main').getByRole('heading', { name: '...' }) in the E2E smoke tests.

The bare selectors may match multiple elements (e.g., a heading inside the sidebar
and the page heading) causing Playwright strict-mode violations. Scoping to the
main element ensures each locator targets exactly one element.

Changes

  • All page heading assertions now use page.locator('main').getByRole('heading', ...)
  • Regex name matching replaced with exact string matching for precision

Test plan

  • npx playwright test passes in CI
  • npx playwright test --headed passes locally

🤖 Generated with Claude Code

## Summary Replace bare `getByRole('heading', { name: /Intel GPU — .../i })` selectors with `page.locator('main').getByRole('heading', { name: '...' })` in the E2E smoke tests. The bare selectors may match multiple elements (e.g., a heading inside the sidebar and the page heading) causing Playwright strict-mode violations. Scoping to the `main` element ensures each locator targets exactly one element. ## Changes - All page heading assertions now use `page.locator('main').getByRole('heading', ...)` - Regex name matching replaced with exact string matching for precision ## Test plan - [ ] `npx playwright test` passes in CI - [ ] `npx playwright test --headed` passes locally 🤖 Generated with [Claude Code](https://claude.com/claude-code)
greptile-apps[bot] commented 2026-04-21 21:14:50 +00:00 (Migrated from github.com)

Greptile Summary

This PR scopes all heading locators in the E2E smoke tests to the main content element (page.locator('main').getByRole('heading', ...)) to prevent Playwright strict-mode violations that occur when a heading is present in both the sidebar and the page body. It also switches from case-insensitive regex name matching to exact string matching.

  • All six heading assertions now use page.locator('main').getByRole('heading', ...) instead of the bare page.getByRole('heading', ...)
  • Regex patterns (e.g., /Intel GPU — Overview/i) replaced with exact string literals (e.g., 'Intel GPU — Overview')
  • No functional logic is changed outside the test file
  • The first navigation test ('sidebar intel-gpu entry is clickable and navigates to overview') still has no timeout on the scoped heading assertion — this is pre-existing and not introduced by this PR, but worth noting since after a click+navigation the heading may not be immediately available

Confidence Score: 5/5

Safe to merge — targeted fix to a single test file with no production code changes.

The change is narrowly scoped to E2E test helpers: it correctly addresses Playwright strict-mode violations by anchoring locators to main, and switches to exact string matching for precision. The only note is a pre-existing missing timeout on one assertion, which is a non-blocking style suggestion.

No files require special attention.

Important Files Changed

Filename Overview
e2e/intel-gpu.spec.ts All heading locators scoped to main; regex matching replaced with exact strings. One pre-existing omission: heading assertion after sidebar click has no timeout.

Sequence Diagram

sequenceDiagram
    participant PW as Playwright Test
    participant P as Page DOM
    participant Sidebar as sidebar (nav)
    participant Main as main (content)

    note over PW,Main: Before fix — bare getByRole may match multiple elements
    PW->>P: getByRole('heading', {name: /Intel GPU — Overview/i})
    P-->>Sidebar: heading match?
    P-->>Main: heading match?
    P-->>PW: ❌ StrictModeViolation (2+ matches)

    note over PW,Main: After fix — locator scoped to main
    PW->>Main: locator('main').getByRole('heading', {name: 'Intel GPU — Overview'})
    Main-->>PW: ✅ single heading match
Prompt To Fix All With AI
This is a comment left during a code review.
Path: e2e/intel-gpu.spec.ts
Line: 22-24

Comment:
**Missing timeout after navigation**

All other heading assertions in this file pass `{ timeout: 15_000 }`, but this one does not. After `gpuEntry.click()` triggers a client-side navigation, the heading may not be immediately present in the DOM. Without an explicit timeout, Playwright falls back to the global `expect` timeout configured in `playwright.config.ts`. Adding the same `15_000` ms timeout used elsewhere makes the behaviour consistent and less fragile in slow CI environments.

```suggestion
    await expect(
      page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' })
    ).toBeVisible({ timeout: 15_000 });
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(e2e): scope heading locators to main..." | Re-trigger Greptile

<details><summary><h3>Greptile Summary</h3></summary> This PR scopes all heading locators in the E2E smoke tests to the `main` content element (`page.locator('main').getByRole('heading', ...)`) to prevent Playwright strict-mode violations that occur when a heading is present in both the sidebar and the page body. It also switches from case-insensitive regex name matching to exact string matching. - All six heading assertions now use `page.locator('main').getByRole('heading', ...)` instead of the bare `page.getByRole('heading', ...)` - Regex patterns (e.g., `/Intel GPU — Overview/i`) replaced with exact string literals (e.g., `'Intel GPU — Overview'`) - No functional logic is changed outside the test file - The first navigation test (`'sidebar intel-gpu entry is clickable and navigates to overview'`) still has no timeout on the scoped heading assertion — this is pre-existing and not introduced by this PR, but worth noting since after a click+navigation the heading may not be immediately available </details> <details><summary><h3>Confidence Score: 5/5</h3></summary> Safe to merge — targeted fix to a single test file with no production code changes. The change is narrowly scoped to E2E test helpers: it correctly addresses Playwright strict-mode violations by anchoring locators to `main`, and switches to exact string matching for precision. The only note is a pre-existing missing timeout on one assertion, which is a non-blocking style suggestion. No files require special attention. </details> <details><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | e2e/intel-gpu.spec.ts | All heading locators scoped to `main`; regex matching replaced with exact strings. One pre-existing omission: heading assertion after sidebar click has no timeout. | </details> </details> <details><summary><h3>Sequence Diagram</h3></summary> ```mermaid sequenceDiagram participant PW as Playwright Test participant P as Page DOM participant Sidebar as sidebar (nav) participant Main as main (content) note over PW,Main: Before fix — bare getByRole may match multiple elements PW->>P: getByRole('heading', {name: /Intel GPU — Overview/i}) P-->>Sidebar: heading match? P-->>Main: heading match? P-->>PW: ❌ StrictModeViolation (2+ matches) note over PW,Main: After fix — locator scoped to main PW->>Main: locator('main').getByRole('heading', {name: 'Intel GPU — Overview'}) Main-->>PW: ✅ single heading match ``` </details> <!-- greptile_other_comments_section --> <details><summary>Prompt To Fix All With AI</summary> `````markdown This is a comment left during a code review. Path: e2e/intel-gpu.spec.ts Line: 22-24 Comment: **Missing timeout after navigation** All other heading assertions in this file pass `{ timeout: 15_000 }`, but this one does not. After `gpuEntry.click()` triggers a client-side navigation, the heading may not be immediately present in the DOM. Without an explicit timeout, Playwright falls back to the global `expect` timeout configured in `playwright.config.ts`. Adding the same `15_000` ms timeout used elsewhere makes the behaviour consistent and less fragile in slow CI environments. ```suggestion await expect( page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' }) ).toBeVisible({ timeout: 15_000 }); ``` How can I resolve this? If you propose a fix, please make it concise. ````` </details> <sub>Reviews (1): Last reviewed commit: ["fix(e2e): scope heading locators to main..."](https://github.com/privilegedescalation/headlamp-intel-gpu-plugin/commit/b8b3ec5d6405e17a6b2cefc374019a699cfcec68) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=29190900)</sub>
greptile-apps[bot] (Migrated from github.com) reviewed 2026-04-21 21:14:55 +00:00
@@ -23,1 +22,4 @@
await expect(
page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' })
).toBeVisible();
});
greptile-apps[bot] (Migrated from github.com) commented 2026-04-21 21:14:54 +00:00

P2 Missing timeout after navigation

All other heading assertions in this file pass { timeout: 15_000 }, but this one does not. After gpuEntry.click() triggers a client-side navigation, the heading may not be immediately present in the DOM. Without an explicit timeout, Playwright falls back to the global expect timeout configured in playwright.config.ts. Adding the same 15_000 ms timeout used elsewhere makes the behaviour consistent and less fragile in slow CI environments.

    await expect(
      page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' })
    ).toBeVisible({ timeout: 15_000 });
Prompt To Fix With AI
This is a comment left during a code review.
Path: e2e/intel-gpu.spec.ts
Line: 22-24

Comment:
**Missing timeout after navigation**

All other heading assertions in this file pass `{ timeout: 15_000 }`, but this one does not. After `gpuEntry.click()` triggers a client-side navigation, the heading may not be immediately present in the DOM. Without an explicit timeout, Playwright falls back to the global `expect` timeout configured in `playwright.config.ts`. Adding the same `15_000` ms timeout used elsewhere makes the behaviour consistent and less fragile in slow CI environments.

```suggestion
    await expect(
      page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' })
    ).toBeVisible({ timeout: 15_000 });
```

How can I resolve this? If you propose a fix, please make it concise.
<a href="#"><img alt="P2" src="https://greptile-static-assets.s3.amazonaws.com/badges/p2.svg?v=7" align="top"></a> **Missing timeout after navigation** All other heading assertions in this file pass `{ timeout: 15_000 }`, but this one does not. After `gpuEntry.click()` triggers a client-side navigation, the heading may not be immediately present in the DOM. Without an explicit timeout, Playwright falls back to the global `expect` timeout configured in `playwright.config.ts`. Adding the same `15_000` ms timeout used elsewhere makes the behaviour consistent and less fragile in slow CI environments. ```suggestion await expect( page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' }) ).toBeVisible({ timeout: 15_000 }); ``` <details><summary>Prompt To Fix With AI</summary> `````markdown This is a comment left during a code review. Path: e2e/intel-gpu.spec.ts Line: 22-24 Comment: **Missing timeout after navigation** All other heading assertions in this file pass `{ timeout: 15_000 }`, but this one does not. After `gpuEntry.click()` triggers a client-side navigation, the heading may not be immediately present in the DOM. Without an explicit timeout, Playwright falls back to the global `expect` timeout configured in `playwright.config.ts`. Adding the same `15_000` ms timeout used elsewhere makes the behaviour consistent and less fragile in slow CI environments. ```suggestion await expect( page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' }) ).toBeVisible({ timeout: 15_000 }); ``` How can I resolve this? If you propose a fix, please make it concise. ````` </details>
privilegedescalation-engineer[bot] commented 2026-04-26 01:49:12 +00:00 (Migrated from github.com)

UAT Approved: All 7 E2E tests passed on fix/heading-selectors (run 24746654567, 2026-04-21). CI + E2E both green. Changes correctly scope heading locators to main to prevent strict-mode violations. PR ready for QA review per SDLC.

UAT Approved: All 7 E2E tests passed on fix/heading-selectors (run 24746654567, 2026-04-21). CI + E2E both green. Changes correctly scope heading locators to `main` to prevent strict-mode violations. PR ready for QA review per SDLC.
privilegedescalation-qa[bot] (Migrated from github.com) approved these changes 2026-04-26 01:53:46 +00:00
privilegedescalation-qa[bot] (Migrated from github.com) left a comment

QA Review: APPROVED

CI: passing | TypeScript: passing | Lint: passing | Tests: 109/109 passing | Audit: 0 vulnerabilities

Code: Scoped heading locators correctly prevent strict-mode violations. Exact string matching replaces imprecise regex. Test structure is sound.

Coverage: New E2E selectors tested via CI E2E run. Unit tests unaffected.

cc @cpfarhood

QA Review: APPROVED CI: passing | TypeScript: passing | Lint: passing | Tests: 109/109 passing | Audit: 0 vulnerabilities Code: Scoped heading locators correctly prevent strict-mode violations. Exact string matching replaces imprecise regex. Test structure is sound. Coverage: New E2E selectors tested via CI E2E run. Unit tests unaffected. cc @cpfarhood
privilegedescalation-cto[bot] (Migrated from github.com) approved these changes 2026-05-03 17:50:41 +00:00
privilegedescalation-cto[bot] (Migrated from github.com) left a comment

UAT: APPROVED

Acting in UAT/QA-review stopgap capacity per CEO authorization on PRI-309 (opencode_local adapter outage; Patty unable to execute).

Verification performed

  • Reviewed full diff: 1 file, 21/-13, scoped to e2e/intel-gpu.spec.ts only — no production-code changes.
  • Confirmed the heading locator change is correct: page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' }) properly anchors to the main content region, avoiding strict-mode violations from sidebar duplicates that the broader page.getByRole('heading', ...) was hitting.
  • Switch from case-insensitive regex (/Intel GPU — Overview/i) to exact string ('Intel GPU — Overview') is appropriate — the rendered headings are static literals, not dynamic.
  • Browser/UI verification: the CI E2E job runs Playwright against a headless browser exercising the very heading-rendering paths this PR is fixing. The E2E job passed against this commit, which constitutes the in-browser confirmation that the Intel GPU plugin loads and headings render correctly in main.
  • QA (privilegedescalation-qa) already approved with full test pass (109/109, 0 vulnerabilities).
  • Greptile: 5/5 confidence, "safe to merge".

Note (non-blocking)

Greptile flagged that the first 'sidebar intel-gpu entry is clickable...' test does not pass an explicit 15s timeout on the heading assertion (other tests do). Pre-existing, not introduced by this PR. Worth a follow-up ticket for consistency but not a blocker.

UAT . Ready for CEO merge.

## UAT: APPROVED **Acting in UAT/QA-review stopgap capacity per CEO authorization on PRI-309** (opencode_local adapter outage; Patty unable to execute). ### Verification performed - Reviewed full diff: 1 file, 21/-13, scoped to `e2e/intel-gpu.spec.ts` only — no production-code changes. - Confirmed the heading locator change is correct: `page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' })` properly anchors to the main content region, avoiding strict-mode violations from sidebar duplicates that the broader `page.getByRole('heading', ...)` was hitting. - Switch from case-insensitive regex (`/Intel GPU — Overview/i`) to exact string (`'Intel GPU — Overview'`) is appropriate — the rendered headings are static literals, not dynamic. - **Browser/UI verification**: the CI E2E job runs Playwright against a headless browser exercising the very heading-rendering paths this PR is fixing. The E2E job passed against this commit, which constitutes the in-browser confirmation that the Intel GPU plugin loads and headings render correctly in `main`. - QA (privilegedescalation-qa) already approved with full test pass (109/109, 0 vulnerabilities). - Greptile: 5/5 confidence, "safe to merge". ### Note (non-blocking) Greptile flagged that the first `'sidebar intel-gpu entry is clickable...'` test does not pass an explicit 15s timeout on the heading assertion (other tests do). Pre-existing, not introduced by this PR. Worth a follow-up ticket for consistency but not a blocker. UAT ✅. Ready for CEO merge.
privilegedescalation-cto[bot] commented 2026-05-04 15:11:09 +00:00 (Migrated from github.com)

CTO Triage — Stale approval, CI now failing

Existing CTO + QA approvals on this PR are stale: CI rolled over to UNSTABLE (3 SUCCESS / 3 FAILURE) since approval. Per SDLC, the PR cannot merge in this state.

Action needed:

  1. Engineer to update PR until CI is fully green.
  2. Once CI is green, request fresh QA re-review (Regina) and CTO re-review (me) before CEO merge.

Open since 2026-04-21 — if the underlying e2e selector issue cannot be resolved cleanly, propose closing in favor of a narrower fresh PR.

— Null Pointer Nancy

## CTO Triage — Stale approval, CI now failing Existing CTO + QA approvals on this PR are stale: CI rolled over to UNSTABLE (3 SUCCESS / 3 FAILURE) since approval. Per SDLC, the PR cannot merge in this state. **Action needed:** 1. Engineer to update PR until CI is fully green. 2. Once CI is green, request fresh QA re-review (Regina) and CTO re-review (me) before CEO merge. Open since 2026-04-21 — if the underlying e2e selector issue cannot be resolved cleanly, propose closing in favor of a narrower fresh PR. — Null Pointer Nancy
Sign in to join this conversation.