Skip to content

Conversation

@crutch12
Copy link
Contributor

@crutch12 crutch12 commented Dec 23, 2025

Summary

Tests have been disabled for a long time because of fails, so I've decided to bring them back alive.

Main changes

  • fixed page loading (cypress didn't stat test because of idle page status)
    • also disabled Service Worker for e2e environment
  • actualized README
  • updated tests to work with current functionality
  • added mockSendCall to mock user's balance and allowance
  • updated vite build config

To Test

  1. yarn e2e should work and success
  2. yarn e2e:open should work (idk why, but it doesn't work with my Google Chrome, so I use Ms Edge)

Since dev server doesn't work too fast, I've tested it only for production build.

Background

Offtop I think Cypress is not the best e2e framework 🫠

Summary by CodeRabbit

  • Tests

    • Numerous E2E tests re-enabled or restructured, added per-test setup and mocks for blockchain interactions, new unlock helper command, adjusted timeouts and faster load behavior.
  • Documentation

    • Updated integration test instructions and standardized E2E environment variable names.
  • Chores

    • Added E2E environment placeholders, updated test project build/config, and tightened TypeScript return types.
  • Bug Fixes

    • Added runtime guards to service-worker logic to prevent errors on unsupported platforms.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 23, 2025

@crutch12 is attempting to deploy a commit to the cow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

Walkthrough

Adds a root E2E .env, updates README, re-enables and adapts many Cypress E2E tests, introduces a provider mock middleware and cy.unlockCrossChainSwap command, adjusts Cypress/Vite config and TS paths, and tightens TypeScript signatures and DOM IDs used by tests.

Changes

Cohort / File(s) Summary
E2E env & docs
\.env, README.md, apps/cowswap-frontend/.env
Adds root .env with Cypress placeholders (CYPRESS_INTEGRATION_TEST_PRIVATE_KEY, CYPRESS_INTEGRATION_TESTS_INFURA_KEY), updates README instructions and variable names, and removes old E2E vars from apps/cowswap-frontend/.env.
Cypress config & TS paths
apps/cowswap-frontend-e2e/cypress.config.ts, apps/cowswap-frontend-e2e/tsconfig.json
Adds Vite overrides (node polyfills, vite-tsconfig-paths, macrosPlugin), adjusts timeouts (pageLoadTimeout=15000, defaultCommandTimeout=5000), and adds @cowprotocol/* path mappings.
Provider mock middleware
apps/cowswap-frontend-e2e/src/support/mocks/mockSendCall.ts
New middleware chain to stub ethereum.send with helpers: mockSendCall, handleTokenBalance, handleTokenAllowance, handleNativeBalance; handles eth_call, eth_getBalance, multicall3 encode/decode and delegates when unmatched.
E2E support & global setup
apps/cowswap-frontend-e2e/src/support/e2e.ts, apps/cowswap-frontend-e2e/src/support/commands.ts
Replaces window:load with before:load, adds analytics/third-party intercepts and caching, updates Infura origin handling and VisitOptions typing, implements cy.unlockCrossChainSwap() and adjusts token selection selectors.
E2E tests (enable & adapt)
apps/cowswap-frontend-e2e/src/e2e/*
Re-enables and adapts many tests (fee, fiat-amounts, limit-orders, lists, search, swap, swapMod, token), adds cy.unlockCrossChainSwap() prerequisites and onBeforeLoad mocks, updates selectors (#do-trade-button), adds explicit return types, and removes send.test.ts.
Support typings / small TS changes
apps/cowswap-frontend-e2e/src/support/ethereum.ts, various *.test.ts
Minor ESLint/typing adjustments, slight error string tweak, and added explicit return types for helper functions used in tests.
Frontend DOM IDs & runtime guards
apps/cowswap-frontend/src/modules/.../TradeApproveButton/TradeApproveButton.tsx, .../swapTradeButtonsMap.tsx, apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx, apps/cowswap-frontend/src/serviceWorkerRegistration.ts
Adds id="approve-trade-button" and id="do-trade-button" for E2E selectors; tightens return types and adds runtime guards around service worker usage.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant T as Cypress test
  participant B as Browser / App
  participant E as window.ethereum
  participant M as Mock middleware chain

  Note over T,B: cy.visit(..., onBeforeLoad) installs mocks & stubs
  T->>B: cy.visit(onBeforeLoad)
  B->>E: App invokes ethereum.send(method, params)
  E->>M: Stubbed send forwards call to middleware chain
  alt middleware handles call (balance/allowance/multicall)
    M-->>E: Return mocked RPC response
  else not handled
    M-->>E: Forward to original provider / real send
  end
  E-->>B: RPC response (mocked or real)
  B-->>T: UI updates (balances/allowances)
  T->>B: cy.unlockCrossChainSwap() (click `#unlock-cross-chain-swap-btn`)
  B-->>T: UI enters unlocked state
  T->>B: User actions -> click `#do-trade-button`
  B-->>T: Confirmation UI appears
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • alfetopito
  • shoom3301
  • limitofzero

Poem

Hopping through mocks with a twitch of my nose, 🐇
I stitch RPC replies where the test garden grows.
Buttons now labeled, the swaps wake and hum,
Unlock, click, assert — the CI drum will thrum.
Tiny rabbit cheers — tests march on, here we come!

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.86% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: restore e2e tests' is clear, concise, and directly summarizes the main objective of the changeset: re-enabling previously disabled end-to-end tests.
Description check ✅ Passed The PR description provides a summary, lists main changes, and includes testing instructions, but is missing the structured format required by the template (lacks explicit 'To Test' checkboxes and Background section formatting).

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 28c2122 and 56d52a9.

📒 Files selected for processing (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • README.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Cypress
  • GitHub Check: Setup

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.

@elena-zh elena-zh requested a review from a team December 23, 2025 12:04
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (7)
.env (1)

1-8: Add a trailing blank line.

The file is missing a blank line at the end, which is flagged by the dotenv-linter.

🔎 Proposed fix
 CYPRESS_INTEGRATION_TEST_PRIVATE_KEY=
 CYPRESS_INTEGRATION_TESTS_INFURA_KEY=
+
apps/cowswap-frontend-e2e/src/support/ethereum.ts (1)

22-22: Minor: Trailing comma in error message.

The error message string now includes a trailing comma, which is unconventional but harmless. Consider removing it for cleaner output.

🔎 Proposed fix
-  `PROVIDER_URL is empty, NETWORK_URL=${NETWORK_URL}, INTEGRATION_TESTS_INFURA_KEY=${INTEGRATION_TESTS_INFURA_KEY}`,
+  `PROVIDER_URL is empty, NETWORK_URL=${NETWORK_URL}, INTEGRATION_TESTS_INFURA_KEY=${INTEGRATION_TESTS_INFURA_KEY}`
apps/cowswap-frontend-e2e/cypress.config.ts (1)

34-34: Consider if 30s page load timeout is sufficient for E2E tests.

The pageLoadTimeout is set to 30 seconds (reduced from Cypress's default of 60 seconds). While this may work for fast development environments, E2E tests running in CI or slower environments might experience intermittent failures due to genuine slow page loads.

apps/cowswap-frontend-e2e/src/e2e/fee.test.ts (1)

98-100: Replace hardcoded wait(1000) with proper element waiting.

Using cy.wait(1000) introduces flakiness and unnecessary delays. Instead, wait for specific UI elements or conditions to be ready.

Example: wait for output token to be visible
 cy.unlockCrossChainSwap()
 cy.swapSelectInput(USDC)
-cy.wait(1000)
+cy.get('#output-currency-input .open-currency-select-button').should('be.visible')
 cy.swapSelectOutput(COW)

Also applies to: 145-147

apps/cowswap-frontend-e2e/src/e2e/swap.test.ts (1)

102-102: Replace hardcoded cy.wait(1000) with explicit element waiting.

Similar to the fee tests, this hardcoded delay introduces flakiness. Wait for the specific UI element to be ready instead.

Example refactor
 acceptFeesExceedWarning()
-cy.wait(1000)
-cy.get('#classic-eth-flow-banner').should('contain', 'Wrap your ETH and use the classic WETH experience').click()
+cy.get('#classic-eth-flow-banner', { timeout: 5000 }).should('be.visible').should('contain', 'Wrap your ETH and use the classic WETH experience').click()
apps/cowswap-frontend-e2e/src/support/mocks/mockSendCall.ts (2)

13-51: Consider adding explicit return types.

The function correctly handles both callback and promise forms of ethereum.send. However, the return type and Function type on line 15 could be more specific for better type safety.

🔎 Optional refactor for type safety
-// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-function-return-type
-function parseSendArgs(send: typeof injected.send, ...args: any[]) {
+function parseSendArgs(send: typeof injected.send, ...args: any[]): {
+  method: string | undefined
+  params: any[] | undefined
+  getOriginalResult: () => Promise<BytesLike>
+  returnResult: (value: unknown) => Promise<unknown> | void
+} {
   const isCallbackForm = typeof args[0] === 'object' && typeof args[1] === 'function'
-  let callback: Function | undefined
+  let callback: ((value: unknown) => void) | undefined

94-94: Redundant property assignment.

Setting both item[1] and item.returnData assigns to the same property twice since item[1] and item.returnData refer to the same value in the tuple.

🔎 Simplify to single assignment
-        item[1] = item.returnData = returnData
+        item.returnData = returnData
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f287a0 and 9eda11c.

📒 Files selected for processing (22)
  • .env
  • README.md
  • apps/cowswap-frontend-e2e/cypress.config.ts
  • apps/cowswap-frontend-e2e/src/e2e/fee.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/limit-orders.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/lists.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/search.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/send.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
  • apps/cowswap-frontend-e2e/src/support/commands.ts
  • apps/cowswap-frontend-e2e/src/support/e2e.ts
  • apps/cowswap-frontend-e2e/src/support/ethereum.ts
  • apps/cowswap-frontend-e2e/src/support/mocks/mockSendCall.ts
  • apps/cowswap-frontend-e2e/tsconfig.json
  • apps/cowswap-frontend/.env
  • apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx
  • apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveButton/TradeApproveButton.tsx
  • apps/cowswap-frontend/src/modules/swap/containers/TradeButtons/swapTradeButtonsMap.tsx
  • apps/cowswap-frontend/src/serviceWorkerRegistration.ts
💤 Files with no reviewable changes (2)
  • apps/cowswap-frontend/.env
  • apps/cowswap-frontend-e2e/src/e2e/send.test.ts
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.
📚 Learning: 2025-07-28T16:26:08.051Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/search.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/limit-orders.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/lists.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/fee.test.ts
  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-09-25T08:48:53.495Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-09-25T08:49:32.256Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
  • apps/cowswap-frontend-e2e/src/support/mocks/mockSendCall.ts
  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
  • apps/cowswap-frontend-e2e/src/support/commands.ts
  • apps/cowswap-frontend-e2e/src/e2e/fee.test.ts
📚 Learning: 2025-08-08T13:55:17.528Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6125
File: libs/tokens/src/state/tokens/allTokensAtom.ts:78-78
Timestamp: 2025-08-08T13:55:17.528Z
Learning: In libs/tokens/src/state/tokens/allTokensAtom.ts (TypeScript/Jotai), the team prefers to wait for token lists to initialize (listsStatesListAtom non-empty) before returning tokens. No fallback to favorites/user-added/native tokens should be used when listsStatesList is empty.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
📚 Learning: 2025-02-20T15:59:33.749Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5443
File: apps/cowswap-frontend/src/modules/swap/containers/ConfirmSwapModalSetup/index.tsx:71-71
Timestamp: 2025-02-20T15:59:33.749Z
Learning: The swap module in apps/cowswap-frontend/src/modules/swap/ is marked for deletion in PR #5444 as part of the swap widget unification effort.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
📚 Learning: 2025-10-10T20:28:16.565Z
Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 6347
File: apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx:49-49
Timestamp: 2025-10-10T20:28:16.565Z
Learning: In apps/cowswap-frontend/src/modules/trade, TradeConfirmation follows a two-layer architecture: TradeConfirmationView (pure/stateless) in pure/TradeConfirmation/index.tsx renders the UI, while TradeConfirmation (container) in containers/TradeConfirmation/index.tsx wraps it to freeze props during pending trades (via useStableTradeConfirmationProps), wire in signing state (useSigningStep), and inject trade confirmation state (useTradeConfirmState). Consuming modules should import the container TradeConfirmation from 'modules/trade' to preserve this stateful behavior.
<!-- [add_learning]
When reviewing component refactoring in apps/cowswap-frontend/src/modules/trade, recognize the pattern where a pure view component (e.g., TradeConfirmationView) is separated from a stateful container (e.g., TradeConfirmation) that wraps it. The container adds runtime state management (prop stabilization, signing state, etc.) while the view remains testable and composable. Do not flag usages that import th...

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
  • apps/cowswap-frontend/src/modules/swap/containers/TradeButtons/swapTradeButtonsMap.tsx
  • apps/cowswap-frontend-e2e/src/e2e/limit-orders.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveButton/TradeApproveButton.tsx
📚 Learning: 2025-10-13T19:41:31.440Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveButton/TradeApproveButton.tsx
📚 Learning: 2025-09-19T11:38:59.206Z
Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 6232
File: apps/cowswap-frontend/src/modules/tokensList/pure/ChainsSelector/index.tsx:199-200
Timestamp: 2025-09-19T11:38:59.206Z
Learning: The makeBuildClickEvent function in apps/cowswap-frontend/src/modules/tokensList/pure/ChainsSelector/index.tsx takes five parameters: defaultChainId, contextLabel, mode, isSwapMode, and chainsCount. The chainsCount parameter is used to determine the CrossChain flag in analytics events.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/swap.test.ts
  • apps/cowswap-frontend/src/modules/swap/containers/TradeButtons/swapTradeButtonsMap.tsx
  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
  • apps/cowswap-frontend-e2e/src/support/commands.ts
📚 Learning: 2025-07-24T16:42:53.154Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6009
File: apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/HighFeeWarning/HighFeeWarningTooltipContent.tsx:23-33
Timestamp: 2025-07-24T16:42:53.154Z
Learning: In apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/HighFeeWarning/HighFeeWarningTooltipContent.tsx, the use of toFixed(2) for percentage formatting in tooltip content is intentional and differs from the banner message formatting that uses toSignificant(2, undefined, Rounding.ROUND_DOWN). This formatting difference serves different UX purposes and should not be flagged as inconsistent.

Applied to files:

  • apps/cowswap-frontend/src/modules/swap/containers/TradeButtons/swapTradeButtonsMap.tsx
📚 Learning: 2025-11-19T10:18:23.717Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6537
File: apps/cowswap-frontend/src/modules/trade/pure/PartnerFeeRow/index.tsx:33-35
Timestamp: 2025-11-19T10:18:23.717Z
Learning: In apps/cowswap-frontend/src/modules/trade/pure/PartnerFeeRow/index.tsx, when there is no partner fee (amount is null/undefined, bps is missing, or amount equals 0), FreeFeeRow is rendered with withTimelineDot={false} hardcoded. This is intentional design—free fee rows should not show the timeline dot regardless of what the parent component passes, as they have a distinct visual treatment from actual fee rows.

Applied to files:

  • apps/cowswap-frontend/src/modules/swap/containers/TradeButtons/swapTradeButtonsMap.tsx
  • apps/cowswap-frontend-e2e/src/e2e/fee.test.ts
📚 Learning: 2025-05-26T12:39:29.009Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 5715
File: libs/common-const/src/tokens.ts:539-555
Timestamp: 2025-05-26T12:39:29.009Z
Learning: The team accepts using NATIVE_CURRENCY_ADDRESS as a temporary placeholder for COW token contract addresses on new networks (Polygon, Avalanche) until actual COW contracts are deployed.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
📚 Learning: 2025-06-25T07:28:32.570Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5881
File: apps/cowswap-frontend/src/modules/cowShed/containers/ProxyRecipient/index.tsx:68-72
Timestamp: 2025-06-25T07:28:32.570Z
Learning: In the ProxyRecipient component (apps/cowswap-frontend/src/modules/cowShed/containers/ProxyRecipient/index.tsx), throwing an error when recipient address doesn't match proxy address is intentional design choice to prevent proceeding with incorrect data and ensure data integrity.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
📚 Learning: 2025-02-21T13:00:04.809Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5443
File: apps/cowswap-frontend/src/modules/swap/hooks/useSwapWidgetActions.ts:37-37
Timestamp: 2025-02-21T13:00:04.809Z
Learning: Recipient address validation in the swap widget is handled in a different layer, not in the onChangeRecipient callback.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts
📚 Learning: 2025-07-24T10:00:45.353Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6009
File: apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/HighFeeWarning/hooks/useHighFeeWarning.ts:36-36
Timestamp: 2025-07-24T10:00:45.353Z
Learning: In the CowSwap frontend, when there's a bridgeFee present in the transaction, the isSell flag is always true for business reasons. This means bridge transactions are always structured as sell operations, which ensures consistent currency handling in fee percentage calculations.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/fee.test.ts
📚 Learning: 2025-12-03T19:23:35.789Z
Learnt from: kernelwhisperer
Repo: cowprotocol/cowswap PR: 6610
File: apps/cowswap-frontend/project.json:38-39
Timestamp: 2025-12-03T19:23:35.789Z
Learning: In the cowswap-frontend project configuration (apps/cowswap-frontend/project.json), the Vite dev server option `"host": true` is set to support Windows + WSL development environments, where binding to all network interfaces is required for the Windows host to access the dev server running in WSL.

Applied to files:

  • apps/cowswap-frontend-e2e/cypress.config.ts
📚 Learning: 2025-09-11T08:25:51.460Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 6234
File: libs/tokens/src/index.ts:1-4
Timestamp: 2025-09-11T08:25:51.460Z
Learning: In the cowprotocol/cowswap project, there is currently no SSR (Server-Side Rendering) support, so localStorage access at module import time does not cause SSR-related issues.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
🧬 Code graph analysis (6)
apps/cowswap-frontend-e2e/src/e2e/swap.test.ts (2)
libs/common-const/src/tokens.ts (1)
  • USDC (540-557)
apps/cowswap-frontend-e2e/src/support/mocks/mockSendCall.ts (4)
  • mockSendCall (140-151)
  • handleTokenBalance (104-106)
  • handleTokenAllowance (108-110)
  • handleNativeBalance (136-138)
apps/cowswap-frontend/src/modules/swap/containers/TradeButtons/swapTradeButtonsMap.tsx (1)
libs/ui/src/pure/Button/index.tsx (1)
  • ButtonError (232-238)
apps/cowswap-frontend-e2e/src/support/mocks/mockSendCall.ts (1)
apps/cowswap-frontend-e2e/src/support/ethereum.ts (2)
  • send (47-118)
  • injected (124-124)
apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts (1)
apps/cowswap-frontend-e2e/src/support/mocks/mockSendCall.ts (2)
  • mockSendCall (140-151)
  • handleNativeBalance (136-138)
apps/cowswap-frontend-e2e/src/e2e/fee.test.ts (1)
libs/common-const/src/tokens.ts (1)
  • USDC (540-557)
apps/cowswap-frontend-e2e/src/support/e2e.ts (1)
apps/cowswap-frontend-e2e/src/support/ethereum.ts (1)
  • injected (124-124)
🪛 dotenv-linter (4.0.0)
.env

[warning] 8-8: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)


[warning] 8-8: [UnorderedKey] The CYPRESS_INTEGRATION_TESTS_INFURA_KEY key should go before the CYPRESS_INTEGRATION_TEST_PRIVATE_KEY key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Setup
  • GitHub Check: Cypress
🔇 Additional comments (31)
apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx (3)

62-64: LGTM! Defensive runtime guard for service worker availability.

This check prevents errors in environments where service workers are unavailable (e.g., E2E tests, certain browsers). The error is properly caught by the catch block at lines 97-99.


103-107: LGTM! Explicit return type annotations improve type safety.

The explicit : void and : React.ReactNode annotations correctly reflect React's lifecycle method signatures and improve TypeScript type safety.


147-152: LGTM! Explicit return type annotations are correct.

The : React.ReactNode return type for the HOC and : void for the error handler correctly reflect their behavior and improve TypeScript type safety.

apps/cowswap-frontend/src/serviceWorkerRegistration.ts (1)

26-26: LGTM! Explicit return type annotations improve type safety.

Adding explicit : void return types to registerValidSW, checkValidServiceWorker, register, and unregister is good TypeScript practice. The early return guard at line 96 is also a sensible defensive check.

Also applies to: 70-70, 95-96, 132-132

README.md (1)

116-120: LGTM!

The documentation updates correctly reflect the new Cypress-prefixed environment variables and provide clearer instructions for E2E test setup.

apps/cowswap-frontend-e2e/src/e2e/lists.test.ts (1)

6-7: LGTM!

Re-enabling the test with the proper prerequisite (unlockCrossChainSwap) is appropriate. This aligns with the PR's objective to restore E2E tests.

apps/cowswap-frontend/src/modules/swap/containers/TradeButtons/swapTradeButtonsMap.tsx (1)

54-59: LGTM!

Adding the id attribute provides a stable selector for E2E tests. The naming is clear and follows good practices for test automation.

apps/cowswap-frontend-e2e/src/support/e2e.ts (3)

48-56: LGTM!

Disabling the service worker via window:before:load is the correct approach to prevent interference with test execution, as noted in the comment about Safari SDK and window.load event issues.


58-69: LGTM!

Blocking analytics and tracking URLs during E2E tests prevents external network dependencies and speeds up test execution.


71-89: LGTM!

Moving initialization to window:before:load within beforeEach ensures proper setup timing. Using Cypress.config('baseUrl') for the origin header is more flexible than a hardcoded value.

apps/cowswap-frontend-e2e/src/e2e/search.test.ts (2)

1-3: LGTM!

Adding an explicit return type improves code clarity and type safety.


10-86: LGTM!

Re-enabling the test suite with consistent prerequisites (unlockCrossChainSwap) across all tests is appropriate and aligns with the PR's objective to restore E2E tests.

apps/cowswap-frontend-e2e/src/e2e/token.test.ts (2)

3-6: Good approach to speed up tests by mocking slow endpoints.

The intercept for safe.global/tx-service returning a 404 effectively bypasses a slow-loading dependency, allowing the token search tests to run without the long wait times.


14-30: LGTM! Token search tests are now active and well-structured.

The tests properly verify token search by name, address, and case-insensitive address. Each test independently visits the page for good isolation.

apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts (2)

1-7: Good addition of explicit return types.

Adding Cypress.Chainable return types improves TypeScript support and makes the helper functions' contracts clearer.


18-38: LGTM! Test properly verifies fiat amount scaling.

The test includes the necessary unlock step and correctly verifies that fiat amounts scale proportionally with input amounts.

apps/cowswap-frontend-e2e/src/support/commands.ts (2)

69-74: LGTM! Well-structured Cypress command addition.

The unlockCrossChainSwap command is properly documented, includes visibility checks before clicking, and follows Cypress best practices. The command is correctly registered and typed.

Also applies to: 185-187, 214-214


108-108: Good improvement for case-insensitive token matching.

Converting the token address to lowercase ensures the selector works regardless of address casing variations in the DOM.

apps/cowswap-frontend-e2e/src/e2e/swapMod.test.ts (2)

1-1: Good addition of mocking utilities for reliable E2E tests.

Importing and using mockSendCall with handleNativeBalance allows tests to run with predictable blockchain state, reducing flakiness from actual network conditions.

Also applies to: 79-89


11-116: LGTM! Comprehensive swap test coverage with proper setup.

The test suite now includes:

  • Proper per-test isolation with individual cy.visit calls
  • Cross-chain swap unlocking before interactions
  • Multiple input validation scenarios (empty, valid, zero, invalid)
  • Native token swap with mocked balances
  • Recipient mode verification

The updated selector #do-trade-button aligns with the UI changes mentioned in the PR.

apps/cowswap-frontend-e2e/src/e2e/limit-orders.test.ts (2)

5-23: Good addition of explicit return types for helper functions.

Adding void and Cypress.Chainable return types improves type safety and code clarity.


25-76: LGTM! Comprehensive limit order URL parameter testing.

The test suite is now active and includes thorough coverage of URL parameter handling:

  • Individual sellAmount and buyAmount parameters
  • Parameter validation when tokens are missing
  • Parameter precedence rules

The skipped confirmation test has a clear TODO marker for future work.

apps/cowswap-frontend-e2e/src/e2e/swap.test.ts (2)

5-10: Excellent use of mocking for reliable swap tests.

The tests properly mock blockchain interactions using mockSendCall with:

  • Token balances via handleTokenBalance
  • Token allowances via handleTokenAllowance
  • Native ETH balance via handleNativeBalance

This ensures tests run consistently without depending on actual blockchain state.

Also applies to: 34-49, 61-71, 84-94


31-142: LGTM! Comprehensive swap test suite with proper E2E coverage.

The test suite now includes:

  • WETH/USDC swaps with mocked balances and allowances
  • Native ETH swaps with proper balance mocking
  • ETH wrapping flow with banner interactions
  • Extensive URL parameter validation

Tests are well-isolated and include proper unlock steps. The selector updates to #do-trade-button align with the UI changes.

apps/cowswap-frontend-e2e/cypress.config.ts (1)

3-5: All three Vite plugins (vite-plugin-babel-macros, vite-plugin-node-polyfills, vite-tsconfig-paths) are properly declared in package.json devDependencies and are correctly imported in this configuration.

apps/cowswap-frontend-e2e/src/support/mocks/mockSendCall.ts (6)

1-11: LGTM: Imports and setup are appropriate.

The ESLint suppressions are acceptable for test utilities, and the direct import of getMulticallContract to avoid bundling overhead is well-documented.


104-110: LGTM: Token balance and allowance handlers are correct.

The ERC-20 method selectors (0x70a08231 for balanceOf, 0xdd62ed3e for allowance) are accurate, and the encoding is appropriate.


136-138: LGTM: Native balance handler wrapper is correct.

The function appropriately encodes the balance value and delegates to handleNativeBalanceCall.


140-151: LGTM: Middleware chain implementation is solid.

The middleware pattern correctly chains handlers and falls back to the original send method when no middleware matches. The use of cy.stub is appropriate for Cypress tests.


54-54: LGTM: MockMiddleware type is appropriate.

The type definition correctly captures the flexible middleware signature needed for intercepting various Ethereum RPC calls.


89-89: No action needed. structuredClone is already used elsewhere in the codebase (e.g., apps/explorer/src/explorer/pages/AppData/config.tsx) without compatibility issues or polyfills, indicating the project targets environments where it's supported. Cypress 15.4.0 with Node 20.x LTS runs in modern browsers that natively support structuredClone.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/cowswap-frontend-e2e/src/support/e2e.ts (1)

50-56: Consider using Object.getPrototypeOf() instead of __proto__.

__proto__ is deprecated. A more modern approach:

-    // @ts-expect-error
-    delete win.navigator.__proto__.serviceWorker
+    // @ts-expect-error -- deleting from prototype to disable SW
+    delete Object.getPrototypeOf(win.navigator).serviceWorker

This is a minor improvement for future compatibility.

apps/cowswap-frontend-e2e/cypress.config.ts (1)

24-24: Consider verifying if Babel macros are actively used.

The macrosPlugin enables Babel macro transformations at build time. If the codebase doesn't use macro-based libraries (e.g., styled-components/macro, preval.macro), this plugin may be unnecessary overhead.

#!/bin/bash
# Description: Search for macro usage in the codebase to verify if macrosPlugin is needed.

echo "=== Searching for macro imports ==="
rg -n --type ts --type tsx --type js --type jsx 'from.*\.macro' || echo "No macro imports found"
echo ""

echo "=== Searching for babel-plugin-macros usage ==="
rg -n 'babel-plugin-macros|@babel/plugin-macros' package.json || echo "No babel macros plugin config found"
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a340bf and ea2600e.

📒 Files selected for processing (3)
  • apps/cowswap-frontend-e2e/cypress.config.ts
  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
  • apps/cowswap-frontend-e2e/src/support/e2e.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.
📚 Learning: 2025-09-25T08:48:53.495Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-07-28T16:26:08.051Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-09-11T08:25:51.460Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 6234
File: libs/tokens/src/index.ts:1-4
Timestamp: 2025-09-11T08:25:51.460Z
Learning: In the cowprotocol/cowswap project, there is currently no SSR (Server-Side Rendering) support, so localStorage access at module import time does not cause SSR-related issues.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-09-25T08:49:32.256Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-12-03T19:23:35.789Z
Learnt from: kernelwhisperer
Repo: cowprotocol/cowswap PR: 6610
File: apps/cowswap-frontend/project.json:38-39
Timestamp: 2025-12-03T19:23:35.789Z
Learning: In the cowswap-frontend project configuration (apps/cowswap-frontend/project.json), the Vite dev server option `"host": true` is set to support Windows + WSL development environments, where binding to all network interfaces is required for the Windows host to access the dev server running in WSL.

Applied to files:

  • apps/cowswap-frontend-e2e/cypress.config.ts
🧬 Code graph analysis (1)
apps/cowswap-frontend-e2e/src/support/e2e.ts (1)
apps/cowswap-frontend-e2e/src/support/ethereum.ts (1)
  • injected (124-124)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Cypress
  • GitHub Check: Setup
🔇 Additional comments (9)
apps/cowswap-frontend-e2e/src/support/e2e.ts (3)

33-48: LGTM!

The visit command overwrite correctly ensures a clean localStorage state and injects the ethereum provider for each page visit.


58-71: LGTM!

Blocking analytics and third-party requests in E2E tests is good practice for test reliability and speed.


85-119: LGTM!

The beforeEach setup correctly handles:

  • Infura origin headers using baseUrl config
  • Blocking analytics/third-party requests
  • Response caching for static resources
  • Provider injection via window:before:load

The duplicate localStorage/ethereum setup in both the visit overwrite and window:before:load handler ensures coverage for all navigation patterns.

apps/cowswap-frontend-e2e/cypress.config.ts (6)

11-26: LGTM! Vite configuration is appropriate for Cypress E2E testing.

The viteConfigOverrides section properly configures the Vite bundler for Cypress with Node.js polyfills, TypeScript path resolution, and Babel macro support. The plugin ordering (polyfills → path resolution → macro transformation) is logical.


13-20: LGTM! Node.js polyfills are correctly configured.

The polyfills for Buffer, global, and process, along with protocolImports, are necessary because Vite doesn't include Node.js polyfills by default. This configuration is appropriate for Cypress E2E tests.


33-33: Monitor for potential test flakiness from reduced timeout.

Reducing defaultCommandTimeout from 15s to 5s could cause intermittent failures if network requests, UI rendering, or app interactions occasionally exceed 5 seconds. While this aligns with the "decrease delays" objective and you've validated the tests, monitor for flaky failures in CI, especially under varying network conditions or system load.


34-34: LGTM! Page load timeout is appropriate.

Setting pageLoadTimeout to 15,000 ms is reasonable for E2E tests and aligns with the PR objective to fix page loading detection. This gives adequate time for the application to fully load before Cypress begins test execution.


21-23: Root path is correct and resolves to the monorepo root.

The root: '../../' correctly resolves to the repository root where tsconfig.base.json is located.


3-5: All three plugins are at stable versions (1.0.6, 0.24.0, and 5.1.4 respectively) with no known direct security vulnerabilities.

@crutch12 crutch12 force-pushed the chore/restore-e2e-tests branch from ea2600e to 178be39 Compare December 23, 2025 19:36
@crutch12 crutch12 force-pushed the chore/restore-e2e-tests branch from 178be39 to 28c2122 Compare December 23, 2025 19:39
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/cowswap-frontend-e2e/src/support/e2e.ts (1)

77-78: Regex patterns still have unescaped dot before json.

The .* fix was applied, but the dot in .json remains unescaped, so it matches any character (e.g., tokensXjson). This was flagged in a previous review.

🔎 Proposed fix
-  /files.cow.fi\/token-lists\/.*.json/,
-  /files.cow.fi\/tokens\/.*.json/,
+  /files.cow.fi\/token-lists\/.*\.json/,
+  /files.cow.fi\/tokens\/.*\.json/,
🧹 Nitpick comments (3)
apps/cowswap-frontend-e2e/src/support/e2e.ts (3)

27-29: Type serviceWorker?: true only allows literal true.

This type annotation is unusual—it restricts the property to only accept the literal value true, not false. If the intent is to allow enabling/disabling, use boolean. If the intent is "when present, service worker is enabled", consider serviceWorker?: boolean or document the design choice.

🔎 Suggested fix
     interface VisitOptions {
-      serviceWorker?: true
+      serviceWorker?: boolean
     }

88-91: Non-null assertion on baseUrl could cause silent failures.

If baseUrl is not configured in Cypress config, this assertion will produce undefined as the origin header, which may cause Infura requests to fail mysteriously.

🔎 Suggested defensive approach
   cy.intercept(/infura.io/, (req) => {
-    req.headers['origin'] = Cypress.config('baseUrl')!
+    const baseUrl = Cypress.config('baseUrl')
+    if (baseUrl) {
+      req.headers['origin'] = baseUrl
+    }
     req.continue()
   })

116-119: Duplicate initialization with visit command overwrite.

Lines 43-44 in the visit overwrite already clear localStorage and inject ethereum. This beforeEach handler does the same, resulting in double initialization when cy.visit() is called. While harmless, consider removing one to avoid confusion.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea2600e and 178be39.

📒 Files selected for processing (3)
  • apps/cowswap-frontend-e2e/cypress.config.ts
  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
  • apps/cowswap-frontend-e2e/src/support/e2e.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cowswap-frontend-e2e/cypress.config.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.
📚 Learning: 2025-07-28T16:26:08.051Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-08-08T13:55:17.528Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6125
File: libs/tokens/src/state/tokens/allTokensAtom.ts:78-78
Timestamp: 2025-08-08T13:55:17.528Z
Learning: In libs/tokens/src/state/tokens/allTokensAtom.ts (TypeScript/Jotai), the team prefers to wait for token lists to initialize (listsStatesListAtom non-empty) before returning tokens. No fallback to favorites/user-added/native tokens should be used when listsStatesList is empty.

Applied to files:

  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
📚 Learning: 2025-09-25T08:48:53.495Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-05-28T16:50:12.273Z
Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 5768
File: apps/cow-fi/components/LearnPageComponent.tsx:184-185
Timestamp: 2025-05-28T16:50:12.273Z
Learning: In apps/cow-fi/components/LearnPageComponent.tsx, the user prefers to keep the inconsistent link behavior where featured articles always open in new tabs (target="_blank") while media coverage links conditionally open in new tabs based on the linkExternal flag. This inconsistency should not be flagged as an issue in future reviews.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-09-11T08:25:51.460Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 6234
File: libs/tokens/src/index.ts:1-4
Timestamp: 2025-09-11T08:25:51.460Z
Learning: In the cowprotocol/cowswap project, there is currently no SSR (Server-Side Rendering) support, so localStorage access at module import time does not cause SSR-related issues.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-09-25T08:49:32.256Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
🧬 Code graph analysis (1)
apps/cowswap-frontend-e2e/src/support/e2e.ts (1)
apps/cowswap-frontend-e2e/src/support/ethereum.ts (1)
  • injected (124-124)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Cypress
  • GitHub Check: Setup
🔇 Additional comments (4)
apps/cowswap-frontend-e2e/src/e2e/token.test.ts (2)

3-6: Good approach to skip slow external service calls.

Intercepting and returning 404 for the Safe tx-service speeds up test execution without affecting the token search functionality being tested.


14-30: Tests re-enabled with appropriate per-test page visits.

The pattern of visiting the page within each it block ensures test isolation. Based on learnings, the placeholder test at lines 9-12 is intentionally kept to maintain CI stability.

Consider adding explicit waits if these tests become flaky—cy.get has default retries, but token list loading may need additional guards if the backend is slow.

apps/cowswap-frontend-e2e/src/support/e2e.ts (2)

50-56: Hacky but acceptable for test environment.

Deleting from __proto__ to disable service workers is unconventional but reasonable for an e2e test harness where Safari SDK compatibility is needed. The @ts-expect-error is appropriate here.


99-114: Module-level cache persists across spec files.

cypressCache is defined at module scope, so cached responses persist across test files within the same Cypress run. This is likely intentional for performance, but be aware that stale data could affect tests if the underlying API changes mid-run.

The headers: undefined workaround for req.reply compatibility is fragile—consider adding a brief comment explaining why headers must be stripped.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
apps/cowswap-frontend-e2e/src/support/e2e.ts (3)

27-28: Minor type issue: serviceWorker?: true seems unused.

This type declaration appears unused in the visit command override. If this is meant to be a toggle to conditionally enable/disable service worker suppression, consider using boolean type. Otherwise, if unused, it could be removed to reduce confusion.


77-78: Follow-up: Escape the literal dot before json in regex patterns.

The previous review flagged the /* issue which was fixed, but the dot before json is still unescaped. In regex, . matches any character, so foo.json and fooXjson would both match. While unlikely to cause issues in practice, escaping the dot makes the intent clearer.

🔎 Proposed fix
-  /files.cow.fi\/token-lists\/.*.json/,
-  /files.cow.fi\/tokens\/.*.json/,
+  /files.cow.fi\/token-lists\/.*\.json/,
+  /files.cow.fi\/tokens\/.*\.json/,

88-91: Consider a fallback for baseUrl to avoid silent failures.

If baseUrl is ever undefined (misconfigured test run), the origin header would be set to the string "undefined", which could cause confusing auth failures with Infura. A fallback or explicit error would make debugging easier.

🔎 Proposed fix
   cy.intercept(/infura.io/, (req) => {
-    req.headers['origin'] = Cypress.config('baseUrl')!
+    const baseUrl = Cypress.config('baseUrl')
+    if (!baseUrl) throw new Error('Cypress baseUrl must be configured for E2E tests')
+    req.headers['origin'] = baseUrl
     req.continue()
   })
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 178be39 and 28c2122.

📒 Files selected for processing (3)
  • apps/cowswap-frontend-e2e/cypress.config.ts
  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
  • apps/cowswap-frontend-e2e/src/support/e2e.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cowswap-frontend-e2e/src/e2e/token.test.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.
📚 Learning: 2025-09-25T08:48:53.495Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-07-28T16:26:08.051Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-05-28T16:50:12.273Z
Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 5768
File: apps/cow-fi/components/LearnPageComponent.tsx:184-185
Timestamp: 2025-05-28T16:50:12.273Z
Learning: In apps/cow-fi/components/LearnPageComponent.tsx, the user prefers to keep the inconsistent link behavior where featured articles always open in new tabs (target="_blank") while media coverage links conditionally open in new tabs based on the linkExternal flag. This inconsistency should not be flagged as an issue in future reviews.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-09-11T08:25:51.460Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 6234
File: libs/tokens/src/index.ts:1-4
Timestamp: 2025-09-11T08:25:51.460Z
Learning: In the cowprotocol/cowswap project, there is currently no SSR (Server-Side Rendering) support, so localStorage access at module import time does not cause SSR-related issues.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-09-25T08:49:32.256Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.

Applied to files:

  • apps/cowswap-frontend-e2e/src/support/e2e.ts
📚 Learning: 2025-12-03T19:23:35.789Z
Learnt from: kernelwhisperer
Repo: cowprotocol/cowswap PR: 6610
File: apps/cowswap-frontend/project.json:38-39
Timestamp: 2025-12-03T19:23:35.789Z
Learning: In the cowswap-frontend project configuration (apps/cowswap-frontend/project.json), the Vite dev server option `"host": true` is set to support Windows + WSL development environments, where binding to all network interfaces is required for the Windows host to access the dev server running in WSL.

Applied to files:

  • apps/cowswap-frontend-e2e/cypress.config.ts
🧬 Code graph analysis (1)
apps/cowswap-frontend-e2e/src/support/e2e.ts (1)
apps/cowswap-frontend-e2e/src/support/ethereum.ts (1)
  • injected (124-124)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Setup
  • GitHub Check: Cypress
🔇 Additional comments (8)
apps/cowswap-frontend-e2e/cypress.config.ts (4)

11-20: LGTM! Node polyfills configured appropriately for E2E tests.

The nodePolyfills configuration with Buffer, global, and process globals is appropriate for E2E tests that interact with blockchain/Web3 libraries. The protocolImports: true setting enables Node.js protocol imports which is helpful for better compatibility.


21-25: LGTM! Path resolution and macros plugin configured correctly.

The viteTsConfigPaths with root: '../../' correctly points to the monorepo root for resolving TypeScript path aliases. The macrosPlugin() enables Babel macro support which is useful for libraries like styled-components or twin.macro.


33-34: Monitor for flakiness after reducing command timeout.

Reducing defaultCommandTimeout from 15s to 5s (67% reduction) significantly speeds up tests but may cause flakiness if any commands occasionally exceed 5s, especially in slower CI environments or under load. The new pageLoadTimeout of 15s is reasonable.

Consider monitoring test stability closely after this change, particularly in CI. If flakiness emerges, you may need to selectively increase timeout for specific commands using cy.command({ timeout: 10000 }) rather than reverting the global setting.


3-5: The Vite plugin packages vite-plugin-babel-macros (^1.0.6), vite-plugin-node-polyfills (^0.24.0), and vite-tsconfig-paths (~5.1.4) are all installed in the project's devDependencies and properly imported. No action required.

apps/cowswap-frontend-e2e/src/support/e2e.ts (4)

33-48: LGTM!

The visit command override cleanly injects the ethereum provider and clears localStorage. Properly chains with user-provided onBeforeLoad callbacks.


50-56: LGTM!

The prototype chain manipulation is an effective technique for disabling service workers in the test environment. The @ts-expect-error appropriately handles the non-standard delete operation.


116-119: Potentially redundant with visit command's onBeforeLoad.

This handler duplicates the localStorage clearing and ethereum injection that already happens in the overwritten visit command (lines 41-44). The cy.on('window:before:load') fires for all window loads including iframes, while the visit's onBeforeLoad is scoped to the navigated page.

If both are needed for specific scenarios (e.g., SPA navigation that doesn't trigger visit), consider adding a comment explaining why. Otherwise, this duplication may cause confusion or unnecessary double-initialization.


99-114: LGTM - reasonable caching strategy for static resources.

The module-scoped cache improves test performance by avoiding repeated fetches of token lists and CMS data. Stripping headers is a known workaround for Cypress intercept limitations. The trade-off against strict test isolation is acceptable for these truly static resources.

import type { BytesLike } from '@ethersproject/bytes'
import type { JsonRpcProvider } from '@ethersproject/providers'

// @cowprotocol/multicall takes long time to bundle, so import getMulticallContract directly
Copy link
Contributor

Choose a reason for hiding this comment

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

@cowprotocol/multicall takes long time to bundle

Can you expand a little bit on this?

Copy link
Contributor Author

@crutch12 crutch12 Dec 30, 2025

Choose a reason for hiding this comment

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

Sure. @cowprotocol/multicall exports barrel file that imports another @cowprotocol/** libs, therefore we have to build every imported lib and it takes much more time.

So I avoid it by importing only needed files/methods

Copy link
Contributor

@kernelwhisperer kernelwhisperer left a comment

Choose a reason for hiding this comment

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

Amazing, thank you very much for this!

They are still a bit flaky on my machine (it might be the free infura key I'm using), but let's see how they behave in CI.

@vercel
Copy link

vercel bot commented Dec 31, 2025

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

Project Deployment Review Updated (UTC)
swap-dev Ready Ready Preview Dec 31, 2025 4:47am

>
> - `INTEGRATION_TEST_PRIVATE_KEY=<your-private-key>`: Private key
> - `INTEGRATION_TESTS_INFURA_KEY=<your-infura-key>`: Infura key
> - `CYPRESS_INTEGRATION_TEST_PRIVATE_KEY=<your-private-key>`: Private key
Copy link
Collaborator

Choose a reason for hiding this comment

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

@crutch12 thank you! Tests are not working due to this change, I believe.
Is there a reason to rename INTEGRATION_TESTS_INFURA_KEY to CYPRESS_INTEGRATION_TEST_PRIVATE_KEY?

image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi! It's strange, I didn't change config files, only readme 🤔

Why it should work: Cypress takes every CYPRESS_** variable, removes prefix and provides value to tests
https://docs.cypress.io/app/references/environment-variables#Option-3-CYPRESS_

That's why (?) it has prefix in ci.yml

CYPRESS_INTEGRATION_TEST_PRIVATE_KEY: ${{ secrets.CYPRESS_INTEGRATION_TEST_PRIVATE_KEY }}

And it works locally... I will check ci later

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi

Another PRs' CI step fails with the same reason, so it's not about my change. (e.g. https://github.com/cowprotocol/cowswap/actions/runs/20579882617/job/59104917257?pr=6775)

Are you sure that secrets.CYPRESS_INTEGRATION_TEST_PRIVATE_KEY is set in the workflow settings?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants