feat: e2e tests with playwright - #7961
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughChangesThe PR adds a complete Playwright/Synpress E2E application for CoW Swap. It includes wallet engines, RPC services, API and balance mocks, page objects, test fixtures, documentation, Nx targets, and smoke tests. Playwright E2E application
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant PlaywrightTest
participant WalletFixture
participant RpcProxy
participant CowProtocolApiMock
participant BalancesMock
participant CowSwapUI
PlaywrightTest->>WalletFixture: Configure wallet and chain
WalletFixture->>RpcProxy: Send wallet RPC requests
PlaywrightTest->>CowProtocolApiMock: Configure API responses
PlaywrightTest->>BalancesMock: Configure balances and SSE snapshots
CowSwapUI->>CowProtocolApiMock: Request quotes and orders
CowSwapUI->>BalancesMock: Request balance sessions and updates
CowSwapUI->>WalletFixture: Sign and submit trade operations
WalletFixture->>RpcProxy: Forward or stub chain calls
PlaywrightTest->>CowSwapUI: Assert trade and network states
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
…/e2e-playwright-3
…l/cowswap into feat/e2e-playwright-2
… feat/e2e-playwright
… feat/e2e-playwright
…cowswap into feat/e2e-playwright-1
…l/cowswap into feat/e2e-playwright-2 # Conflicts: # bundle-size.jsonc
…cowswap into feat/e2e-playwright-1
…l/cowswap into feat/e2e-playwright-2
…/e2e-playwright-2
… feat/e2e-playwright-1 # Conflicts: # apps/cowswap-frontend/src/modules/balancesAndAllowances/updaters/CommonPriorityBalancesAndAllowancesUpdater.tsx
…l/cowswap into feat/e2e-playwright-2
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 20
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (13)
apps/cowswap-e2e-tests/src/tests/market-orders.spec.ts-27-27 (1)
27-27: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAssert the expected quote value.
Both assertions accept any non-empty output. A stale default quote can satisfy them. Assert the configured quote value, or poll until the expected value is stable.
apps/cowswap-e2e-tests/src/tests/market-orders.spec.ts#L27-L27: replace the non-empty assertion with the expected output amount.apps/cowswap-e2e-tests/src/tests/market-orders.spec.ts#L46-L46: replace the non-empty assertion with the expected output amount.As per coding guidelines, tests must assert a specific expected value or poll for stability because stale default quotes must not satisfy assertions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/tests/market-orders.spec.ts` at line 27, Replace the non-empty output assertions in market-orders.spec.ts at lines 27-27 and 46-46 with assertions against the configured expected output amount, or poll until that exact value is stable; both sites require the same change so stale default quotes cannot satisfy the tests.Source: Coding guidelines
apps/cowswap-e2e-tests/README.md-191-192 (1)
191-192: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winLimit the cache prerequisite to Synpress tests.
The MetaMask cache is required only for Synpress fixtures. Mock-wallet tests do not use the extension or
.cache-synpress. Update this command description so developers do not build the cache before mock-wallet-only runs.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/README.md` around lines 191 - 192, Update the e2e:build-cache description in the README so it states that the Synpress MetaMask profile cache is required only for Synpress tests, not all test runs; leave the command itself and the full-suite entry unchanged.apps/cowswap-e2e-tests/README.md-151-153 (1)
151-153: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winDo not state a USDC amount without fixture decimals.
"5000000"is not always 5 USDC. The committed Sepolia fixture token labelled USDC has 18 decimals. State that the displayed amount depends on the token fixture decimals.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/README.md` around lines 151 - 153, Update the README guidance around raw atom values to state that the displayed token amount depends on the fixture token’s decimals, specifically noting that the committed Sepolia fixture labeled USDC uses 18 decimals; avoid presenting “5000000” as universally equal to 5 USDC, while preserving the existing guidance about stringifying values above 2^53.apps/cowswap-e2e-tests/src/mockWallet/injectedShim.ts-77-80 (1)
77-80: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winNormalize the rejection value before the callback.
Promise rejection values can be non-
Errorvalues. Type the parameter asunknown. Normalize it once before passing it tocallback.Because
injectedShimis serialized into the page, keep the normalization helper inside the serialized function.Proposed fix
+ function normalizeError(err: unknown): Error { + return err instanceof Error ? err : new Error(String(err)) + } + const provider = { // ... send( // ... ): Promise<unknown> | void { if (typeof methodOrRequest === 'object' && typeof paramsOrCallback === 'function') { const callback = paramsOrCallback request(methodOrRequest).then( (result) => callback(null, { result }), - (error: Error) => callback(error, null), + (err: unknown) => { + const error = normalizeError(err) + callback(error, null) + }, )As per coding guidelines, promise rejection values must use
(err: unknown)andconst error = normalizeError(err)before use.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mockWallet/injectedShim.ts` around lines 77 - 80, Update the rejection handler in the serialized injectedShim function to accept `(err: unknown)`, normalize it once with the local normalization helper, and pass the resulting error to callback. Keep the helper inside the serialized function and preserve the existing callback arguments.Source: Coding guidelines
apps/cowswap-e2e-tests/src/support/rpcProxy.test.ts-89-93 (1)
89-93: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAssert the
/admin/resetpostcondition.The test invokes
/admin/resetbut does not verify that it cleared the worker stub. The test passes if the endpoint returns success without changing proxy state. Query the same balance after reset and assert the dummy upstream error.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/support/rpcProxy.test.ts` around lines 89 - 93, Update the test around the /admin/reset request to query the same worker balance again after the POST and assert that the dummy upstream error is returned, verifying the reset cleared the worker stub rather than only relying on the endpoint response.apps/cowswap-e2e-tests/src/support/rpcProxy.ts-123-126 (1)
123-126: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winNormalize rejected values at both catch sites.
Production TypeScript must type the rejection value as
unknownand normalize it once before use. Replace each catch parameter witherr: unknown, then createconst error = normalizeError(err)before constructing the response.
apps/cowswap-e2e-tests/src/support/rpcProxy.ts#L123-L126: normalize the request-handler rejection before writing the HTTP error.apps/cowswap-e2e-tests/src/support/rpcProxy.ts#L321-L325: normalize the forwarding rejection before creating the JSON-RPC error.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/support/rpcProxy.ts` around lines 123 - 126, Normalize rejected values at both catch sites in apps/cowswap-e2e-tests/src/support/rpcProxy.ts:123-126 and apps/cowswap-e2e-tests/src/support/rpcProxy.ts:321-325 by typing each catch parameter as unknown, calling normalizeError once to create error, and using that normalized value for the HTTP response and JSON-RPC error respectively.Source: Coding guidelines
apps/cowswap-e2e-tests/src/support/rpcProxy.ts-104-108 (1)
104-108: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winUse
getAddressKeyfor EVM address map keys.Manual
toLowerCase()normalization violates the address identity rule and can miss equivalent inputs.
apps/cowswap-e2e-tests/src/support/rpcProxy.ts#L104-L108: usegetAddressKeyfor the address part of both balance and call stub keys.apps/cowswap-e2e-tests/src/mocks/usdPrices.ts#L23-L25,apps/cowswap-e2e-tests/src/mocks/usdPrices.ts#L55-L61: usegetAddressKeyfor price storage and lookup keys.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/support/rpcProxy.ts` around lines 104 - 108, Replace manual toLowerCase() address normalization with getAddressKey in balanceKey and callKey in apps/cowswap-e2e-tests/src/support/rpcProxy.ts (lines 104-108), applying it to each address component. Also update price storage in apps/cowswap-e2e-tests/src/mocks/usdPrices.ts (lines 23-25) and price lookup in lines 55-61 to use getAddressKey for their EVM address keys.Source: Coding guidelines
apps/cowswap-e2e-tests/src/support/buildWalletCache.ts-99-101 (1)
99-101: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winNormalize the rejected value before logging it.
Declare the handler parameter as
err: unknown. Setconst error = normalizeError(err)once. Logerrorinstead of the raw rejection value.As per coding guidelines, “Promise rejection values MUST be typed as
(err: unknown)and normalized exactly once withconst error = normalizeError(err)before use.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/support/buildWalletCache.ts` around lines 99 - 101, Update the catch handler in buildWalletCache to type its rejection parameter as err: unknown, normalize it exactly once with const error = normalizeError(err), and pass the normalized error to console.error before exiting.Source: Coding guidelines
apps/cowswap-e2e-tests/src/mocks/allowances/fixture.ts-30-40 (1)
30-40: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winReject unsafe chain IDs before creating the lookup key.
Line 33 rounds decimal values above
Number.MAX_SAFE_INTEGER. This can store an allowance under a different chain ID. ValidatechainIdwithNumber.isSafeInteger()after conversion.Proposed fix
const chainId = Number(chainKey) + if (!Number.isSafeInteger(chainId)) { + throw new Error(`${source}["${owner}"]: "${chainKey}" is not a safe integer chain id`) + } for (const [token, value] of entriesOf(byToken, `${source}["${owner}"]["${chainKey}"]`, 'chain entry')) {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mocks/allowances/fixture.ts` around lines 30 - 40, Update the chain ID validation in the allowance fixture before calling allowanceKey: after converting chainKey to chainId, require Number.isSafeInteger(chainId) and reject unsafe values with the existing invalid-chain error path. Keep the decimal-format validation and lookup behavior unchanged for safe integer IDs.apps/cowswap-e2e-tests/src/mocks/allowances/rpcUrls.ts-10-13 (1)
10-13: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winNormalize the pathname before appending the query string.
Line 12 does not normalize
https://rpc.example/path/?key=valueto the same value ashttps://rpc.example/path?key=value. This contradicts the trailing-slash contract and can prevent route interception.Proposed fix
export function normalizeRpcUrl(url: string): string { const parsed = new URL(url) - return `${parsed.origin}${parsed.pathname}${parsed.search}`.replace(/\/$/, '') + return `${parsed.origin}${parsed.pathname.replace(/\/$/, '')}${parsed.search}` }Add a test that covers a trailing slash before a query string.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mocks/allowances/rpcUrls.ts` around lines 10 - 13, The normalizeRpcUrl function currently removes a trailing slash only after appending the query string, so paths ending in "/?" are not normalized correctly. Normalize parsed.pathname before concatenating parsed.search, preserving the query string, and add a test covering a trailing slash before a query string.apps/cowswap-e2e-tests/src/mocks/allowances/index.ts-120-124 (1)
120-124: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winNormalize the caught rejection value once.
Bind this catch handler to
(err: unknown), then useconst error = normalizeError(err)before recording the problem.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mocks/allowances/index.ts` around lines 120 - 124, Update the catch handler in the allowance mock route to bind the rejection as err: unknown, normalize it once with normalizeError(err), and use the resulting error when pushing the problem message. Preserve the existing route.continue() fallback behavior.Source: Coding guidelines
apps/cowswap-e2e-tests/src/mocks/balances/fixture.ts-30-33 (1)
30-33: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReject chain IDs that cannot be represented safely.
DECIMAL_REaccepts values thatNumber()rounds or converts toInfinity. This can create incorrect lookup keys. ValidatechainIdwithNumber.isSafeInteger()before using it. Reject non-positive values if chain ID zero is not supported.Proposed fix
if (!DECIMAL_RE.test(chainKey)) { throw new Error(`${source}["${owner}"]: "${chainKey}" is not a valid chain id`) } const chainId = Number(chainKey) + if (!Number.isSafeInteger(chainId) || chainId <= 0) { + throw new Error(`${source}["${owner}"]: "${chainKey}" is not a valid chain id`) + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mocks/balances/fixture.ts` around lines 30 - 33, Validate the `chainId` produced in the chain-key parsing flow with `Number.isSafeInteger()` and require it to be positive before using it as a lookup key. Extend the existing error path near `DECIMAL_RE` and `Number(chainKey)` to reject unsafe, infinite, fractional, or non-positive values while preserving the current valid-chain behavior.apps/cowswap-e2e-tests/src/mocks/balances/types.ts-21-27 (1)
21-27: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winUse
getAddressKeyfor the owner balance key.
balanceKeyandbalanceOwnerChainPrefixlowercase the owner manually. Replace those owner normalizations withgetAddressKey()so the balance mock uses the repository address-key contract.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mocks/balances/types.ts` around lines 21 - 27, Update balanceKey and balanceOwnerChainPrefix to normalize the owner with getAddressKey() instead of manually calling toLowerCase(), while preserving the existing chain and token formatting.Source: Coding guidelines
🧹 Nitpick comments (3)
apps/cowswap-e2e-tests/src/mocks/allowances/index.ts (1)
45-45: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winHandle route registration asynchronously before returning the mock.
BrowserContext.route()returns a Promise, andinstallAllowances()returns synchronously. Other mock installers discard the same Promise, but this API’s caller path also has no await surface, so tests can assume allowance interception is installed immediately. Make the registration awaitable where the mock is installed, or otherwise document that interception is asynchronous.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mocks/allowances/index.ts` at line 45, Update installAllowances to await BrowserContext.route before resolving, changing its return type as needed to expose an awaitable installation; update its callers to await the returned mock before issuing requests. Ensure allowance interception is registered before the mock is used rather than relying on synchronous return timing.apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/types.ts (1)
47-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSimplify the factory return type.
unknown | Promise<unknown>collapses tounknownin TypeScript. The union reads as if it constrains the return value, but it does not.resolveResponsealready awaits the result, sounknownalone is accurate.♻️ Proposed change
-export type CowApiOverrideFactory = (req: CowApiRequest) => unknown | Promise<unknown> +/** May return a value or a promise; `resolveResponse` awaits the result. */ +export type CowApiOverrideFactory = (req: CowApiRequest) => unknown🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/types.ts` at line 47, Update the CowApiOverrideFactory return type to unknown instead of unknown | Promise<unknown>; resolveResponse already awaits the factory result, so preserve its existing behavior while simplifying the type declaration.apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/record.ts (1)
105-105: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd a timeout to the recording
fetchcall.If the CoW API stops responding, the unbounded request can let
record.mocksrun for an entry without output or progress. The declared Node range (>=20.19 <23) supportsAbortSignal.timeout, so attachsignal: AbortSignal.timeout(30_000)to both GET and POST options.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/record.ts` at line 105, Add a 30-second timeout to the fetch request in the recording flow by attaching AbortSignal.timeout(30_000) to the request options used for both GET and POST calls. Update the shared options around the fetch invocation so both methods receive the signal without changing their existing behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cowswap-e2e-tests/playwright.config.ts`:
- Around line 31-33: Update the webServer command in the Playwright
configuration to use pnpm start:cowswap instead of pnpm preview, while
preserving the existing cwd and other web server settings.
In `@apps/cowswap-e2e-tests/src/fixtures/mockWallet.ts`:
- Around line 110-114: Update the initialization flow around openApp() and the
injectedShim setup so the initial chain is derived from the URL hash, falling
back to chainIdHex when no chain is specified. Pass that resolved chain to the
shim instead of always using toHex(CHAIN_IDS.SEPOLIA), keeping
window.ethereum.chainId consistent with eth_chainId.
In `@apps/cowswap-e2e-tests/src/fixtures/rpcProxy.ts`:
- Around line 22-41: Update the administrative requests in setBalance, stubCall,
and reset to retain each fetch response, validate response.ok, and throw an
error containing the specific endpoint and HTTP status when a request fails.
Preserve the existing request payloads and methods for successful responses.
In `@apps/cowswap-e2e-tests/src/mocks/allowances/codec.ts`:
- Around line 122-130: Replace manual toLowerCase() address normalization in
classifyAllowance with getAddressKey from `@cowprotocol/cow-sdk` for token, owner,
and spender. Update the matching expected allowance identities in
apps/cowswap-e2e-tests/src/mocks/allowances/codec.test.ts at lines 69-77,
95-101, 154-163, and 173-183 to use the same getAddressKey representation.
In `@apps/cowswap-e2e-tests/src/mocks/allowances/types.ts`:
- Around line 22-28: Update allowanceKey() and ownerKeyPrefix() to normalize
addresses through getAddressKey() instead of calling toLowerCase() directly for
owner and token values. Preserve the existing key format and ensure both fixture
and runtime allowance lookups use the canonical normalization path.
In `@apps/cowswap-e2e-tests/src/mocks/balances/index.ts`:
- Around line 116-121: Update the SSE response body in the balance mock route
around route.fulfill to remove the 500 ms retry configuration or replace it with
a retry interval longer than the browser’s default reconnect delay, while
preserving the existing balance_update snapshot payload.
In `@apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/index.ts`:
- Line 77: Update installCowProtocolApi to return the context.route(...)
promise, and await that installer from the shared mocks.cowApi fixture before
exposing the mock. Keep CowProtocolApiMock methods synchronous by resolving the
registration promise internally in set, while preserving the existing mock API.
In `@apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/normalize.ts`:
- Around line 163-166: Replace the toLowerCase() normalization in subjectAddress
with getAddressKey from `@cowprotocol/cow-sdk` while preserving undefined when no
address is provided. Update install.test.ts lines 104-107 to compare order.owner
and order.receiver with getAddressKey(ADDRESS), and resolve.test.ts lines 41-46
to compare them with getAddressKey(TRADER).
In `@apps/cowswap-e2e-tests/src/mocks/safeSdk.ts`:
- Around line 24-35: Normalize the Safe RPC method name before the response
selection in the mock handler: strip the `safe_` prefix from `msg.method` or
compare against the full prefixed names so `safe_getSafeInfo` returns the safe
details and `safe_getEnvironmentInfo` returns the environment data, while
preserving the empty object fallback for other Safe methods.
In `@apps/cowswap-e2e-tests/src/mockWallet/walletEngine.ts`:
- Line 79: Replace the cast-only RPC response handling near the `res.json()`
call and in `eth_signTypedData` with `unknown` values followed by runtime
validation of the required response and typed-data fields. Narrow validated
values before forwarding them to viem, and reject malformed or missing RPC
payloads rather than relying on TypeScript assertions.
- Around line 166-167: Update the catch block in handle() to catch the rejection
as err: unknown and normalize it exactly once with normalizeError(err). Preserve
the normalized EIP-1193 code and data when constructing the RpcError, then
return the failure envelope as { ok: false, error }.
In `@apps/cowswap-e2e-tests/src/pages/HeaderPage.ts`:
- Around line 5-19: In apps/cowswap-e2e-tests/src/pages/HeaderPage.ts lines
5-19, add readonly constructor properties for the header and network-dialog
Locators, and scope the dynamic currentNetworkLabel and targetNetworkLabel
locators from those properties within switchNetwork. In
apps/cowswap-e2e-tests/src/pages/TokenSelector.ts lines 4-17, add readonly
constructor properties for the input selector, output selector, search input,
and currency-list Locators, then reuse them in the page-object action methods.
In `@apps/cowswap-e2e-tests/src/pages/SwapPage.ts`:
- Around line 135-138: Update the mockSwapFulfillment flow to accept and use
buyTokenBalanceBefore when setting balances. In the balances.set call, preserve
the existing buy-token balance by storing buyTokenBalanceBefore +
BigInt(body.buyAmount) instead of replacing it with body.buyAmount, while
keeping the sell-token deduction unchanged.
In `@apps/cowswap-e2e-tests/src/support/rpcProxy.ts`:
- Around line 114-121: Update forward() to use an AbortController with a bounded
timeout when calling fetch(opts.sepoliaRpcUrl, ...), pass its signal to fetch,
and clear the timeout in cleanup after resolution or rejection so stalled
upstream requests abort and tryForward() can return its JSON-RPC error.
In `@apps/cowswap-e2e-tests/src/support/setupTestConditions.test.ts`:
- Around line 91-98: Update the expected USDC balance in the balances.calls
assertion to use the committed Sepolia fixture’s 18-decimal value,
56_000_000_000_000_000_000_000n, while leaving the WETH and allowance
expectations unchanged.
In `@apps/cowswap-e2e-tests/src/support/tokens.ts`:
- Around line 10-13: Update the Sepolia USDC metadata in the CHAIN_IDS.SEPOLIA
token configuration to use 18 decimals instead of 6, and add a matching
assertion in the token metadata tests confirming the Sepolia USDC fixture has 18
decimals.
In `@apps/cowswap-e2e-tests/src/support/wallet.setup.ts`:
- Around line 25-27: Update the button-click flow around button.isVisible() so
clicked is set to true only when button.click succeeds; do not suppress a failed
click while marking it completed. If the locator remains visible after failure,
apply a bounded retry or propagate the normalized error so the quiet counter
cannot reset indefinitely.
In `@apps/cowswap-e2e-tests/src/tests/limit-orders.spec.ts`:
- Line 27: Move the specified interactions behind page-object APIs: in
apps/cowswap-e2e-tests/src/tests/limit-orders.spec.ts at line 27, add and call a
LimitPage action that clicks placeOrderButton; in
apps/cowswap-e2e-tests/src/tests/market-orders.spec.ts at line 135, add and call
a ConfirmModal action that confirms the trade; and at line 179, add a readonly
warning locator to SwapPage and assert it from the spec. Keep selectors and
interactions out of the specs.
- Around line 11-30: Add a test.beforeEach fixture with default mocked token
balances to the test.describe blocks in
apps/cowswap-e2e-tests/src/tests/limit-orders.spec.ts (11-30),
apps/cowswap-e2e-tests/src/tests/market-orders.spec.ts (16-181), and
apps/cowswap-e2e-tests/src/tests/network.spec.ts (8-23). Keep each test’s
scenario-specific balances in setupTestConditions as overrides of those shared
defaults.
In `@package.json`:
- Line 143: Align the patched dependency key with the installed
`@synthetixio/synpress-metamask` version: regenerate and reference the patch for
version 0.0.14, updating related package metadata or lockfile entries as needed,
or consistently pin the dependency to patched version 0.0.11.
---
Minor comments:
In `@apps/cowswap-e2e-tests/README.md`:
- Around line 191-192: Update the e2e:build-cache description in the README so
it states that the Synpress MetaMask profile cache is required only for Synpress
tests, not all test runs; leave the command itself and the full-suite entry
unchanged.
- Around line 151-153: Update the README guidance around raw atom values to
state that the displayed token amount depends on the fixture token’s decimals,
specifically noting that the committed Sepolia fixture labeled USDC uses 18
decimals; avoid presenting “5000000” as universally equal to 5 USDC, while
preserving the existing guidance about stringifying values above 2^53.
In `@apps/cowswap-e2e-tests/src/mocks/allowances/fixture.ts`:
- Around line 30-40: Update the chain ID validation in the allowance fixture
before calling allowanceKey: after converting chainKey to chainId, require
Number.isSafeInteger(chainId) and reject unsafe values with the existing
invalid-chain error path. Keep the decimal-format validation and lookup behavior
unchanged for safe integer IDs.
In `@apps/cowswap-e2e-tests/src/mocks/allowances/index.ts`:
- Around line 120-124: Update the catch handler in the allowance mock route to
bind the rejection as err: unknown, normalize it once with normalizeError(err),
and use the resulting error when pushing the problem message. Preserve the
existing route.continue() fallback behavior.
In `@apps/cowswap-e2e-tests/src/mocks/allowances/rpcUrls.ts`:
- Around line 10-13: The normalizeRpcUrl function currently removes a trailing
slash only after appending the query string, so paths ending in "/?" are not
normalized correctly. Normalize parsed.pathname before concatenating
parsed.search, preserving the query string, and add a test covering a trailing
slash before a query string.
In `@apps/cowswap-e2e-tests/src/mocks/balances/fixture.ts`:
- Around line 30-33: Validate the `chainId` produced in the chain-key parsing
flow with `Number.isSafeInteger()` and require it to be positive before using it
as a lookup key. Extend the existing error path near `DECIMAL_RE` and
`Number(chainKey)` to reject unsafe, infinite, fractional, or non-positive
values while preserving the current valid-chain behavior.
In `@apps/cowswap-e2e-tests/src/mocks/balances/types.ts`:
- Around line 21-27: Update balanceKey and balanceOwnerChainPrefix to normalize
the owner with getAddressKey() instead of manually calling toLowerCase(), while
preserving the existing chain and token formatting.
In `@apps/cowswap-e2e-tests/src/mockWallet/injectedShim.ts`:
- Around line 77-80: Update the rejection handler in the serialized injectedShim
function to accept `(err: unknown)`, normalize it once with the local
normalization helper, and pass the resulting error to callback. Keep the helper
inside the serialized function and preserve the existing callback arguments.
In `@apps/cowswap-e2e-tests/src/support/buildWalletCache.ts`:
- Around line 99-101: Update the catch handler in buildWalletCache to type its
rejection parameter as err: unknown, normalize it exactly once with const error
= normalizeError(err), and pass the normalized error to console.error before
exiting.
In `@apps/cowswap-e2e-tests/src/support/rpcProxy.test.ts`:
- Around line 89-93: Update the test around the /admin/reset request to query
the same worker balance again after the POST and assert that the dummy upstream
error is returned, verifying the reset cleared the worker stub rather than only
relying on the endpoint response.
In `@apps/cowswap-e2e-tests/src/support/rpcProxy.ts`:
- Around line 123-126: Normalize rejected values at both catch sites in
apps/cowswap-e2e-tests/src/support/rpcProxy.ts:123-126 and
apps/cowswap-e2e-tests/src/support/rpcProxy.ts:321-325 by typing each catch
parameter as unknown, calling normalizeError once to create error, and using
that normalized value for the HTTP response and JSON-RPC error respectively.
- Around line 104-108: Replace manual toLowerCase() address normalization with
getAddressKey in balanceKey and callKey in
apps/cowswap-e2e-tests/src/support/rpcProxy.ts (lines 104-108), applying it to
each address component. Also update price storage in
apps/cowswap-e2e-tests/src/mocks/usdPrices.ts (lines 23-25) and price lookup in
lines 55-61 to use getAddressKey for their EVM address keys.
In `@apps/cowswap-e2e-tests/src/tests/market-orders.spec.ts`:
- Line 27: Replace the non-empty output assertions in market-orders.spec.ts at
lines 27-27 and 46-46 with assertions against the configured expected output
amount, or poll until that exact value is stable; both sites require the same
change so stale default quotes cannot satisfy the tests.
---
Nitpick comments:
In `@apps/cowswap-e2e-tests/src/mocks/allowances/index.ts`:
- Line 45: Update installAllowances to await BrowserContext.route before
resolving, changing its return type as needed to expose an awaitable
installation; update its callers to await the returned mock before issuing
requests. Ensure allowance interception is registered before the mock is used
rather than relying on synchronous return timing.
In `@apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/record.ts`:
- Line 105: Add a 30-second timeout to the fetch request in the recording flow
by attaching AbortSignal.timeout(30_000) to the request options used for both
GET and POST calls. Update the shared options around the fetch invocation so
both methods receive the signal without changing their existing behavior.
In `@apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/types.ts`:
- Line 47: Update the CowApiOverrideFactory return type to unknown instead of
unknown | Promise<unknown>; resolveResponse already awaits the factory result,
so preserve its existing behavior while simplifying the type declaration.
🪄 Autofix
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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 4df44055-ca9f-43cf-8ac3-7ceaab0370ee
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (92)
AGENTS.mdapps/cowswap-e2e-tests/.env.exampleapps/cowswap-e2e-tests/.gitignoreapps/cowswap-e2e-tests/AGENTS.mdapps/cowswap-e2e-tests/README.mdapps/cowswap-e2e-tests/package.jsonapps/cowswap-e2e-tests/playwright.config.tsapps/cowswap-e2e-tests/project.jsonapps/cowswap-e2e-tests/src/fixtures/index.tsapps/cowswap-e2e-tests/src/fixtures/mockWallet.tsapps/cowswap-e2e-tests/src/fixtures/rpcProxy.tsapps/cowswap-e2e-tests/src/fixtures/shared.tsapps/cowswap-e2e-tests/src/fixtures/synpress.tsapps/cowswap-e2e-tests/src/fixtures/wallet.tsapps/cowswap-e2e-tests/src/mockWallet/injectedShim.tsapps/cowswap-e2e-tests/src/mockWallet/seedAutoConnect.tsapps/cowswap-e2e-tests/src/mockWallet/walletEngine.test.tsapps/cowswap-e2e-tests/src/mockWallet/walletEngine.tsapps/cowswap-e2e-tests/src/mocks/allowances/codec.test.tsapps/cowswap-e2e-tests/src/mocks/allowances/codec.tsapps/cowswap-e2e-tests/src/mocks/allowances/fixture.test.tsapps/cowswap-e2e-tests/src/mocks/allowances/fixture.tsapps/cowswap-e2e-tests/src/mocks/allowances/fixtures/allowances.jsonapps/cowswap-e2e-tests/src/mocks/allowances/index.tsapps/cowswap-e2e-tests/src/mocks/allowances/resolve.test.tsapps/cowswap-e2e-tests/src/mocks/allowances/resolve.tsapps/cowswap-e2e-tests/src/mocks/allowances/rpcUrls.test.tsapps/cowswap-e2e-tests/src/mocks/allowances/rpcUrls.tsapps/cowswap-e2e-tests/src/mocks/allowances/types.tsapps/cowswap-e2e-tests/src/mocks/balances/fixture.test.tsapps/cowswap-e2e-tests/src/mocks/balances/fixture.tsapps/cowswap-e2e-tests/src/mocks/balances/fixtures/balances.jsonapps/cowswap-e2e-tests/src/mocks/balances/index.tsapps/cowswap-e2e-tests/src/mocks/balances/resolve.test.tsapps/cowswap-e2e-tests/src/mocks/balances/resolve.tsapps/cowswap-e2e-tests/src/mocks/balances/types.tsapps/cowswap-e2e-tests/src/mocks/bungee.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/endpoints.test.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/endpoints.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/accountOrders.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/appData.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/nativePrice.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/order.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/orderStatus.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/quote.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/solverCompetition.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/solverCompetitionByTx.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/totalSurplus.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/trades.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/transactionOrders.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/fixtures/version.jsonapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/index.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/install.test.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/networks.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/normalize.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/record.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/resolve.test.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/resolve.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/types.tsapps/cowswap-e2e-tests/src/mocks/nearIntents.tsapps/cowswap-e2e-tests/src/mocks/safeSdk.tsapps/cowswap-e2e-tests/src/mocks/tokenLists.tsapps/cowswap-e2e-tests/src/mocks/usdPrices.tsapps/cowswap-e2e-tests/src/pages/AccountPage.tsapps/cowswap-e2e-tests/src/pages/ConfirmModal.tsapps/cowswap-e2e-tests/src/pages/HeaderPage.tsapps/cowswap-e2e-tests/src/pages/LimitPage.tsapps/cowswap-e2e-tests/src/pages/SwapPage.tsapps/cowswap-e2e-tests/src/pages/TokenSelector.tsapps/cowswap-e2e-tests/src/pages/TradePage.tsapps/cowswap-e2e-tests/src/pages/TwapPage.tsapps/cowswap-e2e-tests/src/support/buildWalletCache.tsapps/cowswap-e2e-tests/src/support/constants.tsapps/cowswap-e2e-tests/src/support/globalSetup.tsapps/cowswap-e2e-tests/src/support/globalTeardown.tsapps/cowswap-e2e-tests/src/support/rpcProxy.test.tsapps/cowswap-e2e-tests/src/support/rpcProxy.tsapps/cowswap-e2e-tests/src/support/setupTestConditions.test.tsapps/cowswap-e2e-tests/src/support/setupTestConditions.tsapps/cowswap-e2e-tests/src/support/synpress.tsapps/cowswap-e2e-tests/src/support/tokens.test.tsapps/cowswap-e2e-tests/src/support/tokens.tsapps/cowswap-e2e-tests/src/support/wallet.setup.tsapps/cowswap-e2e-tests/src/support/walletSetupHashProbe.spec.tsapps/cowswap-e2e-tests/src/tests/limit-orders.spec.tsapps/cowswap-e2e-tests/src/tests/market-orders.spec.tsapps/cowswap-e2e-tests/src/tests/network.spec.tsapps/cowswap-e2e-tests/tsconfig.jsonbundle-size.jsonceslint.config.jspackage.jsonpatches/@synthetixio__synpress-metamask@0.0.11.patch
shoom3301
left a comment
There was a problem hiding this comment.
✅ AI Review (Claude Sonnet 5, worked ~10m): follow-up addressed, no new findings
Rechecked
- WalletConnect downgrade finding: fixed in
b6a1aa9c9.package.jsonresolutions/dependencies/pnpm.peerDependencyRules.allowedVersionsfor@walletconnect/*are back to2.23.10, matchingdevelop.bundle-size.jsonc(which still carried the pre-fix numbers when this was first fixed) has since been corrected by the automatic bundle-size job in87961b30fand now matchesdevelopexactly — no diff remains. - Two additional issues found in a follow-up pass over this PR's own new code, fixed in
bee89ccc1:apps/cowswap-e2e-tests/src/mocks/allowances/resolve.test.ts: two tests ('matches regardless of address case','isOwnerConfigured sees owners from either map') called.toUpperCase()on the whole address including the0xprefix, which@cowprotocol/cow-sdk'sisEvmAddressdoesn't recognize as an EVM address (it requires a literal lowercase0x), sogetAddressKeyskipped normalization and the lookup missed. Fixed to uppercase only the hex body.apps/cowswap-e2e-tests/AGENTS.md: the "Known issues" section referenced abwEnabledPercentageLaunchDarkly flag already removed fromCommonPriorityBalancesAndAllowancesUpdater.tsxin #7985 (already in this branch's history) — updated to describe the currentisWatcherActive-based gating.
Result: All fixed. Re-ran npx tsx --test "src/**/*.test.ts" (123/123 pass), tsc --noEmit, and nx run cowswap-e2e-tests:lint against current HEAD (da89b12ca) — clean.
No new findings this round.
Review scope and related context
All 20 coderabbitai threads on this PR are resolved and hold up against current code (spot-checked safeSdk.ts, walletEngine.ts, SwapPage.mockSwapFulfillment, tokens.ts, wallet.setup.ts). This comment closes out the one thread (discussion_r3750735358) that was still open, plus reports two issues found and fixed outside any existing thread.
Generated using the pr-review skill from the CoW Protocol skills repo.
… feat/e2e-playwright-1
…l/cowswap into feat/e2e-playwright-2
… feat/e2e-playwright-2
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/cowswap-e2e-tests/src/pages/SwapPage.ts (1)
83-89: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winWait for the current quote before submitting orders.
data-isLoadingis absent when no request is active, so the predicate can pass before the request for the current input starts. Apply a request-specific completion check or assert the expected output value inSwapPage.ts,LimitPage.ts, andTwapPage.ts.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/cowswap-e2e-tests/src/pages/SwapPage.ts` around lines 83 - 89, The quote wait logic in waitForQuote must not complete while no request is active; replace the data-isLoading-only predicate with a request-specific completion check or validation of the expected output value. Apply the same correction in SwapPage.ts (waitForQuote), LimitPage.ts (its quote-wait flow), and TwapPage.ts so orders are submitted only after the current input’s quote has completed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/cowswap-e2e-tests/src/mocks/balances/index.ts`:
- Around line 116-121: Update handleSse() so balances.set() invoked by postOrder
delivers the updated snapshot to the active EventSource response
deterministically, rather than relying on retry: 800 reconnects. Add a direct
SSE push or explicit synchronization between the balance update and response
delivery, while preserving the existing initial snapshot behavior.
In `@apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/index.ts`:
- Line 77: Await every installCowProtocolApi invocation, including the calls in
shared.ts and install.test.ts, so route registration completes before exposing
CowProtocolApiMock or starting navigation. Propagate async setup through the
surrounding fixture and test functions as needed while preserving existing mock
behavior.
---
Outside diff comments:
In `@apps/cowswap-e2e-tests/src/pages/SwapPage.ts`:
- Around line 83-89: The quote wait logic in waitForQuote must not complete
while no request is active; replace the data-isLoading-only predicate with a
request-specific completion check or validation of the expected output value.
Apply the same correction in SwapPage.ts (waitForQuote), LimitPage.ts (its
quote-wait flow), and TwapPage.ts so orders are submitted only after the current
input’s quote has completed.
🪄 Autofix
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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: d9ae55b2-f057-41a2-9bc8-e2917da78716
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (29)
apps/cowswap-e2e-tests/AGENTS.mdapps/cowswap-e2e-tests/package.jsonapps/cowswap-e2e-tests/playwright.config.tsapps/cowswap-e2e-tests/src/fixtures/rpcProxy.tsapps/cowswap-e2e-tests/src/fixtures/shared.tsapps/cowswap-e2e-tests/src/mockWallet/walletEngine.tsapps/cowswap-e2e-tests/src/mocks/allowances/codec.test.tsapps/cowswap-e2e-tests/src/mocks/allowances/codec.tsapps/cowswap-e2e-tests/src/mocks/allowances/resolve.test.tsapps/cowswap-e2e-tests/src/mocks/allowances/types.tsapps/cowswap-e2e-tests/src/mocks/balances/index.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/index.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/install.test.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/normalize.tsapps/cowswap-e2e-tests/src/mocks/cowProtocolApi/resolve.test.tsapps/cowswap-e2e-tests/src/mocks/safeSdk.tsapps/cowswap-e2e-tests/src/pages/ConfirmModal.tsapps/cowswap-e2e-tests/src/pages/HeaderPage.tsapps/cowswap-e2e-tests/src/pages/LimitPage.tsapps/cowswap-e2e-tests/src/pages/SwapPage.tsapps/cowswap-e2e-tests/src/pages/TokenSelector.tsapps/cowswap-e2e-tests/src/support/rpcProxy.tsapps/cowswap-e2e-tests/src/support/setupTestConditions.test.tsapps/cowswap-e2e-tests/src/support/tokens.test.tsapps/cowswap-e2e-tests/src/support/tokens.tsapps/cowswap-e2e-tests/src/support/wallet.setup.tsapps/cowswap-e2e-tests/src/tests/limit-orders.spec.tsapps/cowswap-e2e-tests/src/tests/market-orders.spec.tspackage.json
🚧 Files skipped from review as they are similar to previous changes (19)
- apps/cowswap-e2e-tests/playwright.config.ts
- apps/cowswap-e2e-tests/src/fixtures/rpcProxy.ts
- apps/cowswap-e2e-tests/src/pages/HeaderPage.ts
- apps/cowswap-e2e-tests/src/pages/ConfirmModal.ts
- apps/cowswap-e2e-tests/src/tests/limit-orders.spec.ts
- apps/cowswap-e2e-tests/src/support/setupTestConditions.test.ts
- apps/cowswap-e2e-tests/src/mocks/allowances/types.ts
- apps/cowswap-e2e-tests/src/support/tokens.test.ts
- apps/cowswap-e2e-tests/package.json
- apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/install.test.ts
- apps/cowswap-e2e-tests/src/support/tokens.ts
- apps/cowswap-e2e-tests/src/tests/market-orders.spec.ts
- apps/cowswap-e2e-tests/src/mocks/safeSdk.ts
- apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/normalize.ts
- apps/cowswap-e2e-tests/src/mockWallet/walletEngine.ts
- apps/cowswap-e2e-tests/src/mocks/cowProtocolApi/resolve.test.ts
- apps/cowswap-e2e-tests/src/mocks/allowances/codec.test.ts
- apps/cowswap-e2e-tests/src/mocks/allowances/codec.ts
- apps/cowswap-e2e-tests/src/support/rpcProxy.ts
… feat/e2e-playwright-2 # Conflicts: # pnpm-lock.yaml
Fixes:
What changed
apps/cowswap-e2e-tests, replacing the removed legacy e2e tests.fixtures/mockWallet— an in-process viem account (EIP-6963 injected), instant signing, no extension. Used by every current spec.fixtures(Synpress) — a real MetaMask extension, for connect/approve/network-switch UI itself.src/support/rpcProxy.ts) sits between the app and Sepolia so each test gets isolated chain-state stubs.quote,postOrder,accountOrders,orderStatus,order, ...), ERC-20 allowances, and the balances-watcher SSE endpoint. Any unmocked CoW API call fails the test at teardown by default.src/pages/) for Swap, Limit, TWAP, Account, TokenSelector, ConfirmModal, Header, Trade.@smoke).Why
(connect/approve/network-switch popups).
fail-fast: false) catches regressions and Synpress/MetaMask version drift without blocking PRs.Testing
Developer verification:
pnpm e2e:build-cacheonce, thenpnpm --filter @cowprotocol/cowswap-e2e-pw exec playwright testruns the full suite locally.pnpm e2e:uiruns Playwright app where you can manually run specific tests.npx tsx --test "src/**/*.test.ts"covers the mocks/support code in isolation (no browser).Reviewer note:
cypresswhich are removed in the mentioned PR.Summary by CodeRabbit
New Features
Documentation
Tests