Skip to content

feat: Migrate testcafe tests to playwright [WIP]#5463

Open
tiagoapolo wants to merge 13 commits intomainfrom
feat/migrate-playwright
Open

feat: Migrate testcafe tests to playwright [WIP]#5463
tiagoapolo wants to merge 13 commits intomainfrom
feat/migrate-playwright

Conversation

@tiagoapolo
Copy link
Contributor

@tiagoapolo tiagoapolo commented May 16, 2025

Thanks for submitting a PR! Please check the boxes below:

  • I have added information to docs/ if required so people know about the feature!
  • I have filled in the "Changes" section below?
  • I have filled in the "How did you test this code" section below?
  • I have used a Conventional Commit title for this Pull Request

Changes

Pending:

  1. Tests still needs to be reviewed to be optimized for playwright
  2. All scenarios need to be fully tested
  3. Review playwright configurations
  4. Setup video storage

How did you test this code?

Please describe.

@tiagoapolo tiagoapolo requested a review from a team as a code owner May 16, 2025 21:08
@tiagoapolo tiagoapolo requested review from Zaimwa9 and removed request for a team May 16, 2025 21:08
@vercel
Copy link

vercel bot commented May 16, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview, Comment Jan 5, 2026 1:27pm
flagsmith-frontend-staging Ready Ready Preview, Comment Jan 5, 2026 1:27pm
1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Ignored Ignored Preview Jan 5, 2026 1:27pm

@github-actions github-actions bot added the front-end Issue related to the React Front End Dashboard label May 16, 2025
@tiagoapolo tiagoapolo changed the title feat: Migrate testcafe tests to playwright feat: Migrate testcafe tests to playwright [WIP] May 16, 2025
@github-actions github-actions bot added the feature New feature or request label May 16, 2025
@github-actions
Copy link
Contributor

github-actions bot commented May 16, 2025

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-api-test:pr-5463 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-api:pr-5463 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-e2e:pr-5463 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith:pr-5463 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-5463 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-frontend:pr-5463 Finished ✅ Results

@github-actions
Copy link
Contributor

github-actions bot commented May 16, 2025

Uffizzi Ephemeral Environment Deploying

☁️ https://app.uffizzi.com/github.com/Flagsmith/flagsmith/pull/5463

⚙️ Updating now by workflow run 15077923522.

What is Uffizzi? Learn more!

@github-actions github-actions bot added feature New feature or request and removed feature New feature or request labels May 16, 2025
@codecov
Copy link

codecov bot commented May 16, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.07%. Comparing base (38ac162) to head (ec3d48c).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5463   +/-   ##
=======================================
  Coverage   98.07%   98.07%           
=======================================
  Files        1294     1294           
  Lines       46535    46537    +2     
=======================================
+ Hits        45637    45639    +2     
  Misses        898      898           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions bot added feature New feature or request and removed feature New feature or request labels Jan 5, 2026
};

export const toggleFeature = async (page: Page, index: number, toValue: boolean) => {
await click(page, byId(`feature-switch-${index}${toValue ? '-off' : 'on'}`));
Copy link

Choose a reason for hiding this comment

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

Missing hyphen in toggleFeature selector breaks false case

The toggleFeature and setUserPermissions functions have a missing hyphen in the selector construction. When toValue is false, the selector becomes feature-switch-${index}on instead of feature-switch-${index}-on. This will cause tests that attempt to toggle a feature off to fail because the selector won't match any element.

Additional Locations (1)

Fix in Cursor Fix in Web

await setText(page, byId(`featureVariationValue${i}`), v.value);
await setText(page, byId(`featureVariationWeight${v.value}`), `${v.weight}`);
}),
);
Copy link

Choose a reason for hiding this comment

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

Race condition with Promise.all for sequential UI clicks

The createRemoteConfig function uses Promise.all with map to add multiple variations, but each iteration clicks add-variation which creates new UI elements. Running these in parallel causes a race condition where multiple clicks can occur before form fields are populated, leading to incorrect indices or values being set in wrong fields. The createSegment function correctly uses a sequential for loop pattern for similar operations. This will cause test flakiness.

Fix in Cursor Fix in Web

log('User with CREATE_ENVIRONMENT can create an environment');
await login(page, E2E_NON_ADMIN_USER_WITH_PROJECT_PERMISSIONS, PASSWORD);
await click(page, '#project-select-0');
await createEnvironment(page, 'Staging');
Copy link

Choose a reason for hiding this comment

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

Missing navigation step before createEnvironment call

The test calls createEnvironment directly after selecting a project, but the createEnvironment helper function expects to already be on the create environment page. Other tests like environment-test.spec.ts correctly navigate by clicking #create-env-link before calling createEnvironment. Without this navigation step, the test will fail because it tries to fill a form that doesn't exist on the current page.

Fix in Cursor Fix in Web

log('User without VIEW_AUDIT_LOG cannot view the audit log');
await login(page, E2E_NON_ADMIN_USER_WITH_PROJECT_PERMISSIONS, PASSWORD);
await click(page, '#project-select-0');
await waitForElementNotExist(page, 'audit-log-link');
Copy link

Choose a reason for hiding this comment

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

Missing byId wrapper causes incorrect element selector

The selector 'audit-log-link' is passed as a raw string to waitForElementNotExist, but it needs to be wrapped with byId() to generate the correct [data-test="audit-log-link"] selector. The correct pattern is shown in environment-permission-test.spec.ts which uses byId('audit-log-link'). Without the wrapper, this will look for an HTML element with tag name audit-log-link, which doesn't exist.

Fix in Cursor Fix in Web

- Update Node.js version from 16.20.1 to 22.12.0 in Dockerfile-base.e2e
  (Playwright requires Node.js 18+)
- Remove orphaned steps block from workflow YAML
- Fix byId() wrapper in deleteSegment and deleteFeature functions
- Fix compareVersion copy-paste bug (was checking old-value instead of new-value)
- Add wait for page load in gotoSegments function
- Add overflow menu handling in goToFeatureVersions function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The pre-built base image (ghcr.io/flagsmith/e2e-frontend-base:latest)
still has Node.js 16, which doesn't support Playwright.

This change inlines the base image build steps with Node.js 22.12.0
directly in Dockerfile.e2e to unblock CI until the base image is rebuilt.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add test-framework parameter to reusable E2E workflow
- Split run-e2e-tests into run-e2e-tests-playwright and run-e2e-tests-testcafe jobs
- Add npm scripts test:playwright and test:testcafe
- Add Makefile targets test-playwright and test-testcafe
- Fix Playwright strict mode violations by using .first() on locators

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- api-image: ${{ needs.docker-build-api.outputs.image }}
args: --meta-filter category=smoke
- api-image: ${{ needs.docker-build-private-cloud-api.outputs.image }}
args: --meta-filter category=smoke --meta-filter category=enterprise
Copy link

Choose a reason for hiding this comment

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

Testcafe workflow uses nonexistent test category and wrong format

The new run-e2e-tests-testcafe job passes --meta-filter category=smoke but no testcafe tests define category: 'smoke' - all tests use category: 'oss' or category: 'enterprise'. This causes zero tests to run for the OSS API. Additionally, the second job uses multiple --meta-filter flags (space-separated) instead of the expected comma-separated format (--meta-filter category=oss,category=enterprise). The testcafe code calls .split(',') on args['meta-filter'], which would throw a TypeError when minimist returns an array from multiple flags. The testcafe CI job will either crash or silently pass with no tests running.

Fix in Cursor Fix in Web

Split the PR workflow E2E jobs to run both test frameworks in parallel:
- run-e2e-tests-playwright (OSS)
- run-e2e-tests-testcafe (OSS)
- run-e2e-tests-private-cloud-playwright (Enterprise)
- run-e2e-tests-private-cloud-testcafe (Enterprise)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comment on lines +165 to +182
if: github.event.pull_request.draft == false && !cancelled()
needs: [permissions-check, docker-build-api, docker-build-e2e]
uses: ./.github/workflows/.reusable-docker-e2e-tests.yml
with:
runs-on: ${{ matrix.runs-on }}
e2e-image: ${{ needs.docker-build-e2e.outputs.image }}
api-image: ${{ needs.docker-build-api.outputs.image }}
test-framework: testcafe
args: --meta-filter category=smoke
secrets:
GCR_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.GITHUB_TOKEN || '' }}
SLACK_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.SLACK_TOKEN || '' }}

strategy:
matrix:
runs-on: [depot-ubuntu-latest-16, depot-ubuntu-latest-arm-16]

run-e2e-tests-private-cloud-playwright:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}

Copilot Autofix

AI about 1 month ago

In general: add an explicit permissions: block to the workflow (preferably at the root so it applies to all jobs) that restricts GITHUB_TOKEN to the minimal scopes required, typically contents: read for CI that just needs to fetch code and read workflow files.

Best minimal fix here: add a top‑level permissions: section after the on: block, setting contents: read. This will apply to all jobs in platform-pull-request.yml, including run-e2e-tests-testcafe, and will satisfy CodeQL’s requirement that the workflow explicitly limit GITHUB_TOKEN permissions, without changing any job logic. If other jobs in this workflow need elevated permissions, they can override permissions: individually, but we are not asked to change that, and there is no evidence in the provided snippet of a need for broader scopes.

Concretely:

  • Edit .github/workflows/platform-pull-request.yml.

  • Insert:

    permissions:
      contents: read

    between the on: block (lines 3–8) and jobs: (line 10).

  • No imports or additional methods are needed, since this is a YAML configuration change only.

Suggested changeset 1
.github/workflows/platform-pull-request.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/platform-pull-request.yml b/.github/workflows/platform-pull-request.yml
--- a/.github/workflows/platform-pull-request.yml
+++ b/.github/workflows/platform-pull-request.yml
@@ -7,6 +7,9 @@
       - docs/**
       - infrastructure/**
 
+permissions:
+  contents: read
+
 jobs:
   permissions-check:
     name: Check actor permissions
EOF
@@ -7,6 +7,9 @@
- docs/**
- infrastructure/**

permissions:
contents: read

jobs:
permissions-check:
name: Check actor permissions
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +183 to +200
if: github.event.pull_request.draft == false && !cancelled() && needs.permissions-check.outputs.can-write == 'true'
needs: [permissions-check, docker-build-private-cloud, docker-build-e2e]
uses: ./.github/workflows/.reusable-docker-e2e-tests.yml
with:
runs-on: ${{ matrix.runs-on }}
e2e-image: ${{ needs.docker-build-e2e.outputs.image }}
api-image: ${{ needs.docker-build-private-cloud.outputs.image }}
test-framework: playwright
args: --project=oss --project=enterprise
secrets:
GCR_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.GITHUB_TOKEN || '' }}
SLACK_TOKEN: ${{ needs.permissions-check.outputs.can-write == 'true' && secrets.SLACK_TOKEN || '' }}

strategy:
matrix:
runs-on: [depot-ubuntu-latest-16, depot-ubuntu-latest-arm-16]

run-e2e-tests-private-cloud-testcafe:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}

Copilot Autofix

AI about 1 month ago

In general, the fix is to explicitly declare permissions: in the workflow so the GITHUB_TOKEN has the minimum required scopes. The safest and simplest change is to add a root-level permissions: block (right under name: or on:) so that all jobs default to least-privilege read access, and then selectively elevate permissions for any jobs that genuinely need writes. From the provided snippet, the jobs are building Docker images and running E2E tests via reusable workflows, and they use secrets.GITHUB_TOKEN as GCR_TOKEN. For typical container build/test workflows, contents: read is sufficient; no explicit write scopes are obviously required.

The single best fix here without changing any behavior is:

  • Add a root-level permissions: block (near the top of .github/workflows/platform-pull-request.yml) setting contents: read.
  • Do not add any additional write permissions unless strictly necessary. From the context provided, we don’t see any direct need for write permissions, so limiting to contents: read should preserve behavior while restricting potential damage.

Concretely:

  • In .github/workflows/platform-pull-request.yml, insert:

    permissions:
      contents: read

    between the on: block and jobs: (or just under name:; both are valid, but placing it between on: and jobs: is common and clear).

No additional imports, methods, or definitions are required, since this is purely a YAML configuration change.

Suggested changeset 1
.github/workflows/platform-pull-request.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/platform-pull-request.yml b/.github/workflows/platform-pull-request.yml
--- a/.github/workflows/platform-pull-request.yml
+++ b/.github/workflows/platform-pull-request.yml
@@ -7,6 +7,9 @@
       - docs/**
       - infrastructure/**
 
+permissions:
+  contents: read
+
 jobs:
   permissions-check:
     name: Check actor permissions
EOF
@@ -7,6 +7,9 @@
- docs/**
- infrastructure/**

permissions:
contents: read

jobs:
permissions-check:
name: Check actor permissions
Copilot is powered by AI and may make mistakes. Always verify output.
@github-actions github-actions bot added feature New feature or request and removed feature New feature or request labels Jan 5, 2026
- Fix deleteFeature: change `remove-feature-btn-${index}` to `feature-remove-${index}`
- Fix deleteSegment: add `segment-action-${index}` click to open menu,
  change `remove-segment-btn-${index}` to `segment-remove-${index}`

These selectors now match the actual UI element IDs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
&& nvm use default

# add node and npm to path so the commands are available
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
Copy link

Choose a reason for hiding this comment

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

Incorrect NODE_PATH missing versions/node directory segment

The NODE_PATH environment variable uses path $NVM_DIR/v$NODE_VERSION/lib/node_modules which is inconsistent with NVM's actual directory structure. Line 38 correctly uses $NVM_DIR/versions/node/v$NODE_VERSION/bin for PATH, showing the correct pattern includes versions/node/ before the version. The NODE_PATH is missing this segment and will point to a non-existent directory, which could affect module resolution for globally installed packages.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants