All E2E tests run with a proxy mock server. Requests not matched by a mock reach the real network, but the test framework warns you (and will soon enforce this). Always mock external APIs your feature calls.
Pass to withFixtures to apply mocks only for that test:
import { Mockttp } from 'mockttp';
import { setupRemoteFeatureFlagsMock } from '../../api-mocking/helpers/remoteFeatureFlagsHelper';
import { setupMockRequest } from '../../api-mocking/mockHelpers';
const testSpecificMock = async (mockServer: Mockttp) => {
// Feature flags
await setupRemoteFeatureFlagsMock(mockServer, { myFeatureEnabled: true });
// GET request
await setupMockRequest(mockServer, {
requestMethod: 'GET',
url: 'https://api.example.com/data',
response: { items: [] },
responseCode: 200,
});
};
await withFixtures({ fixture: ..., testSpecificMock }, async () => { ... });import { setupRemoteFeatureFlagsMock } from '../../api-mocking/helpers/remoteFeatureFlagsHelper';
// Simple boolean flags
await setupRemoteFeatureFlagsMock(mockServer, {
predictTradingEnabled: true,
carouselBanners: false,
});
// Nested flags
await setupRemoteFeatureFlagsMock(mockServer, {
bridgeConfig: { support: true, refreshRate: 5000 },
});
// Flask distribution
await setupRemoteFeatureFlagsMock(mockServer, { perpsEnabled: true }, 'flask');
// Combine predefined configs
import { confirmationsRedesignedFeatureFlags } from '../../api-mocking/mock-responses/feature-flags-mocks';
await setupRemoteFeatureFlagsMock(
mockServer,
Object.assign({}, ...confirmationsRedesignedFeatureFlags, { myFlag: true }),
);import {
setupMockRequest,
setupMockPostRequest,
} from '../../api-mocking/mockHelpers';
// GET
await setupMockRequest(mockServer, {
requestMethod: 'GET',
url: 'https://api.example.com/resource',
response: { data: [] },
responseCode: 200,
});
// POST with body validation
await setupMockPostRequest(
mockServer,
'https://api.example.com/submit',
{ amount: '1000000000000000000' }, // expected request body
{ success: true }, // response
{ statusCode: 201, ignoreFields: ['timestamp', 'nonce'] },
);For mocks used across multiple tests, create a file in tests/api-mocking/mock-responses/:
// tests/api-mocking/mock-responses/predict-mocks.ts
import { MockApiEndpoint } from '../framework/types';
export const PREDICT_MOCKS = {
GET: [
{
urlEndpoint: 'https://predict.api.metamask.io/markets',
responseCode: 200,
response: { markets: [{ id: 'btc-usd', name: 'BTC above $100k?' }] },
},
] as MockApiEndpoint[],
};Then pass directly to withFixtures:
await withFixtures({ fixture: ..., testSpecificMock: PREDICT_MOCKS }, async () => { ... });Only needed when the feature uses SDKs with complex transport (WebSockets, custom protocols) that can't be intercepted at the HTTP level.
- Implement a mixin in
tests/controller-mocking/mock-config/ - See
tests/docs/CONTROLLER_MOCKING.mdfor details - Prefer HTTP-level mocking whenever possible
Check test output for warnings like:
⚠️ Unmocked request: GET https://api.example.com/resource
Add a mock for every such request to ensure test determinism.
Some features depend on WebSockets or other non-HTTP transport (e.g. Perps/HyperLiquid, real-time data). The HTTP mock server cannot intercept these. The repo uses three patterns:
- WebSocket mocking — A
LocalWebSocketServer(tests/websocket/server.ts) intercepts production WebSocket connections via URL rewriting in the E2E shim. Protocol-specific mocks handle subscribe/unsubscribe and push notifications. Seetests/docs/WEBSOCKET_MOCKING.mdfor full usage guide and how to add new services. Example:tests/websocket/account-activity-mocks.tsfor AccountActivity. - Controller-level mocking — A mixin under
tests/controller-mocking/mock-config/replaces provider SDK touchpoints so E2E runs with stable, test-controlled data. Example:perps-controller-mixin.tsfor HyperLiquid. Seetests/docs/CONTROLLER_MOCKING.mdfor when and how to use it. - Command queue / test server — Tests that need to drive the app (e.g. inject state or commands) can use
CommandQueueServer(tests/framework/fixtures/CommandQueueServer.ts). Enable it in the fixture withuseCommandQueueServer: true. Used by Perps specs (e.g.tests/smoke/perps/perps-add-funds.spec.ts,tests/regression/perps/perps-limit-long-fill.spec.ts). The app consumes the queue in E2E context.
When adding support for a new feature that uses WebSockets or similar:
- For WebSocket services: add a service config in
tests/websocket/constants.tsand a protocol mock. Seetests/docs/WEBSOCKET_MOCKING.md. - For SDK-level mocking: implement under
tests/controller-mocking/mock-config/. - For test-driven commands: extend the command-queue protocol as needed.
- Add or update tests/specs that cover the mock infrastructure and the E2E flow.
Prefer HTTP mocking whenever the feature’s API is plain HTTP; use WebSocket mocking for WS connections; use controller mocking or the command server only when necessary.