Skip to content

test(e2e): mock Polymarket endpoints to remove from allowlist (MMQA-1800)#29811

Merged
chrisleewilcox merged 8 commits into
mainfrom
MMQA-1800-mock-polymarket-defaults
May 8, 2026
Merged

test(e2e): mock Polymarket endpoints to remove from allowlist (MMQA-1800)#29811
chrisleewilcox merged 8 commits into
mainfrom
MMQA-1800-mock-polymarket-defaults

Conversation

@chrisleewilcox
Copy link
Copy Markdown
Contributor

@chrisleewilcox chrisleewilcox commented May 6, 2026

Description

Removes both Polymarket entries from ALLOWLISTED_HOSTS by adding default mocks for the Polymarket endpoints fired by the wallet's Explore tab and shoring up several pre-existing test-mock gaps the wildcard had been masking. Parent epic MMQA-1364.

Why these were allowlisted in the first place

The wallet's Explore tab (TrendingView / usePredictMarketData) fetches data from gamma-api.polymarket.com and other Polymarket hosts when rendered. Many specs pass through Explore on the way to the browser — tests/flows/browser.flow.ts:118 calls navigateToBrowserView() via Explore → Trending → Browser, so Polymarket calls fire across many specs that have nothing to do with prediction markets.

What this PR adds

  1. New default mocks under defaults/polymarket-apis.ts for the Explore-render endpoints:
Endpoint Default response
gamma-api.polymarket.com/events/pagination?... { data: [] }
gamma-api.polymarket.com/public-search?... { events: [] }
gamma-api.polymarket.com/markets?... []
gamma-api.polymarket.com/teams?... [] (defensive — non-predict specs that hit the new TeamsCache get an empty payload to absorb the leak)
polymarket.com/api/homepage/carousel []
polymarket.com/api/crypto/crypto-price?... {}
data-api.polymarket.com/positions?... []
data-api.polymarket.com/activity?... []
data-api.polymarket.com/upnl?... []

gamma-api.polymarket.com/events/{id} and events?parent_event_id=... are intentionally not in defaults — empty payloads for those routes caused the wallet's detail screens to render the legacy layout (no picks list). They're now covered by spec-specific mocks instead.

  1. Extended POLYMARKET_COMPLETE_MOCKS with two new helpers:
  • POLYMARKET_PRICES_HISTORY_MOCKSclob.polymarket.com/prices-history returning { history: [] }. Predict happy-path specs were making live calls here via the wildcard.
  • POLYMARKET_TEAMS_MOCKSgamma-api.polymarket.com/teams?league=... returning realistic NBA + NFL team rosters via a callback. Required because the new TeamsCache/buildGameData path (recently added on main) drops market.game to undefined when teams aren't found, causing PredictMarketDetails.tsx:370 to render the legacy layout (no picks list, no cash-out button).
  1. Tightened POLYMARKET_EVENT_DETAILS_MOCKS:
  • Bumped to explicit PRIORITY.BASE (was at default mockttp priority, tied with the proxy fallback handler — the wildcard was masking cases where the fallback won).
  • Tightened matcher to /events/{numericId} only, after Cursor Bugbot flagged that includes('events/') also matches events/pagination because events/ is a substring of events/pagination. The new regex gamma-api\.polymarket\.com\/events\/[0-9]+ ensures pagination requests fall through to their dedicated mock regardless of registration order.
  1. Extended trending-api-mocks.ts with three new entries used by the trending feed's prediction detail flow:
  • gamma-api.polymarket.com/events/1 returning the same Bitcoin event payload as the existing events/pagination mock
  • clob.polymarket.com/prices-history returning { history: [] }
  • clob.polymarket.com/prices (POST) returning {}

Allowlist entries removed:

  • gamma-api.polymarket.com (was redundant — covered by the wildcard)
  • *.polymarket.com (covered all subdomains + apex)

ALLOWLISTED_HOSTS is now down to 5 entries: 4 local + metamask.github.io.

Changelog

CHANGELOG entry: null

Related issues

MMQA-1800
Parent epic: MMQA-1364

Fixes:

Manual testing steps

Feature: E2E mock coverage for Polymarket Explore-tab calls

  Scenario: browser specs that pass through Explore no longer leak Polymarket requests
    Given an E2E spec calls navigateToBrowserView()
    And the flow taps Explore → Trending → Browser

    When TrendingView renders sports market feeds via usePredictMarketData
    Then requests to gamma-api.polymarket.com (events/pagination, public-search, markets, teams) are answered by the default mocks
    And requests to data-api.polymarket.com (positions, activity, upnl) are answered by the default mocks
    And requests to polymarket.com (homepage/carousel, crypto/crypto-price) are answered by the default mocks
    And no entries for Polymarket hosts are required in mock-e2e-allowlist.ts

  Scenario: predict specs render market detail with picks list and cash-out button
    Given the spec registers POLYMARKET_COMPLETE_MOCKS as its testSpecificMock
    And the production default for predictLiveSports has leagues ['nfl','nba']

    When the test taps a position and navigates to PredictMarketDetails
    Then gamma-api.polymarket.com/teams returns realistic team payloads for the requested league
    And buildGameData populates market.game with home/away team data
    And PredictMarketDetails renders PredictGameDetailsContent with the picks list
    And the predict-picks-cash-out-button-{positionId} element is present for the test to tap

  Scenario: trending-feed renders prediction detail without leaking
    Given the spec registers TRENDING_API_MOCKS as its testSpecificMock

    When the test taps a prediction row and the wallet navigates to the detail screen
    Then events/{id}, prices, and prices-history are answered by the trending mocks
    And the spec passes without a live request leak

Screenshots/Recordings

Before

tests/api-mocking/mock-e2e-allowlist.ts:

export const ALLOWLISTED_HOSTS = [
  '0.0.0.0', '127.0.0.1', 'localhost', '10.0.2.2',
  'gamma-api.polymarket.com',
  '*.polymarket.com',
  'metamask.github.io',
];

tests/api-mocking/mock-responses/defaults/polymarket-apis.ts had a single entry: the geoblock mock. All other Polymarket calls leaked to live via the wildcard, masking gaps in test-specific mocks.

After

tests/api-mocking/mock-e2e-allowlist.ts:

export const ALLOWLISTED_HOSTS = [
  '0.0.0.0', '127.0.0.1', 'localhost', '10.0.2.2',
  'metamask.github.io',
];

defaults/polymarket-apis.ts now has 10 default GET matchers (geoblock + 9 new) covering Explore-render endpoints.

POLYMARKET_COMPLETE_MOCKS covers clob.polymarket.com/prices-history and gamma-api.polymarket.com/teams with realistic NBA + NFL rosters. POLYMARKET_EVENT_DETAILS_MOCKS has explicit PRIORITY.BASE and a tightened numeric-ID matcher. TRENDING_API_MOCKS covers events/1, prices-history, and prices.

CI verification (commit a3d232d3):

All E2E smoke suites pass with zero leak warnings sampled across prediction-market-{android,ios}-smoke, wallet-platform-{android,ios}-smoke (which includes trending-feed.spec.ts), confirmations-{android,ios}-smoke, and browser-ios-smoke. Run: https://github.com/MetaMask/metamask-mobile/actions/runs/25526071329

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

…800)

The wallet's Explore tab (TrendingView / usePredictMarketData) fetches
data from gamma-api.polymarket.com and other Polymarket hosts when
rendered. Many specs pass through Explore on the way to the browser
via navigateToBrowserView() — Explore → Trending → Browser — so
Polymarket calls fire across many specs that aren't predict-related.

Adds minimal-safe default mocks for the endpoints fired during Explore
render (events/pagination, public-search, events/{id}, markets, parent
events, homepage/carousel, crypto-price, data-api positions/activity/
upnl). Response shapes match the consumer's expected payload (e.g.
events/pagination returns { data: [] } since the consumer reads
data?.data).

Predict and trending specs already register POLYMARKET_COMPLETE_MOCKS
as testSpecificMock at higher priority, so their flows are unaffected
by these defaults.

Removes both Polymarket entries from ALLOWLISTED_HOSTS:
- gamma-api.polymarket.com (was redundant — covered by the wildcard)
- *.polymarket.com (covered all subdomains + apex)

clob.polymarket.com is not in defaults because it only fires on trade
actions, not Explore render. If CI surfaces leakage, follow up.

ALLOWLISTED_HOSTS is now down to 5 entries (4 local + metamask.github.io).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbotv2 metamaskbotv2 Bot added the team-qa QA team label May 6, 2026
@github-actions github-actions Bot added pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. size-S labels May 6, 2026
CI surfaced two pre-existing leaks the *.polymarket.com wildcard had
been masking. Both are fixed here so the wildcard removal can ship.

- POLYMARKET_COMPLETE_MOCKS: add prices-history mock returning
  { history: [] }. Predict happy-path specs (open-position, cash-out,
  claim-positions, geo-restriction) were making live calls to
  clob.polymarket.com/prices-history; the chart consumer in
  PolymarketProvider treats a non-array history as empty so this
  empty payload is safe.

- trending-api-mocks: add events/1 (rich Bitcoin event payload
  matching the existing pagination response) and prices-history
  (empty history). trending-feed.spec.ts taps prediction row 1, which
  navigates to a detail screen that calls these endpoints; without
  the mocks the detail screen renders empty and the wallet's React
  tree throws.

- defaults/polymarket-apis: drop the events/{id} and
  events?parent_event_id matchers. They were too aggressive — empty
  payloads cause the wallet to crash in detail screens. Detail-level
  calls should be covered by the spec's testSpecificMock, not by
  generic defaults.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added size-M and removed size-S labels May 6, 2026
@chrisleewilcox chrisleewilcox removed the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label May 6, 2026
…QA-1800)

Two more endpoints surfaced on the previous CI run:

- POLYMARKET_EVENT_DETAILS_MOCKS lacked an explicit priority. Tied at
  default priority with the proxy fallback handler in MockServerE2E,
  the wildcard *.polymarket.com allowlist had been hiding cases where
  the fallback won. Bump to PRIORITY.BASE so events/{id} interception
  is reliable. Fixes events/60362 (predict-claim-positions) and
  events/79682 (predict-open-position).

- trending-api-mocks: add a POST /clob.polymarket.com/prices mock
  returning {} so the prediction detail render in trending-feed.spec
  doesn't leak.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chrisleewilcox chrisleewilcox added the skip-smart-e2e-selection Skip Smart E2E selection, i.e. select all E2E tests to run label May 6, 2026
@chrisleewilcox chrisleewilcox removed the skip-smart-e2e-selection Skip Smart E2E selection, i.e. select all E2E tests to run label May 7, 2026
@chrisleewilcox chrisleewilcox marked this pull request as ready for review May 7, 2026 14:53
@chrisleewilcox chrisleewilcox requested a review from a team as a code owner May 7, 2026 14:53
@chrisleewilcox chrisleewilcox enabled auto-merge May 7, 2026 14:53
cortisiko
cortisiko previously approved these changes May 7, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ef93a06. Configure here.

Comment thread tests/api-mocking/mock-responses/polymarket/polymarket-mocks.ts
The main merge brought in TeamsCache (app/components/UI/Predict/
providers/polymarket/TeamsCache.ts) which fetches
gamma-api.polymarket.com/teams?league=...&abbreviation=... when
rendering sports markets that have team metadata (NBA, NFL, etc.).

Adds:
- POLYMARKET_TEAMS_MOCKS function in polymarket-mocks.ts (returns []),
  wired into POLYMARKET_COMPLETE_MOCKS so predict specs are covered.
- Default GET matcher in defaults/polymarket-apis.ts so non-predict
  specs that pass through Explore don't leak when team-aware markets
  render. Empty array is safe — TeamsCache short-circuits on
  non-array responses.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chrisleewilcox
Copy link
Copy Markdown
Contributor Author

@metamaskbot update-mobile-fixture

chrisleewilcox and others added 2 commits May 7, 2026 12:24
Cursor Bugbot flagged that the previous matcher
`url.includes('gamma-api.polymarket.com/events/')` also matches
`events/pagination` because the substring `events/` appears in
`events/pagination`. With the priority bump in commit 42b2b55,
this rule was at the same priority (PRIORITY.BASE = 999) as the
dedicated POLYMARKET_MARKET_FEEDS_MOCKS pagination matcher.

In practice the bug didn't manifest in the green CI run because
mockttp at equal priority picks the later-registered rule, and
MARKET_FEEDS_MOCKS is registered after EVENT_DETAILS_MOCKS in
POLYMARKET_COMPLETE_MOCKS. But the dependency on registration
order is fragile.

Tighten the matcher to only catch numeric event-id URLs
(/events/{digits}). Now `events/pagination` and
`events?parent_event_id=...` fall through to their dedicated
mocks regardless of registration order.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Investigation revealed why predict-* specs were failing on cash-out
button lookup after main was merged in.

Path:
- Production default for predictLiveSports has leagues=['nfl','nba']
  (registry: tests/feature-flags/feature-flag-registry.ts:3471)
- The tests load this default via setupRemoteFeatureFlagsMock, so
  liveSportsEnabled=true and the wallet calls TeamsCache.ensureTeamsLoaded
  for game events
- TeamsCache caches teams by abbreviation; if a team is missing,
  buildGameData (gameParser.ts:412-417) returns null, which leaves
  market.game undefined
- PredictMarketDetails.tsx:370 only renders the new
  PredictGameDetailsContent (which contains the picks list with
  predict-picks-cash-out-button-{positionId}) when market?.game is set;
  otherwise it falls back to the legacy market detail layout that
  doesn't have the picks list

Returning [] from /teams (previous behavior) caused the wallet to fall
back to the legacy layout, so the cash-out button was never rendered.

This change replaces the static [] with a callback that returns the
NBA/NFL teams referenced by predict E2E fixtures (sas, nop, bos, bkn
for NBA; buf/atl/chi/was/den/nyj/det/kc/jax/pit/cin/sea/sf/tb/dal for
NFL). The wallet's TeamsCache stores all returned teams and looks
them up by abbreviation, so returning the full league roster is safe.

The defaults entry stays at [] since non-predict specs don't render
PredictGameDetailsContent — the [] only needs to absorb the leak,
not produce a working render.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokePredictions, SmokeWalletPlatform, SmokeConfirmations
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: medium
  • AI Confidence: 88%
click to see 🤖 AI reasoning details

E2E Test Selection:
All four changed files are E2E test infrastructure (API mocking layer), not app code. The changes:

  1. mock-e2e-allowlist.ts: Removes gamma-api.polymarket.com and *.polymarket.com from the allowlist, meaning Polymarket traffic will now be intercepted by the mock server instead of passing through live. This is a correctness fix to prevent live API leakage in tests.

  2. defaults/polymarket-apis.ts: Massively expands default Polymarket mock responses (events/pagination, public-search, markets, teams, homepage carousel, crypto-price, positions, activity, upnl). These defaults apply to ALL tests that navigate through the Explore/Trending tab, preventing live Polymarket requests from leaking in non-predict specs.

  3. polymarket-mocks.ts: Adds POLYMARKET_PRICES_HISTORY_MOCKS and POLYMARKET_TEAMS_MOCKS to POLYMARKET_COMPLETE_MOCKS, and refines the event details regex to avoid matching /events/pagination. These are used by SmokePredictions tests.

  4. trending-api-mocks.ts: Adds mocks for Polymarket event details (event ID 1), prices-history, and CLOB prices endpoints used when rendering prediction rows in the Trending feed. Used by SmokeWalletPlatform trending tests.

Selected tags:

  • SmokePredictions: Directly affected — POLYMARKET_COMPLETE_MOCKS (used by all predict specs) now includes new mocks for prices-history and teams. The event details regex fix could affect how predict tests match event detail requests. These tests must be validated.
  • SmokeWalletPlatform: Directly affected — TRENDING_API_MOCKS (used by trending-feed.spec.ts, trending-search.spec.ts, trending-browser.spec.ts) now includes additional Polymarket endpoint mocks for event details and chart data. The Trending tab renders Predictions section which fires these APIs.
  • SmokeConfirmations: Required per SmokePredictions tag description — opening/closing positions are on-chain transactions that go through the confirmations flow.

No app code was changed, so no performance tests are needed.

Performance Test Selection:
All changes are in the E2E test infrastructure (API mocking layer). No app code, UI components, controllers, or data loading logic was modified. Performance characteristics of the app are unaffected by these changes.

View GitHub Actions results

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 7, 2026

@chrisleewilcox chrisleewilcox added this pull request to the merge queue May 8, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 8, 2026
@chrisleewilcox chrisleewilcox added this pull request to the merge queue May 8, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 8, 2026
@chrisleewilcox chrisleewilcox added this pull request to the merge queue May 8, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 8, 2026
@chrisleewilcox chrisleewilcox added this pull request to the merge queue May 8, 2026
Merged via the queue into main with commit ea334d0 May 8, 2026
108 checks passed
@chrisleewilcox chrisleewilcox deleted the MMQA-1800-mock-polymarket-defaults branch May 8, 2026 15:10
@github-actions github-actions Bot locked and limited conversation to collaborators May 8, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.78.0 Issue or pull request that will be included in release 7.78.0 label May 8, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.78.0 Issue or pull request that will be included in release 7.78.0 size-M team-qa QA team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants