Skip to content

test(e2e): cross-chain swaps - #7990

Draft
shoom3301 wants to merge 44 commits into
e2e/market-ordersfrom
e2e/cross-chain-swaps
Draft

test(e2e): cross-chain swaps#7990
shoom3301 wants to merge 44 commits into
e2e/market-ordersfrom
e2e/cross-chain-swaps

Conversation

@shoom3301

@shoom3301 shoom3301 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

What changed

  • Adds cross-chain-swaps.spec.ts, 8 new Playwright specs covering the cross-chain swap UI: provider selection (Bungee/Near Intents), ETH-flow (native ETH) as the sell leg, Solana/Bitcoin as destination chains, and swap/bridge "Expected to receive" / "Min. to receive" parity (CC-01, CC-02, CC-03, CC-13, CC-15, CC-17, CC-26, CC-27).
  • Adds host-mocked fixtures for both bridge providers (mocks/bungee.ts, mocks/nearIntents.ts, plus captured quote/route JSON fixtures) and a BridgeRoutePanel page object for the swap/bridge route breakdown.
  • Adds mockSocketVerifier.ts to stub Bungee's on-chain validateRotueId/validateSocketRequest preflight calls so its quote path doesn't need a real chain.
  • Two small e2e-only hooks in app code, both gated behind a window flag only Playwright sets:
    • bridgingSdk.ts: bypasses Near Intents' recoverDepositAddress signature check behind window.__COWSWAP_E2E__, since a mocked quote/attestation pair can't carry a real signature from Near's attestor key.
    • useFeatureFlags.ts: reads window.__COWSWAP_E2E_FEATURE_FLAGS__ and merges it over LaunchDarkly's flags, since LD's SDK never issues an evaluation request without a configured client-side ID and its API can't be mocked over HTTP instead.
  • CI: adds REACT_APP_NETWORK_URL_1 (mainnet RPC) to e2e-pw-nightly.yml / e2e-pw-smoke.yml and .env.example, since these specs run against Mainnet→Base rather than Sepolia.
  • Documents all of the above — LaunchDarkly workaround, fixture constraints, provider-competition gating — in a new "Cross-chain bridging" section of apps/cowswap-e2e-tests/AGENTS.md.

Why

Cross-chain swap/bridge is a live user-facing flow with no prior Playwright coverage. Two real constraints shaped the approach rather than a straightforward mock:

  • Near Intents' quote is cryptographically signed by Near's attestor key over the exact quote+timestamp payload, so a captured fixture can only ever replay the one route it was signed for — it can't be edited to match arbitrary chain/token pairs, and the signature check has to be bypassed for e2e rather than forged.
  • LaunchDarkly's SDK doesn't make an evaluation request at all without a real client-side ID, so there's no HTTP call to intercept — flags are injected via window instead.

Given those, CC-02/CC-03/CC-26/CC-27 exercise Mainnet USDC → Base USDC (the one route with a valid signed Near fixture) rather than every pairing named in the original spec, and CC-15/CC-17 stop at the recipient-requirement UI states rather than asserting on a real resolved Solana/Bitcoin quote (no valid fixture exists for either). Full scope notes are in the spec file's module doc comment and in AGENTS.md.

QA Testing

Preview URL QA:

  • Cross-chain swap form: https://swap-dev-git-e2e-cross-chain-swaps-cowswap-dev.vercel.app/#/1/swap — pick a destination chain (e.g. Base) and confirm the bridge route panel shows a swap stop and a bridge stop with provider name, fee, and "Expected/Min. to receive" rows.
  • Solana/Bitcoin destination: same URL, select Solana or Bitcoin as the output chain and confirm the recipient-address flow (required-recipient button → address input → confirmation checkbox → enabled trade button).

Developer verification:

  • The 8 specs in cross-chain-swaps.spec.ts are the actual regression coverage here; they aren't independently reproducible through the preview alone since they rely on mocked Bungee/Near Intents responses and a mocked wallet private key.
  • mockSocketVerifier/bungee.ts/nearIntents.ts fixture wiring is exercised by those same specs.

Reviewer note:

  • The two app-code changes (bridgingSdk.ts, useFeatureFlags.ts) both branch only on window flags (__COWSWAP_E2E__, __COWSWAP_E2E_FEATURE_FLAGS__) that only Playwright's addInitScript sets — worth confirming neither path is reachable in a real browser session.

Preview URLs

Surface URL
swap-dev - branch preview URL https://swap-dev-git-e2e-cross-chain-swaps-cowswap-dev.vercel.app
explorer-dev - branch preview URL https://explorer-dev-git-e2e-cross-chain-swaps-cowswap-dev.vercel.app
storybook - branch preview URL https://storybook-git-e2e-cross-chain-swaps-cowswap-dev.vercel.app
widget-configurator - branch preview URL https://widget-configurator-git-e2e-cross-chain-swaps-cowswap-dev.vercel.app
cowfi - branch preview URL https://cowfi-git-e2e-cross-chain-swaps-cowswap.vercel.app

Summary by CodeRabbit

  • New Features
    • Added end-to-end coverage for cross-chain swaps, including Bungee and NEAR Intents routes.
    • Added validation for route details, fees, recipients, quote calculations, confirmations, and bridging progress.
    • Added support for testing Solana and Bitcoin recipients and native ETH flows.
  • Testing
    • Added realistic bridge responses, network configuration, and feature-flag controls for reliable automated testing.
    • Added coverage for provider selection, route availability, and cross-chain transaction behavior.

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
cowfi Ready Ready Preview Aug 13, 2026 10:57pm
explorer-dev Ready Ready Preview Aug 13, 2026 10:57pm
storybook Ready Ready Preview Aug 13, 2026 10:57pm
swap-dev Ready Ready Preview Aug 13, 2026 10:57pm
widget-configurator Ready Ready Preview Aug 13, 2026 10:57pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
cosmos Ignored Ignored Aug 13, 2026 10:57pm
sdk-tools Ignored Ignored Preview Aug 13, 2026 10:57pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

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

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 98d7d221-2d6d-4606-b096-4d8b4369810e

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The PR adds cross-chain Playwright coverage for NEAR Intents and Bungee. It adds bridge fixtures and mocks, SocketVerifier interception, route-panel assertions, E2E feature-flag controls, and workflow RPC configuration.

Changes

Cross-chain E2E coverage

Layer / File(s) Summary
E2E runtime controls
.github/workflows/*, apps/cowswap-e2e-tests/.env.example, apps/cowswap-frontend/src/tradingSdk/bridgingSdk.ts, libs/common-hooks/src/useFeatureFlags.ts
Workflows expose the Ethereum RPC secret. Browser E2E tests can override feature flags and NEAR attestation recovery.
Bridge provider fixtures and mocks
apps/cowswap-e2e-tests/src/mocks/bridge/fixtures/*, apps/cowswap-e2e-tests/src/mocks/bungee.ts, apps/cowswap-e2e-tests/src/mocks/nearIntents.ts
Fixture-backed Bungee and NEAR Intents handlers serve token, quote, transaction, attestation, and status responses. Bungee quotes scale to the requested input.
Verification interception and fixture wiring
apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts, apps/cowswap-e2e-tests/src/fixtures/shared.ts
Shared fixtures install the provider mocks. SocketVerifier interception handles direct calls and nested Multicall3.aggregate3 batches.
Route inspection and cross-chain scenarios
apps/cowswap-e2e-tests/src/pages/BridgeRoutePanel.ts, apps/cowswap-e2e-tests/src/pages/SwapPage.ts, apps/cowswap-e2e-tests/src/tests/cross-chain-swaps.spec.ts, apps/cowswap-e2e-tests/AGENTS.md
The page objects expose route details. Tests cover provider routes, native ETH-flow swaps, Solana and Bitcoin recipients, calculation parity, order confirmation, and bridging progress. The test guidance documents the required setup.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CrossChainSwapTests
  participant SwapPage
  participant BungeeMock
  participant NearIntentsMock
  participant mockSocketVerifier
  CrossChainSwapTests->>SwapPage: configure provider and start swap
  SwapPage->>BungeeMock: request quote and bridge data
  SwapPage->>NearIntentsMock: request tokens and quote
  SwapPage->>mockSocketVerifier: verify SocketVerifier calls
  mockSocketVerifier-->>SwapPage: return mocked or patched RPC results
  BungeeMock-->>SwapPage: return scaled quote and transaction data
  NearIntentsMock-->>SwapPage: return fixture-backed quote and status
Loading

Poem

I’m a rabbit with routes in a row,
Through Bungee and NEAR, the test flows go.
Quotes scale neatly, mocks answer bright,
ETH hops onward through the night.
The bridge panel shows each stop just right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: adding end-to-end coverage for cross-chain swaps.
Description check ✅ Passed The description provides a detailed summary, testing guidance, background, constraints, and preview URLs, but omits the template's formal self-checks section.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch e2e/cross-chain-swaps

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.

…wswap into e2e/cross-chain-swaps

# Conflicts:
#	apps/cowswap-e2e-tests/src/pages/SwapPage.ts
…wswap into e2e/cross-chain-swaps

# Conflicts:
#	apps/cowswap-e2e-tests/src/fixtures/shared.ts
#	apps/cowswap-e2e-tests/src/mocks/bungee.ts
#	apps/cowswap-e2e-tests/src/mocks/nearIntents.ts
@shoom3301 shoom3301 changed the title E2e/cross chain swaps test(e2e): cross-chain swaps Aug 12, 2026

@shoom3301 shoom3301 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

AI Review (Claude Sonnet 5, worked ~45m): security hardening finding, addressed in latest commit

Finding: [NON-BLOCKING] bridgingSdk.ts's e2e signature bypass shipped as live code in every deployed bundle — now fixed

  • Lifecycle: fixed-by-current-pr (was out-of-scope-hardening / P3 at review time)
  • Location: apps/cowswap-frontend/src/tradingSdk/bridgingSdk.ts:44
  • The e2e-only recoverDepositAddress stub (bypasses Near Intents' real ECDSA attestation check) was gated only by the runtime global window.__COWSWAP_E2E__. That flag is only ever set by the Playwright fixture (apps/cowswap-e2e-tests/src/fixtures/shared.ts), so it isn't remotely triggerable — but the branch still shipped as live, unstripped code in every production/staging/preview bundle, keyed on a client-side value with no build-time gate.
  • Fixed in a45006bd2: the condition is now process.env.NODE_ENV !== 'production' && typeof window !== 'undefined' && window.__COWSWAP_E2E__. Every deployed build (prod, staging, Vercel preview) runs the production webpack build (NODE_ENV === 'production'), so Terser now dead-code-eliminates the whole branch — the bypass has no live path in any shipped bundle. Verified: tsc/eslint clean, and CC-01/02/26/27 (the Near-Intents-dependent cross-chain specs) still pass against a freshly started dev server (NODE_ENV === 'development') with the fix in place.
Review scope and related context
  • Ran a targeted security-review pass on this finding specifically (triggered by the diff touching bridge-recipient signature verification). Attempted DeepSec PR-mode via the fast-path helper scoped to this PR's 19 changed files; it resolved dependencies but failed at the AI-agent step (Missing AI credentials for --agent codex, exit 1, no artifact) — blocked on missing AI_GATEWAY_API_KEY/OPENAI_API_KEY in this environment. The verdict below rests on code inspection (traced the real recoverDepositAddress check in @cowprotocol/sdk-bridging's compiled output) plus a targeted Playwright re-run, not DeepSec.
  • Confirmed via repo-wide grep that window.__COWSWAP_E2E__'s only writer is the Playwright fixture; no URL param, extension hook, or other production code path sets it.
  • Noted for context, not filed separately: libs/common-hooks/src/useFeatureFlags.ts uses the same window.__COWSWAP_E2E_FEATURE_FLAGS__ pattern without the NODE_ENV guard. Lower stakes (overrides feature-flag values, not a cryptographic check) so I didn't block on it, but applying the same guard there would be a small, free consistency win if the author wants it in this PR.
  • No other blocking findings surfaced from the CoW institutional-memory scan (wallet storage, Safe, permit, widget/CSP, balances-watcher) — this PR's diff doesn't touch any of those surfaces.
🤖 Prompt for AI agents
This finding is already fixed on the current PR head (commit a45006bd2). No action needed unless
extending the same NODE_ENV production-build guard to libs/common-hooks/src/useFeatureFlags.ts's
window.__COWSWAP_E2E_FEATURE_FLAGS__ check, which currently lacks it (lower severity: overrides
feature-flag values, not a signature check).

Generated using the pr-review skill from the CoW Protocol skills repo.

@shoom3301
shoom3301 marked this pull request as ready for review August 12, 2026 14:55
@shoom3301 shoom3301 self-assigned this Aug 12, 2026
@shoom3301 shoom3301 added the e2e label Aug 12, 2026
@shoom3301

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (8)
apps/cowswap-frontend/src/tradingSdk/bridgingSdk.ts (2)

44-49: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Fix the garbled sentence in the comment.

Line 48 merges two clauses: "Only the local/CI dev server e2e tests actually run against (NODE_ENV === 'development') ever evaluates it". The sentence is unreadable.

📝 Proposed wording
-// there and gets stripped by Terser. Only the local/CI dev server e2e tests actually run against
-// (`NODE_ENV === 'development'`) ever evaluates it, so a real deployed bundle has no live code path
+// there and gets stripped by Terser. Only the local/CI dev server that e2e tests run against
+// (`NODE_ENV === 'development'`) evaluates it, so a real deployed bundle has no live code path
 // that can disable this signature check, no matter what `window.__COWSWAP_E2E__` is set to.
🤖 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-frontend/src/tradingSdk/bridgingSdk.ts` around lines 44 - 49,
Rewrite the garbled sentence in the comment near the NODE_ENV check for clear
grammar, preserving the meaning that only local or CI development-server E2E
tests run with NODE_ENV === 'development' and evaluate this branch.

35-37: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The duplicated attestor address can drift from the SDK value.

NEAR_INTENTS_E2E_ATTESTATOR_ADDRESS copies a non-exported SDK constant. If the SDK rotates the attestor address, this copy stays stale and the bypass returns a wrong address without any failure signal. Consider asserting the value in an e2e test, or deriving it from the SDK if any export path exists.

🤖 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-frontend/src/tradingSdk/bridgingSdk.ts` around lines 35 - 37,
The duplicated NEAR Intents attestor address in
NEAR_INTENTS_E2E_ATTESTATOR_ADDRESS can become stale when the SDK value changes.
Derive this address from an available `@cowprotocol/sdk-bridging` export if
possible; otherwise add an e2e assertion that verifies
NEAR_INTENTS_E2E_ATTESTATOR_ADDRESS matches the SDK’s ATTESTATOR_ADDRESS.
libs/common-hooks/src/useFeatureFlags.ts (1)

22-28: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

The override branch returns a new object on every render.

When __COWSWAP_E2E_FEATURE_FLAGS__ is set, each render produces a fresh object. Consumers that put the result in a dependency array or a memo comparison then re-run on every render. This only affects e2e runs, but it can change timing-sensitive behavior that the tests assert on. Wrapping the merge in useMemo keyed on flags keeps the identity stable.

🤖 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 `@libs/common-hooks/src/useFeatureFlags.ts` around lines 22 - 28, Update the
override branch in useFeatureFlags to memoize the merged feature flags with
useMemo, using flags as the dependency so the result remains stable across
renders when the e2e override is unchanged.
apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts (1)

8-11: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Confirm the stubbed selectors match the current SDK functions.

The selectors 0xeee54b0d and 0xf75d4a35 are hardcoded, and the comment notes a typo in the real signature (validateRotueId). If the SDK changes either signature, the stub silently stops matching and Bungee tests fail against a real RPC with RouteIdNotFound(). Deriving the selectors with viem's toFunctionSelector from the signature strings makes the mismatch visible in the source.

🤖 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/mockSocketVerifier.ts` around lines 8 -
11, Update STUBBED_SELECTORS to derive both values with viem’s
toFunctionSelector from the exact current SDK signatures, including the
validateRotueId spelling, instead of hardcoding hexadecimal selectors. Keep the
existing selector-matching behavior unchanged while making signature changes
visible in the source.
apps/cowswap-e2e-tests/src/pages/BridgeRoutePanel.ts (1)

52-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Consider a data-testid instead of matching styled-components class hashes.

detailContent walks to an ancestor whose class contains __Label-. That string comes from babel-plugin-styled-components's displayName output. If the build disables displayName (common in production-mode builds) or the plugin changes its naming, every row locator here breaks at once with no clear signal. Adding data-testid to ConfirmDetailsItem's Label/Content would remove the coupling to build tooling.

🤖 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/BridgeRoutePanel.ts` around lines 52 - 64,
Replace the styled-components class selector in BridgeRoutePanel.detailContent
with stable data-testid attributes added to ConfirmDetailsItem’s Label and
Content elements. Locate each matching label by its test ID, then select the
corresponding content element while preserving exact text matching and
occurrence handling; update amountValue only as needed to use the revised
detailContent flow.
apps/cowswap-e2e-tests/src/mocks/bungee.ts (2)

50-50: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Both bridge mock installers discard the context.route() promise. context.route() returns a Promise<void>. Each installer applies the void operator to it, so a registration rejection is swallowed and the handler is not guaranteed to be installed before the page starts loading.

  • apps/cowswap-e2e-tests/src/mocks/bungee.ts#L50-L50: make installBungee return Promise<BungeeMock> and await context.route(...).
  • apps/cowswap-e2e-tests/src/mocks/nearIntents.ts#L31-L31: make installNearIntents return Promise<NearIntentsMock> and await context.route(...).

If you change both signatures, also await the two calls in apps/cowswap-e2e-tests/src/fixtures/shared.ts at Lines 130-131. Confirm the convention used by the existing mock installers first, so the new mocks stay consistent with the suite.

🤖 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/bungee.ts` at line 50, Update installBungee
in apps/cowswap-e2e-tests/src/mocks/bungee.ts at line 50 to return
Promise<BungeeMock> and await context.route(...). Update installNearIntents in
apps/cowswap-e2e-tests/src/mocks/nearIntents.ts at line 31 to return
Promise<NearIntentsMock> and await context.route(...). Then await both installer
calls in apps/cowswap-e2e-tests/src/fixtures/shared.ts at lines 130-131,
following the existing mock-installer convention.

138-182: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

toUsd loses precision for tokens with 18 decimals.

Number(amount) is used on a raw base-unit string. For the committed USDC fixture (6 decimals) the value stays well inside the safe integer range, so the current behavior is correct. If a future fixture uses an 18-decimal token, a scaled base-unit amount exceeds Number.MAX_SAFE_INTEGER and the derived USD values silently drift.

The valueInUsd fields only feed display and price-impact math in the mock, so this is not a current defect. Consider a short comment recording the 6-decimal assumption, so a later 18-decimal fixture does not hit a silent rounding trap.

🤖 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/bungee.ts` around lines 138 - 182, Add a
concise comment adjacent to toUsd documenting that its Number-based conversion
assumes fixture token amounts, such as the committed USDC data, remain within
safe integer precision (6 decimals), and that 18-decimal amounts may lose
precision. Do not change the current conversion behavior.
apps/cowswap-e2e-tests/src/mocks/nearIntents.ts (1)

6-10: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

FIXTURES_DIR and loadFixture duplicate bungee.ts.

Both constants and the helper are byte-identical to apps/cowswap-e2e-tests/src/mocks/bungee.ts Lines 6-10. Extract them into one shared module, for example src/mocks/bridge/loadFixture.ts, and import it in both mocks.

As per coding guidelines: "Code MUST prefer existing shared utilities and hooks over creating near-duplicates."

♻️ Proposed shared helper

Add apps/cowswap-e2e-tests/src/mocks/bridge/loadFixture.ts:

import { readFileSync } from 'node:fs'
import path from 'node:path'

const FIXTURES_DIR = path.join(__dirname, 'fixtures')

export function loadFixture(name: string): unknown {
  return JSON.parse(readFileSync(path.join(FIXTURES_DIR, name), 'utf8')) as unknown
}

Then in nearIntents.ts:

-import { readFileSync } from 'node:fs'
-import path from 'node:path'
-
 import type { BrowserContext, Route } from '`@playwright/test`'
 
-const FIXTURES_DIR = path.join(__dirname, 'bridge', 'fixtures')
-
-function loadFixture(name: string): unknown {
-  return JSON.parse(readFileSync(path.join(FIXTURES_DIR, name), 'utf8')) as unknown
-}
+import { loadFixture } from './bridge/loadFixture'
🤖 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/nearIntents.ts` around lines 6 - 10, Extract
the duplicated FIXTURES_DIR and loadFixture logic from nearIntents.ts and
bungee.ts into a shared bridge/loadFixture module, preserving the existing
fixture path and JSON parsing behavior. Export loadFixture from the shared
module and update both mocks to import and reuse it, removing their local
constants, helper definitions, and now-unused imports.

Source: Coding guidelines

🤖 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/pages/BridgeRoutePanel.ts`:
- Line 22: Update the expandToggle initialization in BridgeRoutePanel to target
the trade-details accordion specifically, using its container selector or a
stable TradeDetailsAccordion hook instead of the page-wide [aria-expanded]
locator; preserve selecting the accordion’s expand control.

In `@apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts`:
- Around line 121-125: Replace address string comparisons with areAddressesEqual
from `@cowprotocol/cow-sdk`: in
apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts lines 121-125, update
the comparison in the STUBBED_SELECTORS branch; in
apps/cowswap-e2e-tests/src/tests/cross-chain-swaps.spec.ts lines 188-191, update
the recipient assertion to expect areAddressesEqual(swapRecipientAddress,
wallet.address) to be false. Add or reuse the required import in both files.
- Around line 71-74: The SocketVerifier route must be installed before
navigation proceeds. In apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts
lines 71-74, update mockSocketVerifier to return Promise<void> and await
context.route(...); in
apps/cowswap-e2e-tests/src/tests/cross-chain-swaps.spec.ts lines 74-85, await
the mockSocketVerifier(context) call.

In `@apps/cowswap-e2e-tests/src/tests/cross-chain-swaps.spec.ts`:
- Around line 545-547: Update the parity assertions in the cross-chain swap test
to read the form value once, then compare the route-panel value using a retrying
matcher rather than a second one-time getAttribute snapshot. Apply the same
pattern to the bridgeMinToDeposit/swapMinToReceive assertion, preserving the
existing expected-value relationships.

---

Nitpick comments:
In `@apps/cowswap-e2e-tests/src/mocks/bungee.ts`:
- Line 50: Update installBungee in apps/cowswap-e2e-tests/src/mocks/bungee.ts at
line 50 to return Promise<BungeeMock> and await context.route(...). Update
installNearIntents in apps/cowswap-e2e-tests/src/mocks/nearIntents.ts at line 31
to return Promise<NearIntentsMock> and await context.route(...). Then await both
installer calls in apps/cowswap-e2e-tests/src/fixtures/shared.ts at lines
130-131, following the existing mock-installer convention.
- Around line 138-182: Add a concise comment adjacent to toUsd documenting that
its Number-based conversion assumes fixture token amounts, such as the committed
USDC data, remain within safe integer precision (6 decimals), and that
18-decimal amounts may lose precision. Do not change the current conversion
behavior.

In `@apps/cowswap-e2e-tests/src/mocks/nearIntents.ts`:
- Around line 6-10: Extract the duplicated FIXTURES_DIR and loadFixture logic
from nearIntents.ts and bungee.ts into a shared bridge/loadFixture module,
preserving the existing fixture path and JSON parsing behavior. Export
loadFixture from the shared module and update both mocks to import and reuse it,
removing their local constants, helper definitions, and now-unused imports.

In `@apps/cowswap-e2e-tests/src/pages/BridgeRoutePanel.ts`:
- Around line 52-64: Replace the styled-components class selector in
BridgeRoutePanel.detailContent with stable data-testid attributes added to
ConfirmDetailsItem’s Label and Content elements. Locate each matching label by
its test ID, then select the corresponding content element while preserving
exact text matching and occurrence handling; update amountValue only as needed
to use the revised detailContent flow.

In `@apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts`:
- Around line 8-11: Update STUBBED_SELECTORS to derive both values with viem’s
toFunctionSelector from the exact current SDK signatures, including the
validateRotueId spelling, instead of hardcoding hexadecimal selectors. Keep the
existing selector-matching behavior unchanged while making signature changes
visible in the source.

In `@apps/cowswap-frontend/src/tradingSdk/bridgingSdk.ts`:
- Around line 44-49: Rewrite the garbled sentence in the comment near the
NODE_ENV check for clear grammar, preserving the meaning that only local or CI
development-server E2E tests run with NODE_ENV === 'development' and evaluate
this branch.
- Around line 35-37: The duplicated NEAR Intents attestor address in
NEAR_INTENTS_E2E_ATTESTATOR_ADDRESS can become stale when the SDK value changes.
Derive this address from an available `@cowprotocol/sdk-bridging` export if
possible; otherwise add an e2e assertion that verifies
NEAR_INTENTS_E2E_ATTESTATOR_ADDRESS matches the SDK’s ATTESTATOR_ADDRESS.

In `@libs/common-hooks/src/useFeatureFlags.ts`:
- Around line 22-28: Update the override branch in useFeatureFlags to memoize
the merged feature flags with useMemo, using flags as the dependency so the
result remains stable across renders when the e2e override is unchanged.
🪄 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: 67662252-c96a-4e15-ae65-c1988ffea65c

📥 Commits

Reviewing files that changed from the base of the PR and between c623450 and a45006b.

📒 Files selected for processing (19)
  • .github/workflows/e2e-pw-nightly.yml
  • .github/workflows/e2e-pw-smoke.yml
  • apps/cowswap-e2e-tests/.env.example
  • apps/cowswap-e2e-tests/AGENTS.md
  • apps/cowswap-e2e-tests/src/fixtures/shared.ts
  • apps/cowswap-e2e-tests/src/mocks/bridge/fixtures/bungee-dest-tokens.json
  • apps/cowswap-e2e-tests/src/mocks/bridge/fixtures/bungee-intermediate-tokens.json
  • apps/cowswap-e2e-tests/src/mocks/bridge/fixtures/bungee-quote.json
  • apps/cowswap-e2e-tests/src/mocks/bridge/fixtures/near-attestation.json
  • apps/cowswap-e2e-tests/src/mocks/bridge/fixtures/near-dest-tokens.json
  • apps/cowswap-e2e-tests/src/mocks/bridge/fixtures/near-quote.json
  • apps/cowswap-e2e-tests/src/mocks/bungee.ts
  • apps/cowswap-e2e-tests/src/mocks/nearIntents.ts
  • apps/cowswap-e2e-tests/src/pages/BridgeRoutePanel.ts
  • apps/cowswap-e2e-tests/src/pages/SwapPage.ts
  • apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts
  • apps/cowswap-e2e-tests/src/tests/cross-chain-swaps.spec.ts
  • apps/cowswap-frontend/src/tradingSdk/bridgingSdk.ts
  • libs/common-hooks/src/useFeatureFlags.ts

Comment thread apps/cowswap-e2e-tests/src/pages/BridgeRoutePanel.ts Outdated
Comment thread apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts Outdated
Comment thread apps/cowswap-e2e-tests/src/support/mockSocketVerifier.ts Outdated
Comment thread apps/cowswap-e2e-tests/src/tests/cross-chain-swaps.spec.ts Outdated
@shoom3301

Copy link
Copy Markdown
Collaborator Author

Addressed the 8 nitpick comments from CodeRabbit's review. Replied inline to the 4 actionable comments; summarizing the nitpicks here since they weren't individually threaded.

Fixed (6):

  • bridgingSdk.ts:44-49 — reworded the garbled comment sentence.
  • useFeatureFlags.ts:22-28 — wrapped the e2e-override merge in useMemo keyed on flags, so it no longer hands consumers a new object identity on every render.
  • mockSocketVerifier.ts:8-11STUBBED_SELECTORS now derives both selectors from their signature strings via viem's toFunctionSelector instead of hardcoded hex (verified they match the previous hardcoded values before switching).
  • nearIntents.ts:6-10 — extracted the duplicated FIXTURES_DIR/loadFixture (byte-identical to bungee.ts's copy) into a shared src/mocks/bridge/loadFixture.ts, imported by both.
  • bungee.ts:138-182 — added a short comment on toUsd documenting the 6-decimal safe-integer assumption.

Not changing, with reasoning:

  • bridgingSdk.ts:35-37 (duplicated attestor address) — checked @cowprotocol/sdk-bridging's type declarations: ATTESTATOR_ADDRESS isn't exported at all, so there's no SDK value to derive from or assert against. The existing comment already documents why it's duplicated; adding a second hardcoded copy in a test wouldn't add real protection against drift, just a third place to update.
  • BridgeRoutePanel.ts:52-64 (data-testid instead of styled-components class match) — this needs adding data-testid to ConfirmDetailsItem's shared Label/Content exports, which render every trade type's confirm/details rows (swap, limit, TWAP), not just bridging. That's a larger production-component change for a test-only convenience, and CodeRabbit's own review flagged it "Poor tradeoff" — agreed. The existing class-substring technique (__Label-) is already the established pattern for the rest of this file's locators.
  • bungee.ts:50 / nearIntents.ts:31 (installer's void context.route() not awaited) — every other mock installer in this suite (installAllowances, installBalances, installMulticall3, installEthGetCode, installTokenLists, installSafeSdk, installLaunchDarkly, installUsdPrices) uses the same fire-and-forget pattern, registered in the mocks fixture well before any navigation starts. Making only these two new installers async would be inconsistent with that convention; a suite-wide change is out of scope here. (mockSocketVerifier's missing await was fixed separately — that one's structurally different: it's called mid-test, right before a navigation, and has a documented real failure mode if the registration loses the race.)

@shoom3301
shoom3301 marked this pull request as draft August 14, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant