Skip to content

DEVPROD-24935: Migrate from Cypress to Playwright for Parsley#1483

Merged
minnakt merged 28 commits intoevergreen-ci:mainfrom
minnakt:DEVPROD-24935_parsley
Apr 9, 2026
Merged

DEVPROD-24935: Migrate from Cypress to Playwright for Parsley#1483
minnakt merged 28 commits intoevergreen-ci:mainfrom
minnakt:DEVPROD-24935_parsley

Conversation

@minnakt
Copy link
Copy Markdown
Contributor

@minnakt minnakt commented Mar 26, 2026

DEVPROD-24935

Description

Migrates tests from Cypress to Playwright. Sorry for how big this PR is 🧍‍♂️

Instructions:

  • Have your backend and frontend server running
  • Run pnpm playwright:ui, which will open the Playwright UI
  • Click on any test suite or specific test you want to run to see results

Cypress configuration still exists since Spruce still has Cypress tests.

Screenshots

Screenshot 2026-03-26 at 3 50 17 PM

@minnakt minnakt marked this pull request as ready for review March 26, 2026 20:01
@minnakt minnakt requested a review from a team as a code owner March 26, 2026 20:01
Copy link
Copy Markdown
Contributor

@sophstad sophstad left a comment

Choose a reason for hiding this comment

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

yay 😍 maybe when Spruce is also done we can migrate away from data-cy and the dataCy utils

Comment thread .evergreen/scripts/constants.js Outdated
Tasks.CheckCodegen,
Tasks.Compile,
Tasks.E2E,
Tasks.E2EPlaywright,
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.

[nit] Maybe we can just name this E2E and the other to e2e_cypress?

Comment thread apps/parsley/playwright.config.ts Outdated
use: {
baseURL: "http://localhost:5173",
viewport: { width: 1280, height: 800 },
video: process.env.CI ? "retain-on-failure" : "off",
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.

Maybe we should use on-first-retry instead of retain-on-failure, it seems possible that recording video by default would be slightly slower

forbidOnly: !!process.env.CI, // Fail if implementer accidentally left test.only in any file.
retries: process.env.CI ? 2 : 0,
workers: 1, // Disable parallelism - run tests serially like Cypress.
use: {
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.

Let's try enabling traces, this looks freaking sick

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

So I think it is possible to get traces to be served from the HTML report, but the amount of things I have to upload would be kind of a lot. (I wish s3.put would just infer content_type?)

Instead I attached a .zip file which contains the traces and can be served locally via pnpm exec playwright show-report playwright-html-report

Comment thread apps/parsley/package.json Outdated
"storybook": "NO_HTTPS=true storybook dev -p 6007",
"storybook:build": "env-cmd -e local storybook build",
"test": "vitest --typecheck=false",
"test": "vitest --typecheck=false --exclude 'playwright/**'",
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.

Would it maybe be preferable to scope Vitest using include to only look at the src directory? Either way let's move the option to Vitest config instead of the script

Comment thread .evergreen/attach.yml Outdated
@minnakt minnakt requested a review from sophstad March 27, 2026 14:29
for (let i = 0; i < conditions.length; i++) {
if (!conditions[i]) {
hasOutOfBoundsValue = true;
console.log(`Out of bounds value: ${i} ${conditions[i]}`);
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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry yeah this is slop

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.

ha you're okay I think it was copypasta from a cy.log()

await page.locator(`[aria-label="Collapse navigation"]`).click();
};

export const validateToast = async (
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.

Would be nice if we can somehow share these utils when Spruce is added

@@ -0,0 +1 @@
export * from "./commands";
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.

I'd be okay having all the helper functions here, seems like this is maybe Cypress cruft

};
const toastDataCy = "toast";

export const getByDataCy = (page: Page, value: string) =>
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.

Hm do you think we should use a custom test attribute instead of requiring this helper everywhere? Or maybe just followup work?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ty!!!

Comment thread .evergreen/attach.yml
Comment on lines +91 to +117
- command: s3.put
type: system
params:
role_arn: ${ASSUME_ROLE_ARN}
local_files_include_filter: ["ui/${app_dir}/bin/playwright/html/data/**/*.png"]
remote_file: ${build_variant}/${task_id}/${execution}/playwright/html/data/
bucket: evg-bucket-evergreen-ui
content_type: image/png
permissions: public-read
- command: s3.put
type: system
params:
role_arn: ${ASSUME_ROLE_ARN}
local_files_include_filter: ["ui/${app_dir}/bin/playwright/html/data/**/*.webm"]
remote_file: ${build_variant}/${task_id}/${execution}/playwright/html/data/
bucket: evg-bucket-evergreen-ui
content_type: video/webm
permissions: public-read
- command: s3.put
type: system
params:
role_arn: ${ASSUME_ROLE_ARN}
local_files_include_filter: ["ui/${app_dir}/bin/playwright/html/data/**/*.md"]
remote_file: ${build_variant}/${task_id}/${execution}/playwright/html/data/
bucket: evg-bucket-evergreen-ui
content_type: text/markdown
permissions: public-read
Copy link
Copy Markdown
Contributor

@sophstad sophstad Mar 27, 2026

Choose a reason for hiding this comment

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

I think maybe we should be grabbing these assets from bin/playwright/test-results instead of /html. That makes them not have hashed asset names, and allows us to directly download the trace.zip files which is ideal. We could also use view remote traces except for a CORS issue I haven't figured out yet 😿

I tried it on this patch (just look at changes in .evergreen/attach.yml)

Comment thread .evergreen/attach.yml
permissions: private
visibility: signed
display_name: "Playwright HTML Report (zip)"
- command: s3.put
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.

Similar changes in the patch I linked -- it is slightly easier imo to just upload the whole /html directory and use preserive_path... and I added a special display name upload so the index file is clear. What do you think?

Comment on lines +14 to +26
// Intercept GraphQL queries to detect mutations; match both relative and absolute paths.
await page.route("**/graphql/query", async (route) => {
const request = route.request();
try {
const postData = request.postDataJSON();
if (postData?.query?.startsWith("mutation")) {
mutationDispatched = true;
}
} catch (e) {
console.error("Failed to parse GraphQL request:", e);
}
await route.continue();
});
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.

Nice (but I want to rip it out 😈)

Comment thread apps/parsley/.gitignore Outdated
body.txt-e

# Playwright
/test-results/
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.

I believe this is being written to /bin so can be removed (playwright-report and blob-report may be the same)

Comment thread apps/parsley/package.json
"postversion": "pnpm deploy-utils-postversion",
"prepare": "pnpm --dir ../.. prepare",
"preview": "serve -s dist -p 4173",
"preview": "serve -s dist -p 5173",
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.

I think this should also be updated in env-cmdrc.json

@minnakt minnakt requested a review from sophstad March 31, 2026 01:47
Copy link
Copy Markdown
Contributor

@sophstad sophstad left a comment

Choose a reason for hiding this comment

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

This is looking pretty good! Main question is whether there's any way to include the test name instead of just the filename for failed assets 🤔 if not that's okay too

Comment thread .evergreen/shared.yml
@minnakt
Copy link
Copy Markdown
Contributor Author

minnakt commented Apr 9, 2026

added test names to uploaded files

@minnakt minnakt requested a review from sophstad April 9, 2026 00:35
Copy link
Copy Markdown
Contributor

@sophstad sophstad left a comment

Choose a reason for hiding this comment

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

WAHOOOO

Comment thread .evergreen/attach.yml
remote_file: ${build_variant}/${task_id}/${execution}/report/
bucket: evg-bucket-evergreen-ui
content_type: text/html
visibility: none
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.

YAY this is geniussss

Comment thread .evergreen/attach.yml
bucket: evg-bucket-evergreen-ui
content_type: image/png
permissions: public-read
display_name: "screenshot:"
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.

[super nit] The names here seem prefixed with the type so could remove if you want, up to you

Suggested change
display_name: "screenshot:"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ty!

Comment thread .evergreen/attach.yml
bucket: evg-bucket-evergreen-ui
content_type: video/webm
permissions: public-read
display_name: "video:"
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.

Here too (giving you github suggestions to make it easy to apply)

Suggested change
display_name: "video:"

Comment thread .evergreen/attach.yml
bucket: evg-bucket-evergreen-ui
content_type: application/zip
permissions: public-read
display_name: "trace:"
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.

Suggested change
display_name: "trace:"

@minnakt minnakt merged commit 8214059 into evergreen-ci:main Apr 9, 2026
12 checks passed
@minnakt minnakt deleted the DEVPROD-24935_parsley branch April 9, 2026 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants