Repository navigation
refactor: migrate tests from cypress to playwright - #11089
robert-hebel-sb wants to merge 14 commits into
Conversation
Add @playwright/test and @types/cors (pinned), playwright.config.ts, a strict tsconfig scoped to test/e2e-playwright, a shared `test` fixture, and TS ports of the OAuth2 test server and multiple-examples helper. Move static/ and fixtures/ to test/e2e-playwright and point the dev-e2e webpack server at the new location. Replace cy:* scripts with e2e:*. Migrate deep-linking and security/oauth2 specs as proof. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Includes the deep-linking and security/oauth2 proof specs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
info and license each carry one test.fixme: the Cypress versions of those assertions passed vacuously (checked before render) and the app/fixture behave differently from what the tests claim. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Install chromium, cache ~/.cache/ms-playwright, shard with --shard=N/4 and upload the HTML report and traces on failure. Drop the Cypress cache. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Remove cypress and start-server-and-test, cypress.config.js, the remaining Cypress files and the temporary migration inventory. Update README, CLAUDE.md, docs/development and .claude guidance for Playwright. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
info-openAPI30.yaml declared openapi 3.1.0, so the 3.1-only summary was rendered; declare 3.0.0 and wait for render before asserting absence. The license test claimed nothing renders when url and identifier are both set, but the app lets url win; assert that instead. bugs/5138 uses a real 3s wait again, matching the original cy.wait(3000). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> # Conflicts: # package-lock.json
There was a problem hiding this comment.
🟡 Changes recommended
Uncaught browser exceptions no longer fail tests, allowing application crashes to pass unnoticed.
1 open finding
What changed in this PR
Migrates the end-to-end test infrastructure from Cypress to TypeScript-based Playwright.
Changes:
- Ports Cypress specifications, fixtures, static assets, and OAuth support.
- Adds Playwright configuration, sharded CI execution, and updated npm scripts.
- Updates documentation and removes Cypress infrastructure.
| File | Description |
|---|---|
playwright.config.ts |
Configures Playwright, servers, retries, and Chromium. |
test/e2e-playwright/** |
Adds ported specifications, fixtures, support utilities, and assets. |
test/e2e-cypress/** |
Removes the former Cypress suite. |
.github/workflows/nodejs.yml |
Adds sharded Playwright CI execution and artifacts. |
webpack/dev-e2e.js |
Serves Playwright test assets. |
package.json / package-lock.json |
Replaces Cypress dependencies and scripts. |
| Documentation and metadata files | Updates testing instructions and path references. |
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
Cypress only suppresses an uncaught:exception when the handler returns false; the old handler returned true, so such exceptions failed tests. Collect weberror events and fail during fixture teardown to keep that behavior. The full suite passes with this in place. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Addresses the CodeQL incomplete string escaping alert. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The strict Playwright TypeScript project is not type-checked in CI, and documented page-error behavior contradicts its implementation.
1 open finding
1 resolved since last review
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
Playwright transpiles TypeScript without type-checking and ESLint does not either, so add an e2e:typecheck script and run it in the build job. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The broad 634-test runner migration and CI orchestration changes require final human confirmation of behavioral parity.
1 open finding
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
|
@robert-hebel-sb @cka121 @glowcloud if you folks are interested in a tests dashboard for Playwright, I'd be happy to provide you one for free as part of the "Flakiness.io Open Source" program. Other big projects like WordPress or Nuxt are already part of it. Let me know if you're interested! |


Description
Replaces the Cypress end-to-end suite with an equivalent Playwright suite written entirely in TypeScript.
test/e2e-cypress/e2e/{a11y,bugs,features,security}are ported 1:1 totest/e2e-playwright/**/*.spec.ts(634 tests, same titles and assertions). Existingit.skiptests remain skipped.playwright.config.tsstarts the webpack dev-e2e server (:3230) and the mock API (:3204), and uses Chromium only.test/e2e-playwright/tsconfig.jsoncovers specs and config.testfixture provides a smallswaggerUihelper.console.errorand fail the test during fixture teardown. This matches the old Cypress behavior: itsuncaught:exceptionhandler returnedtrue, and only returningfalsesuppresses the failure.static/moved totest/e2e-playwright/static/andwebpack/dev-e2e.jspoints at it. The OAuth2 server and themultiple-exampleshelper are ported to TypeScript.cy:*replaced bye2e,e2e:ui,e2e:headed,e2e:report,e2e:server,e2e:mock-api,e2e:typecheck.npm testnow runse2e.buildjob also runsnpm run e2e:typecheck(stricttscover the Playwright tests, since Playwright does not type-check). Thee2e-testsjob installs Chromium, caches~/.cache/ms-playwright, runs 4 shards (--shard=N/4), and uploads the HTML report and traces on failure.@playwright/test1.63.0 and@types/cors2.8.19.@types/corsis needed to type the ported OAuth2 server understrict.@axe-core/playwrightis not needed because the Cypress a11y specs never used axe.cypressandstart-server-and-test.CLAUDE.md,docs/development/scripts.mdand the.claudeguidance docs updated.Notable translation decisions:
cy.wait(ms)was replaced by web-first assertions (orexpect.poll) throughout, exceptbugs/5138, which keeps a fixed 3s wait because it checks that the title stays stable over time..type()special sequences ({selectall},{{},{enter},{leftarrow}) were translated explicitly.cy.intercept/cy.stubbecamepage.route/exposeFunction+addInitScript.Tests that were passing vacuously in Cypress (the check ran before the page rendered):
info: the fixtureinfo-openAPI30.yamldeclaredopenapi: 3.1.0, so the 3.1-only summary was rendered. The fixture now declares3.0.0.license: "should render nothing if both URL & SPDX exists" never matched the app.selectLicenseUrldeliberately prer`. The test is renamed to "should prefer the URL over the SPDX identifier if both exist" and asserts that.Motivation and Context
How Has This Been Tested?
npm run e2e(full Playwright suite): all green.CI=true --repeat-each=3 --workers=2 --retries=0): 1887 passed, 15 skipped, 0 failures.main: full suite again, 631 passed, 3 skipped, 0 failed.npm run lint(0 errors, no warnings in the new files; the remaining 36 warnings pre-exist),npm run test:unit,npm run build,npm run test:artifact.actionlintwas not available locally, so the CI job has not been run on GitHub yet.Known gaps, carried over rather than fixed:
not.existright after an action) were already weak and were ported as is.request-body-upload-filenever uploads a fileScreenshots (if appropriate):
N/A
Checklist
My PR contains...
src/is unmodified: changes to documentation, CI, metadata, etc.)package.json)My changes...
Documentation
Automated tests