Skip to content

UI Testing with ActRight + Playwright#1294

Merged
6 commits merged intomainfrom
scosman/act_right_tests
Apr 30, 2026
Merged

UI Testing with ActRight + Playwright#1294
6 commits merged intomainfrom
scosman/act_right_tests

Conversation

@scosman
Copy link
Copy Markdown
Collaborator

@scosman scosman commented Apr 20, 2026

New UI testing setup.

Should install ActRight skill: https://github.com/scosman/ActRight

1s demo video:
https://github.com/user-attachments/assets/544d2b1e-b8e2-45bf-b01d-0284a676e5d4

Summary by CodeRabbit

  • Tests

    • Added a Playwright E2E suite covering app load, task edit/clone/delete flows, fixtures, and sanity checks.
    • New shared fixtures, API helpers, and a global readiness setup ensure reproducible seeded projects/tasks and reliable polling/retries.
    • Configured serial execution, CI retries, and HTML trace/reporting.
  • Chores

    • CI workflow added to run E2E tests and upload reports on pushes/PRs.
    • Gitignore and npm scripts updated to support E2E tooling and Playwright artifacts.

scosman and others added 3 commits April 19, 2026 21:30
Scaffolds the ActRight / Playwright harness for the Kiln web UI:

- Installs @playwright/test and @playwright/mcp (chromium only) in app/web_ui
- playwright.config.ts with testDir tests/e2e, baseURL http://localhost:6534,
  workers: 1 (shared backend), and a webServer array that starts the FastAPI
  dev_server on port 6535 with HOME redirected to a gitignored .e2e_home dir
  for state isolation, plus Vite on 6534
- .github/workflows/playwright.yml (monorepo-aware, installs uv + npm deps)
- Two sanity tests (act_sanity for install, act_app_loads for the full stack)
- Core fixtures in tests/e2e/fixtures.ts: freshState, registeredUser,
  seededProject, seededProjectWithTask -- backed by /api/projects, /api/tasks,
  and /api/settings, with act docstrings for ActRight

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Six new act-managed Playwright tests covering the edit task screen: load,
save, read-only schemas, clone button, delete flow, and breadcrumb nav.

Setup fixes needed to make browser-originated fetches work:
- Pass KILN_FRONTEND_PORT=6534 to the backend so its CORS allow-list
  matches the Vite dev port (defaulted to 5173).
- Add globalSetup that polls both servers with real requests, since
  the webServer url check is a one-shot probe and a page's own fetches
  can race a still-warming service.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6f7a2fd6-e369-425a-b83f-e2973a060ab3

📥 Commits

Reviewing files that changed from the base of the PR and between d900ed3 and 8cecf99.

⛔ Files ignored due to path filters (1)
  • app/web_ui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • .github/workflows/playwright.yml
  • app/web_ui/package.json
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/playwright.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/web_ui/package.json

📝 Walkthrough

Walkthrough

Adds Playwright end-to-end tests, support fixtures and readiness gating, a Playwright config and npm script, .gitignore updates, and a GitHub Actions workflow that runs Playwright tests and uploads HTML reports.

Changes

Cohort / File(s) Summary
CI Workflow
​.github/workflows/playwright.yml
New GitHub Actions workflow "Playwright Tests": runs on push/PR for main, sets Node/Python, installs uv, syncs Python deps, runs npm ci, installs Playwright browsers, executes npx playwright test, and uploads app/web_ui/playwright-report/ artifact (30-day retention).
Project config & ignores
app/web_ui/package.json, app/web_ui/.gitignore, app/web_ui/playwright.config.ts
Adds tests:e2e npm script, adds @playwright/test and @types/node devDeps, ignores Playwright artifacts/caches, and introduces Playwright config with globalSetup, single-worker mode, HTML reporter, trace-on-retry, Desktop Chrome project, and two managed dev servers (backend Python and frontend npm dev) with readiness probes and isolated HOME.
Test support & helpers
app/web_ui/tests/e2e/fixtures.ts, app/web_ui/tests/e2e/ports.ts, app/web_ui/tests/e2e/global-setup.ts
Adds fixtures exporting apiRequest, cleanBackend, registeredUser, seededProject, seededProjectWithTask and types; defines ports/URLs; and implements globalSetup that polls backend and frontend until they are stable.
E2E specs
app/web_ui/tests/e2e/act_sanity.spec.ts, app/web_ui/tests/e2e/act_fixtures.spec.ts, app/web_ui/tests/e2e/act_app_loads.spec.ts, app/web_ui/tests/e2e/act_edit_task.spec.ts
Adds sanity test, fixture-driven redirect tests, root-page load/title check, and comprehensive edit-task spec covering load, save (with API polling), read-only schema checks, clone/delete flows, and navigation assertions.

Sequence Diagrams

sequenceDiagram
    participant CI as CI Job (GitHub Actions)
    participant Runner as Runner (ubuntu-latest)
    participant Repo as Repository
    participant Playwright as Playwright Test
    participant Artifact as Artifact Storage

    CI->>Runner: checkout repo, set working dir ./app/web_ui
    Runner->>Runner: setup Node (lts/*), setup Python 3.13, install uv
    Runner->>Runner: uv sync (Python deps), npm ci, install Playwright browsers
    Runner->>Playwright: npx playwright test (globalSetup + tests)
    Playwright-->>Artifact: upload app/web_ui/playwright-report/ (retain 30d)
Loading
sequenceDiagram
    actor GlobalSetup
    participant Req as RequestContext
    participant Backend as Backend API (localhost:6535)
    participant Frontend as Frontend Web (localhost:6534)

    GlobalSetup->>Req: create context for BACKEND_URL and FRONTEND_URL
    GlobalSetup->>Backend: poll /api/projects until consecutive 200 responses
    Backend-->>Req: 200 JSON or error
    GlobalSetup->>Frontend: poll / until 200 and HTML doctype observed
    Frontend-->>Req: 200 HTML or error
    Req->>Req: dispose
    GlobalSetup-->>GlobalSetup: return when both ready
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested Reviewers

  • leonardmq

Poem

🐰 I hopped through configs, seeds in paw,
servers woke, the pages saw,
clicks and polls keep tests in tune,
reports saved neat beneath the moon,
carrots for CI — ready soon! 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal and does not follow the repository template. Missing required sections: 'What does this PR do?', 'Related Issues', contributor license agreement confirmation, and checklists. Expand the description to include all template sections: detailed PR objectives, linked issues, CLA confirmation with GitHub username, and completed checklists for testing.
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 (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'UI Testing with ActRight + Playwright' accurately summarizes the main change: introducing a new UI testing framework combining ActRight and Playwright.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch scosman/act_right_tests

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 and usage tips.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 20, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​types/​node@​20.12.12 ⏵ 22.19.17100 +110081 +195100
Addednpm/​@​playwright/​test@​1.59.110010010099100

View full report

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an end-to-end testing suite using Playwright, including configuration, global setup for service readiness, and custom fixtures for state management. The changes add several test suites covering core application flows such as task editing, project seeding, and general app loading. Feedback focuses on improving cross-platform compatibility for directory cleanup in the Playwright configuration and ensuring proper resource cleanup in test fixtures to maintain state isolation.

Comment thread app/web_ui/playwright.config.ts
Comment thread app/web_ui/tests/e2e/fixtures.ts
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 20, 2026

📊 Coverage Report

Overall Coverage: 91%

Diff: origin/main...HEAD

No lines with coverage information in this diff.


Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (4)
.github/workflows/playwright.yml (2)

29-32: Browsers cache would speed up CI noticeably.

npx playwright install --with-deps chromium re-downloads the browser every run. Consider caching ~/.cache/ms-playwright keyed on the resolved @playwright/test version (e.g., from package-lock.json) and skipping the download on cache hit (still running --with-deps to pull the apt packages, or splitting into a deps-only step).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/playwright.yml around lines 29 - 32, The Playwright step
always re-downloads browsers; modify the workflow to cache the Playwright
browser cache (~/.cache/ms-playwright) keyed by the resolved `@playwright/test`
version (derive hash from package-lock.json or package.json resolution) and
change the "npx playwright install --with-deps chromium" step to skip download
when the cache is a hit (keep running --with-deps for apt packages or split into
a deps-only step). Locate the existing "npx playwright install --with-deps
chromium" and "npx playwright test" steps and add a cache restore/save around
them using the computed key so the install is skipped on cache hit.

2-6: Consider narrowing triggers to avoid double runs.

With both push and pull_request on main/master, PRs from branches in this repo will run twice (once for the push, once for the PR). A common pattern is to trigger push only on main/master (for post-merge runs) and pull_request for everything else, plus adding a concurrency group to cancel superseded runs on force-pushes to a PR:

Suggested change
on:
  push:
    branches: [ main, master ]
  pull_request:
concurrency:
  group: playwright-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/playwright.yml around lines 2 - 6, The workflow currently
triggers both push and pull_request for branches [ main, master ], causing PRs
to run twice; update the on: section so push remains limited to branches: [
main, master ] while pull_request has no branch filter (so it runs for all PRs),
and add a concurrency block (using a group like playwright-${{ github.workflow
}}-${{ github.ref }} and cancel-in-progress: ${{ github.event_name ==
'pull_request' }}) to ensure superseded PR runs are cancelled; modify the
existing on:, push, pull_request keys and add the new concurrency keys
accordingly.
app/web_ui/tests/e2e/act_fixtures.spec.ts (1)

84-95: Also assert the fetched task id matches.

Symmetric with the seededProject test (line 69) which checks fetched.id === seededProject.id. Without it, the endpoint could return a different task (or stub) and the test would still pass.

   expect(resp.ok()).toBeTruthy()
+  const fetched = await resp.json()
+  expect(fetched.id).toBe(task.id)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/web_ui/tests/e2e/act_fixtures.spec.ts` around lines 84 - 95, The test
seeded_project_with_task fixture should assert the fetched task ID equals the
seeded task ID: after the apiRequest GET call in the test function
seededProjectWithTask, parse the response body (e.g. await resp.json()) and add
an assertion that the returned task's id matches task.id from the
seededProjectWithTask fixture so the endpoint is verified to return the correct
resource.
app/web_ui/tests/e2e/act_edit_task.spec.ts (1)

220-249: Delete confirmation dialog filter may match too loosely.

page.getByRole("dialog").filter({ hasText: "Delete Task?" }) will also match a dialog whose body text happens to contain the substring (e.g., if the title is rendered elsewhere). Consider constraining via an accessible name or heading to make the selector less brittle:

-  const dialog = page.getByRole("dialog").filter({ hasText: "Delete Task?" })
+  const dialog = page.getByRole("dialog", { name: "Delete Task?" })

Also, because this test deletes the task, seededProjectWithTask's teardown will issue a DELETE against the already-removed task. The teardown's .catch(() => {}) only swallows thrown errors, not non-2xx responses, so the 404 is silently ignored — this is fine, just noting the interaction is intentional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/web_ui/tests/e2e/act_edit_task.spec.ts` around lines 220 - 249, The
dialog selector is too loose: replace page.getByRole("dialog").filter({ hasText:
"Delete Task?" }) with an accessibility-bound selector that targets the dialog
by its accessible name or heading (e.g., page.getByRole("dialog", { name:
"Delete Task?" }) or locate the dialog then use dialog.getByRole("heading", {
name: "Delete Task?" })) so the test matches the actual delete confirmation
title reliably; keep the rest of the flow (clicking the Delete button, URL
assertion, and API poll) as-is and be aware seededProjectWithTask teardown will
attempt to delete the same task but can remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/web_ui/package.json`:
- Line 30: The devDependency "@types/node" in package.json is pinned to
"^25.6.0" which mismatches the CI Node runtime (20.20.2); update the
package.json dependency entry for "@types/node" to a version that matches your
CI Node major (e.g., change "@types/node" to "^20") so type definitions align
with the runtime, or alternatively update the CI Node version to a newer LTS and
pin "@types/node" to that major instead.

In `@app/web_ui/playwright.config.ts`:
- Around line 76-90: The webServer.command currently uses POSIX shell commands
(rm -rf and mkdir -p) which fail on Windows; move the TEST_HOME cleanup out of
the webServer.command into a Node-based setup (e.g., globalSetup) that uses
fs.rmSync(TEST_HOME, { recursive: true, force: true }) and
fs.mkdirSync(TEST_HOME, { recursive: true }) and then set webServer.command to
just start the server ("uv run python -m app.desktop.dev_server"); update the
Playwright config to call that globalSetup and remove the shell cleanup from the
webServer entry so TEST_HOME is created cross-platform and not wiped on
Playwright retries.
- Around line 28-29: The CI retry policy (retries) is causing flaky masking
because tests reuse the same backend process due to fullyParallel: false,
workers: 1 and reuseExistingServer: false; either set retries to 0 (change the
retries variable) until fixtures are isolated, or implement a cleanup/restart
path that wipes the shared fixture directory (e.g., remove or recreate
".e2e_home") and fully restarts the backend between retry attempts so tests like
those depending on freshState see a clean environment; update the playright
config logic around retries and add the cleanup/restart hook invoked before any
retry.

In `@app/web_ui/tests/e2e/act_fixtures.spec.ts`:
- Around line 14-21: The test "fresh_state fixture: backend starts with no
projects" currently only checks resp.ok(); update it to verify the projects list
is empty by parsing the response JSON from apiRequest.get("/api/projects") and
asserting the returned array length is 0 (and optionally that resp.status() ===
200). Use the existing freshState fixture and replace the loose resp.ok()
assertion with explicit checks on resp.json() (or resp.text() parsed to JSON) to
ensure no projects are present.

In `@app/web_ui/tests/e2e/fixtures.ts`:
- Around line 73-95: The seededProject fixture lacks proper teardown so projects
persist and outlive seededProjectWithTask; update the seededProject fixture
(named seededProject) to perform cleanup after await use() by deleting the
created project via the same apiRequest (e.g., call DELETE
/api/projects/${encodeURIComponent(project.id)}) and catch/swallow errors so
Playwright can dispose fixtures in reverse order and seededProjectWithTask’s
task cleanup runs before the project is removed.
- Around line 36-71: The seededProject fixture leaks created projects because it
posts a project in seededProject without deleting it on teardown, causing
freshState (which expects zero projects) to fail for later tests; update
seededProject to perform a best-effort cleanup in its teardown by calling the
project delete endpoint (e.g., DELETE /api/projects/:id using the returned
project.id or slug) after use(), mirroring the cleanup pattern in
seededProjectWithTask; if no delete API exists, instead modify freshState to
actively reset server state or scope freshState to a dedicated worker so tests
do not share persistent HOME=.e2e_home state.

---

Nitpick comments:
In @.github/workflows/playwright.yml:
- Around line 29-32: The Playwright step always re-downloads browsers; modify
the workflow to cache the Playwright browser cache (~/.cache/ms-playwright)
keyed by the resolved `@playwright/test` version (derive hash from
package-lock.json or package.json resolution) and change the "npx playwright
install --with-deps chromium" step to skip download when the cache is a hit
(keep running --with-deps for apt packages or split into a deps-only step).
Locate the existing "npx playwright install --with-deps chromium" and "npx
playwright test" steps and add a cache restore/save around them using the
computed key so the install is skipped on cache hit.
- Around line 2-6: The workflow currently triggers both push and pull_request
for branches [ main, master ], causing PRs to run twice; update the on: section
so push remains limited to branches: [ main, master ] while pull_request has no
branch filter (so it runs for all PRs), and add a concurrency block (using a
group like playwright-${{ github.workflow }}-${{ github.ref }} and
cancel-in-progress: ${{ github.event_name == 'pull_request' }}) to ensure
superseded PR runs are cancelled; modify the existing on:, push, pull_request
keys and add the new concurrency keys accordingly.

In `@app/web_ui/tests/e2e/act_edit_task.spec.ts`:
- Around line 220-249: The dialog selector is too loose: replace
page.getByRole("dialog").filter({ hasText: "Delete Task?" }) with an
accessibility-bound selector that targets the dialog by its accessible name or
heading (e.g., page.getByRole("dialog", { name: "Delete Task?" }) or locate the
dialog then use dialog.getByRole("heading", { name: "Delete Task?" })) so the
test matches the actual delete confirmation title reliably; keep the rest of the
flow (clicking the Delete button, URL assertion, and API poll) as-is and be
aware seededProjectWithTask teardown will attempt to delete the same task but
can remain unchanged.

In `@app/web_ui/tests/e2e/act_fixtures.spec.ts`:
- Around line 84-95: The test seeded_project_with_task fixture should assert the
fetched task ID equals the seeded task ID: after the apiRequest GET call in the
test function seededProjectWithTask, parse the response body (e.g. await
resp.json()) and add an assertion that the returned task's id matches task.id
from the seededProjectWithTask fixture so the endpoint is verified to return the
correct resource.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4b030e73-dcf2-4f58-baff-ce2115963578

📥 Commits

Reviewing files that changed from the base of the PR and between dfb901d and a6cf817.

⛔ Files ignored due to path filters (1)
  • app/web_ui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • .github/workflows/playwright.yml
  • app/web_ui/.gitignore
  • app/web_ui/package.json
  • app/web_ui/playwright.config.ts
  • app/web_ui/tests/e2e/act_app_loads.spec.ts
  • app/web_ui/tests/e2e/act_edit_task.spec.ts
  • app/web_ui/tests/e2e/act_fixtures.spec.ts
  • app/web_ui/tests/e2e/act_sanity.spec.ts
  • app/web_ui/tests/e2e/fixtures.ts
  • app/web_ui/tests/e2e/global-setup.ts

Comment thread app/web_ui/package.json Outdated
Comment thread app/web_ui/playwright.config.ts
Comment thread app/web_ui/playwright.config.ts
Comment thread app/web_ui/tests/e2e/act_fixtures.spec.ts Outdated
Comment thread app/web_ui/tests/e2e/fixtures.ts Outdated
Comment thread app/web_ui/tests/e2e/fixtures.ts
scosman and others added 2 commits April 20, 2026 12:23
Prevents leaked projects from failing the freshState assertion when tests
run serially against a shared backend.
Make fixtures really put the app into clean states, and validate each
fixture's UI goal in a browser so fixture tests exercise the same paths
(CORS, Vite readiness, ui_state redirect) that real UI tests hit.

- Centralize frontend/backend ports + URLs in tests/e2e/ports.ts.
- Rename freshState -> cleanBackend; actively delete projects and clear
  settings instead of only asserting empty state.
- Have registeredUser and seededProject depend on cleanBackend so every
  test starts from a reset.
- Roll ui_state localStorage priming into seededProjectWithTask; drop
  the primeUiState helper from act_edit_task.spec.ts.
- Rewrite act_fixtures.spec.ts to open a browser and assert the
  redirect/heading each fixture is supposed to produce.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/web_ui/tests/e2e/act_edit_task.spec.ts (1)

205-205: Delete button locator is brittle to duplicate icons.

button:has(img[src$="/images/delete.svg"]) will silently match the first candidate if the page ever renders another button with the same icon (e.g., a row-level delete). A stable aria-label/title/data-testid would make the intent explicit and survive future markup changes. Not blocking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/web_ui/tests/e2e/act_edit_task.spec.ts` at line 205, The current locator
"button:has(img[src$=\"/images/delete.svg\"])" is brittle and can match the
wrong delete icon; update the test to target a stable attribute (e.g.,
aria-label, title, or data-testid) on the intended delete control instead of
relying on the image selector, and if that attribute doesn't exist add one to
the corresponding element in the UI so the test can use something like
page.locator('[data-testid="..."]') or locator('button[aria-label="..."]') to
unambiguously select the correct delete button.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/web_ui/tests/e2e/act_edit_task.spec.ts`:
- Line 205: The current locator "button:has(img[src$=\"/images/delete.svg\"])"
is brittle and can match the wrong delete icon; update the test to target a
stable attribute (e.g., aria-label, title, or data-testid) on the intended
delete control instead of relying on the image selector, and if that attribute
doesn't exist add one to the corresponding element in the UI so the test can use
something like page.locator('[data-testid="..."]') or
locator('button[aria-label="..."]') to unambiguously select the correct delete
button.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a8d8f714-dd16-4398-9173-0c6335f1603a

📥 Commits

Reviewing files that changed from the base of the PR and between 792ef10 and d900ed3.

📒 Files selected for processing (6)
  • app/web_ui/playwright.config.ts
  • app/web_ui/tests/e2e/act_edit_task.spec.ts
  • app/web_ui/tests/e2e/act_fixtures.spec.ts
  • app/web_ui/tests/e2e/fixtures.ts
  • app/web_ui/tests/e2e/global-setup.ts
  • app/web_ui/tests/e2e/ports.ts
✅ Files skipped from review due to trivial changes (1)
  • app/web_ui/tests/e2e/ports.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/web_ui/tests/e2e/act_fixtures.spec.ts

- Drop unused @playwright/mcp devDep (was pulling playwright 1.60.0-alpha
  transitively; .mcp.json uses npx @latest, so no manifest pin is needed)
- Pin @types/node to ^22.0.0 to match CI's Node LTS runtime
- Playwright workflow: add paths filter, cancel-in-progress concurrency,
  drop master branch, align setup-uv to @V3 with enable-cache (repo convention)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@scosman scosman closed this pull request by merging all changes into main in 1502495 Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant