Skip to content

test(webview): add Playwright visual regression harness#526

Open
edelauna wants to merge 9 commits into
mainfrom
issue/515
Open

test(webview): add Playwright visual regression harness#526
edelauna wants to merge 9 commits into
mainfrom
issue/515

Conversation

@edelauna

@edelauna edelauna commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Related Issue

Closes: #515

Description

Adds a Playwright component-testing (CT) visual regression layer to webview-ui/ for components where layout, VS Code theme variables, or web-component rendering are under test—scenarios that Vitest/jsdom cannot verify. Also configures Playwright CT code coverage collection and Codecov ratcheting.

What was added:

  • Visual Test Harness & Runner:

    • webview-ui/playwright-ct.config.ts — Component test config with Vite path aliases, vscode mock alias, absolute CI output paths, and publicDir pointing to src/assets/images.
    • webview-ui/playwright/ — Harness setup: index.html applies the vscode-dark body class; index.tsx loads VS Code CSS variables, codicons, app stylesheet, and seeds window.IMAGES_BASE_URI; vscode-theme-dark.css provides a complete set of --vscode-* tokens for Default Dark Modern theme.
    • webview-ui/playwright/run-docker.mjs & docker-compose.visual.yml — Reproducible baseline Docker execution environment using a pinned Playwright Noble container, detecting Compose v2/v1 automatically.
    • .github/workflows/visual-regression.yml — CI workflow triggered on webview-ui/** and src/shared/** changes; runs inside the pinned Playwright container and uploads test artifacts on failure.
  • Reference Visual Test:

    • src/components/welcome/__tests__/RooHero.visual.tsx — Reference visual test rendering the welcome branding hero (RooHero) with font readiness and requestAnimationFrame flushes before screenshotting.
  • Code Coverage & Ratcheting Integration:

    • webview-ui/playwright/coverage-fixture.ts — Custom Playwright fixture extracting Istanbul coverage objects from CT page contexts and emitting LCOV reports.
    • codecov.yml & .github/workflows/code-qa.yml — Configured webview JSDOM and Playwright CT coverage targets and ratcheting rules.
  • Docs & Tooling Configuration:

    • webview-ui/AGENTS.md — Authoring guidance, multi-browser constraints, Docker baseline requirement, and coverage notes.
    • knip.json, vitest.config.ts, tsconfig.json, .gitignore — Ignore/exclude visual test artifacts, coverage reports, and Playwright files from Vitest/build.

Key Technical Decisions:

  • Docker as Source of Truth: Baseline screenshots are generated strictly inside the pinned Linux container to avoid cross-OS rendering differences. Host-rendered screenshots are not committed.
  • Absolute Output Paths: outputDir and HTML reporter output paths are resolved via path.resolve(__dirname, ...) so artifacts land predictably in webview-ui/ regardless of working directory.
  • Toolkit-Free Target Selection: The initial test targets RooHero (a toolkit-free component). Components rendering @vscode/webview-ui-toolkit/react primitives currently trigger module-cycle scope-hoisting issues in Vite 8 / Rolldown (vitejs/vite#22583). Toolkit-based visual tests will be supported once the app migrates off the archived toolkit or Rolldown fixes the issue.

Test Procedure

Run visual tests locally (via Docker):

cd webview-ui
pnpm test:visual:docker

Regenerate baselines after intentional UI changes:

cd webview-ui
pnpm test:visual:docker:update
# Commit updated __screenshots__ files alongside component changes

CI Verification:

  • Webview Visual Regression workflow runs automatically on PRs touching webview-ui/** or src/shared/**.
  • Code Quality workflow collects Playwright CT coverage and enforces Codecov ratcheting.

Pre-Submission Checklist

  • Issue Linked: Closes [ENHANCEMENT] Add Docker-backed Playwright visual smoke testing for webview-ui #515
  • Scope: Changes limited to visual regression infrastructure, reference test, and coverage configuration
  • Self-Review: Completed
  • Testing: Docker visual comparison, CI artifact generation, pnpm check-types, pnpm lint, and all Vitest unit tests pass
  • Documentation Impact: webview-ui/AGENTS.md updated with authoring guidance, Docker requirements, and coverage details
  • Contribution Guidelines: Read and agreed

Summary by CodeRabbit

  • Tests

    • Added Playwright component visual testing for the webview, including dark-theme and hover-state snapshots.
    • Added local and Docker-based commands for running visual tests and updating snapshots.
    • Added automated visual regression checks and failure artifacts in CI.
  • Documentation

    • Updated contribution guidance with visual snapshot requirements and testing recommendations.
  • Chores

    • Improved webview coverage reporting and quality gates, with separate coverage tracking for visual tests.

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e8afbe47-6998-43f7-8691-372951b65d4a

📥 Commits

Reviewing files that changed from the base of the PR and between 4401e58 and 0382bd5.

📒 Files selected for processing (2)
  • .github/pull_request_template.md
  • webview-ui/AGENTS.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • webview-ui/AGENTS.md

📝 Walkthrough

Walkthrough

Adds Docker-backed Playwright component testing for webview-ui, RooHero visual snapshots, CI execution, per-test coverage collection, and Codecov webview quality gates. Testing guidance, dependency analysis, ignore rules, and the pull request template are updated accordingly.

Changes

Webview visual testing

Layer / File(s) Summary
Playwright component-test harness
webview-ui/package.json, webview-ui/playwright-ct.config.ts, webview-ui/playwright/*, webview-ui/vscode-theme-dark.css, webview-ui/tsconfig.json
Configures React/Vite component testing, dark-theme rendering, fixed screenshot settings, visual-test scripts, and automatic JavaScript/CSS coverage collection.
Visual test execution and CI workflow
webview-ui/src/components/welcome/__tests__/RooHero.visual.tsx, webview-ui/docker-compose.visual.yml, webview-ui/playwright/run-docker.mjs, .github/workflows/visual-regression.yml, webview-ui/vitest.config.ts, webview-ui/.gitignore
Adds stable default and hovered RooHero screenshots, Docker-based execution, Playwright artifact handling, path-filtered CI runs, and coverage/artifact exclusions.
Coverage quality gates and testing guidance
codecov.yml, .github/workflows/code-qa.yml, knip.json, webview-ui/AGENTS.md, .github/pull_request_template.md
Separates webview Codecov uploads, defines webview flags and components, adds coverage thresholds, updates dependency checks, and documents visual snapshot practices.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant PlaywrightContainer
  participant PlaywrightCT
  participant Codecov
  GitHubActions->>PlaywrightContainer: Run filtered visual workflow
  PlaywrightContainer->>PlaywrightCT: Execute RooHero screenshot tests
  PlaywrightCT->>Codecov: Upload coverage-ct/lcov.info
Loading

Possibly related issues

  • Zoo-Code-Org/Zoo-Code issue 517: The shared provider harness described there could build on this Playwright visual-testing infrastructure.

Possibly related PRs

Suggested labels: awaiting-review

Suggested reviewers: navedmerchant

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning It builds the harness, but the required screenshot target is ProgressIndicator and the PR uses RooHero instead, missing a core #515 acceptance criterion. Add the committed visual baseline for ProgressIndicator using the real toolkit component, or revise the linked issue to accept RooHero as the proof of concept.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately captures the main change: adding a Playwright visual regression harness.
Description check ✅ Passed The description includes the required issue link, implementation summary, test procedure, and checklist; only optional sections are unfilled.
Out of Scope Changes check ✅ Passed The changed workflows, harness files, coverage config, and docs all support the visual regression feature; no unrelated scope creep is evident.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue/515

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@edelauna edelauna changed the title test(webview): add visual regression harness test(webview): add Playwright visual regression harness Jun 7, 2026
@codecov

codecov Bot commented Jun 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/visual-regression.yml:
- Around line 27-28: Update the actions/checkout step in the visual regression
workflow to set persist-credentials to false, preventing the checkout action
from retaining the GITHUB_TOKEN while PR-controlled test results are present.
Keep the existing pinned checkout action unchanged.

In `@knip.json`:
- Line 7: Update the Knip configuration entry for the playwright-ct plugin from
disabled to enabled so Knip discovers webview-ui/playwright/index.tsx and the
custom Playwright CT test files, while preserving the existing CT dependency
handling.

In `@webview-ui/package.json`:
- Line 12: Remove the test:visual:update script from package.json so committed
visual snapshots cannot be generated through host rendering. Preserve
test:visual:docker:update as the supported baseline-update command, consistent
with the Docker-only source-of-truth workflow.

In `@webview-ui/playwright-ct.config.ts`:
- Around line 16-18: The visual regression workflow uploads CT coverage that is
never generated. Update the Playwright CT reporter configuration in
webview-ui/playwright-ct.config.ts and the test:visual script in
webview-ui/package.json to collect and write coverage to
webview-ui/coverage-ct/lcov.info before upload, or remove the coverage upload if
CT coverage is not intended.

In `@webview-ui/playwright/run-docker.mjs`:
- Line 18: Update webview-ui/playwright/run-docker.mjs at line 18 to pass an
environment object to spawnSync that sets UID and GID from process.getuid() and
process.getgid(), while preserving any explicit environment overrides. Update
webview-ui/docker-compose.visual.yml at line 5 to replace the 1000 UID/GID
fallbacks with required interpolation or a clear missing-variable error,
preventing direct Compose usage from silently selecting another identity.

In `@webview-ui/playwright/vscode-theme-dark.css`:
- Around line 3-6: Update the font-family declarations in the theme stylesheet
to lowercase the value keywords BlinkMacSystemFont, Consolas, and Menlo,
preserving the existing font order and fallback values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8d17b0be-d4c4-4795-b8db-5677e1af1c4c

📥 Commits

Reviewing files that changed from the base of the PR and between 7af1a8a and 32b1842.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • webview-ui/src/components/welcome/__tests__/__screenshots__/zoo-hero-dark.png is excluded by !**/*.png
📒 Files selected for processing (16)
  • .github/workflows/code-qa.yml
  • .github/workflows/visual-regression.yml
  • codecov.yml
  • knip.json
  • webview-ui/.gitignore
  • webview-ui/AGENTS.md
  • webview-ui/docker-compose.visual.yml
  • webview-ui/package.json
  • webview-ui/playwright-ct.config.ts
  • webview-ui/playwright/index.html
  • webview-ui/playwright/index.tsx
  • webview-ui/playwright/run-docker.mjs
  • webview-ui/playwright/vscode-theme-dark.css
  • webview-ui/src/components/welcome/__tests__/RooHero.visual.tsx
  • webview-ui/tsconfig.json
  • webview-ui/vitest.config.ts

Comment thread .github/workflows/visual-regression.yml
Comment thread knip.json
Comment thread webview-ui/package.json Outdated
Comment thread webview-ui/playwright-ct.config.ts Outdated
Comment thread webview-ui/playwright/run-docker.mjs Outdated
Comment thread webview-ui/playwright/vscode-theme-dark.css
@github-actions github-actions Bot added awaiting-review PR changes are ready and waiting for maintainer re-review and removed awaiting-review PR changes are ready and waiting for maintainer re-review labels Jul 23, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
webview-ui/playwright/monocart-reporter.d.ts (1)

1-3: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Align the local declaration with the package’s coverage API.

monocart-reporter@2.9.20 types testInfo as Playwright TestInfo, but coverageData as any[] | any. Replace this local any[] and add a local/external coverage-data type if invalid coverage payloads should not be allowed at this integration boundary.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webview-ui/playwright/monocart-reporter.d.ts` around lines 1 - 3, Update the
addCoverageReport declaration in the monocart-reporter module to match
monocart-reporter@2.9.20: type testInfo as Playwright TestInfo and coverageData
as any[] | any, or introduce a suitable local/external coverage-data type that
preserves the package’s accepted shapes while rejecting invalid payloads.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@webview-ui/src/components/welcome/__tests__/RooHero.visual.tsx`:
- Around line 31-40: Generate the missing hovered-state screenshot baseline for
the RooHero visual test using the Docker-backed visual test workflow, then
commit zoo-hero-dark-hover.png. Use pnpm test:visual:docker for comparison and
pnpm test:visual:docker:update only to intentionally create or update the
baseline.

---

Nitpick comments:
In `@webview-ui/playwright/monocart-reporter.d.ts`:
- Around line 1-3: Update the addCoverageReport declaration in the
monocart-reporter module to match monocart-reporter@2.9.20: type testInfo as
Playwright TestInfo and coverageData as any[] | any, or introduce a suitable
local/external coverage-data type that preserves the package’s accepted shapes
while rejecting invalid payloads.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 58e3683d-b3b3-4758-aa3e-8611fdc47672

📥 Commits

Reviewing files that changed from the base of the PR and between df36498 and aac072e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • .github/workflows/visual-regression.yml
  • knip.json
  • webview-ui/.gitignore
  • webview-ui/AGENTS.md
  • webview-ui/docker-compose.visual.yml
  • webview-ui/package.json
  • webview-ui/playwright-ct.config.ts
  • webview-ui/playwright/coverage-fixture.ts
  • webview-ui/playwright/monocart-reporter.d.ts
  • webview-ui/playwright/run-docker.mjs
  • webview-ui/src/components/welcome/__tests__/RooHero.visual.tsx
  • webview-ui/vitest.config.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • .github/workflows/visual-regression.yml
  • webview-ui/docker-compose.visual.yml
  • webview-ui/vitest.config.ts
  • webview-ui/package.json
  • webview-ui/playwright/run-docker.mjs
  • knip.json
  • webview-ui/AGENTS.md
  • webview-ui/playwright-ct.config.ts

Comment on lines +31 to +40
test("renders the welcome hero hovered state", async ({ mount }) => {
const component = await mount(<RooHero />)

await waitForAssetsAndRender(component)
await component.hover()

await expect(component).toHaveScreenshot("zoo-hero-dark-hover.png", {
animations: "disabled",
})
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Commit the hovered-state baseline before merging.

The CI check reports that zoo-hero-dark-hover.png is missing, so the assertion at Line 37 fails. Generate and commit the expected snapshot using the Docker-backed visual test workflow.

As per coding guidelines, use pnpm test:visual:docker for comparison and pnpm test:visual:docker:update only for intentional baseline updates.

🧰 Tools
🪛 GitHub Actions: Webview Visual Regression / 0_webview-visual.txt

[error] 31-31: Playwright visual test failed: "renders the welcome hero hovered state" (chromium).

🪛 GitHub Actions: Webview Visual Regression / webview-visual

[error] 31-31: Playwright visual test failed for hovered state. Step: "playwright test -c playwright-ct.config.ts". Test: "renders the welcome hero hovered state" (chromium).

🪛 GitHub Check: webview-visual

[failure] 37-37: [chromium] › src/components/welcome/tests/RooHero.visual.tsx:31:1 › renders the welcome hero hovered state

  1. [chromium] › src/components/welcome/tests/RooHero.visual.tsx:31:1 › renders the welcome hero hovered state
    Error: A snapshot doesn't exist at /__w/Zoo-Code/Zoo-Code/webview-ui/src/components/welcome/tests/screenshots/zoo-hero-dark-hover.png, writing actual.

    35 | await component.hover()
    36 |
    > 37 | await expect(component).toHaveScreenshot("zoo-hero-dark-hover.png", {
    | ^
    38 | animations: "disabled",
    39 | })
    40 | })
    at /__w/Zoo-Code/Zoo-Code/webview-ui/src/components/welcome/tests/RooHero.visual.tsx:37:2

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webview-ui/src/components/welcome/__tests__/RooHero.visual.tsx` around lines
31 - 40, Generate the missing hovered-state screenshot baseline for the RooHero
visual test using the Docker-backed visual test workflow, then commit
zoo-hero-dark-hover.png. Use pnpm test:visual:docker for comparison and pnpm
test:visual:docker:update only to intentionally create or update the baseline.

Sources: Coding guidelines, Linters/SAST tools

@github-actions github-actions Bot added the awaiting-review PR changes are ready and waiting for maintainer re-review label Jul 23, 2026
@github-actions github-actions Bot added awaiting-review PR changes are ready and waiting for maintainer re-review and removed awaiting-review PR changes are ready and waiting for maintainer re-review labels Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR changes are ready and waiting for maintainer re-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ENHANCEMENT] Add Docker-backed Playwright visual smoke testing for webview-ui

1 participant