Skip to content

[DRAFT] feat: frontend qa app#7400

Draft
fairlighteth wants to merge 4 commits into
developfrom
feat/frontend-qa
Draft

[DRAFT] feat: frontend qa app#7400
fairlighteth wants to merge 4 commits into
developfrom
feat/frontend-qa

Conversation

@fairlighteth
Copy link
Copy Markdown
Contributor

@fairlighteth fairlighteth commented Apr 24, 2026

Summary

Adds a prototype/advisory Playwright QA lane for high-signal release smoke coverage against the built CoW Swap frontend and a pinned Anvil mainnet fork.

This adds:

  • New cowswap-frontend-qa Nx project.
  • Playwright fixtures for browser setup, injected wallet connection, Anvil fork lifecycle, WETH funding, approvals, and on-chain proof checks.
  • Smoke tests for quote rendering, WETH approval persistence, and native ETH submission choreography up to submitted/recent activity state.
  • GitHub workflow for Playwright QA, safely skipped when MAINNET_RPC is unavailable.
  • Small frontend/wallet testability hooks needed for deterministic QA automation.

Status

This is a prototype/advisory QA lane. It should not become a required release gate until the team agrees on ownership, flake policy, runtime, and MAINNET_RPC availability in CI.

To Test

  1. Prepare local dependencies
  • Ensure Foundry/Anvil is installed: command -v anvil
  • Ensure Playwright Chromium is installed: pnpm --dir apps/cowswap-frontend-qa exec playwright install chromium
  • Set MAINNET_RPC to a mainnet archive-capable RPC URL.
  1. Run the QA suite
pnpx nx run cowswap-frontend-qa:e2e
  • Verify all 3 Playwright tests pass.
  • Verify Anvil starts and stops cleanly.
  • Verify the approval smoke proves WETH allowance changed on the fork.
  • Verify the native submission smoke reaches submitted/recent activity state.
  • Verify the quote smoke renders a non-zero WETH -> USDC buy amount.
  1. Optional debug run

pnpx nx run cowswap-frontend-qa:e2e:headed -- --trace=on

  • Verify traces/screenshots are available for failures.

Non-goals

  • This is not broad UI regression coverage.
  • This does not replace Cypress controlled-state tests, Sepolia/API contract checks, or manual exploratory QA.
  • This does not prove solver settlement, live orderbook acceptance, quote quality, or broad layout/copy behavior.
  • This suite should stay small. New tests should only be added here when Cypress cannot prove the same risk with equivalent confidence.

Background

This adds the concrete Playwright tier described in the QA tiering strategy: production-like release smoke between mocked Cypress coverage and repeated manual QA smoke checks.

The native submission smoke proves the frontend can reach submitted/recent-activity state from a native-token sell path using real wallet/forked on-chain interactions, while stubbing only the live orderbook submission boundary.

Testability hooks

This PR adds narrow testability hooks for deterministic QA:

  • A custom event to connect the injected wallet without depending on vendor modal markup.
  • A sessionStorage flag to force on-chain approval when the smoke test needs to prove allowance mutation.

These hooks do not expose privileged operations; they make existing user/session behavior easier to drive deterministically in the built app.

Fork block

The Anvil fork block is intentionally pinned for reproducibility. It should be refreshed only for a concrete reason: stale route assumptions, provider issues, token/liquidity drift, or an intentional release-smoke refresh.

Review Focus

Please review:

  • Whether the Playwright lane boundary is clear enough.
  • Whether the testability hooks are acceptable and narrow enough.
  • Whether the native submission smoke stubs the right boundary.
  • Whether the workflow skip behavior around MAINNET_RPC is clear enough.
  • Whether the fork block and Anvil lifecycle are maintainable.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 24, 2026

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

Project Deployment Actions Updated (UTC)
cowfi Ready Ready Preview May 11, 2026 2:53pm
explorer-dev Ready Ready Preview May 11, 2026 2:53pm
storybook Error Error May 11, 2026 2:53pm
swap-dev Ready Ready Preview May 11, 2026 2:53pm
widget-configurator Ready Ready Preview May 11, 2026 2:53pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
cosmos Ignored Ignored May 11, 2026 2:53pm
sdk-tools Ignored Ignored Preview May 11, 2026 2:53pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4c718a50-06c3-4e1d-9016-6ba8e22175df

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/frontend-qa

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 24, 2026

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

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​playwright/​test@​1.59.110010010099100

View full report

Comment on lines +243 to +260
await expect(page.getByRole('heading', { name: 'Swap with Wrapped ETH' })).toBeVisible()
await expect(
page.getByText('To continue, click below to wrap your ETH to WETH via an on-chain ERC20 transaction.'),
).toBeVisible()

await page.getByRole('button', { name: 'Wrap ETH' }).click()

const approvalProofBaseline = await createWethApprovalProofBaseline({ anvilUrl, owner: walletAddress })

await expect(page.getByRole('heading', { name: 'Approve WETH' })).toBeVisible({ timeout: 30_000 })
await approveWethForCowVaultRelayer(BigInt(ONE_WETH_IN_WEI))

await assertWethApprovalProof({ anvilUrl, baseline: approvalProofBaseline, owner: walletAddress, testInfo })

await interceptDeterministicWrappedQuote(page, walletAddress)

await page.goto('about:blank')
await page.goto(buildMainnetSwapRoute(MAINNET_WETH, MAINNET_USDC, { orderKind: 'sell', sellAmount: '1' }))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I expected, from the title, this test to use the ethFlow. However, it wraps the native token, approves the wrapped version and then places the order. Essentially a regular order with an approval step.

Since the approval is covered in the previous test, wouldn't make sense to test only a single order instead?

At a bare minimum, make it clearer that this is not an ethFlow test to avoid same confusions in the future :)

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.

Renamed/reworked this to a regular WETH -> USDC order-submission smoke. Since the assertion target is order placement, wrap + approval are now fixture setup instead of UI steps, avoiding duplicate approval coverage and ethFlow confusion.

import { accountSelectors, ethFlowSelectors, swapSelectors, walletSelectors } from './selectors'

const CONNECT_INJECTED_WALLET_EVENT = 'cowswap-connect-injected-wallet'
const FORCE_ONCHAIN_APPROVAL_SESSION_KEY = 'cowswap:qaForceOnchainApproval:v0'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is defined twice, and can lead to issues if one of the locations is updated independently. Would it be possible to fetch both from the same place?

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.

Moved these to a shared macro-free QA constants subpath: @cowprotocol/common-const/qa, so QA and frontend use the same values without importing the macro-backed common-const barrel.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Are those changes necessary for the qa tests setup?

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.

Removed the QA-specific hook from libs/wallet; the deterministic connect listener now lives in the frontend app only and is gated by REACT_APP_ENABLE_QA_INJECTED_WALLET, which the QA Playwright config enables.

Comment thread .github/workflows/qa-playwright.yml Outdated
if: env.HAS_MAINNET_RPC == 'true'
run: pnpm --dir apps/cowswap-frontend-qa exec playwright install --with-deps chromium

- name: Mask RPC secret in logs
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to explicitly mask them? AFAICT, gh actions already redacts any secrets printed in the actions.

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.

Removed the custom masking step and rely on GitHub Actions’ built-in redaction for MAINNET_RPC, which is still passed only via secrets.MAINNET_RPC.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 11, 2026

Deploying swap-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: dc7dc5f
Status:🚫  Build failed.

View logs

@fairlighteth fairlighteth requested a review from alfetopito May 11, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants