diff --git a/.gitattributes b/.gitattributes index 75d1544237f..677b8fb2faa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,5 +2,7 @@ # https://help.github.com/articles/dealing-with-line-endings/ *.bat text eol=crlf +# Snap binary tarballs stored with .txt extension must not be normalized +tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/*.txt binary # Shell scripts must keep LF so they run in WSL on Windows. *.sh text eol=lf diff --git a/app/core/Snaps/location/npm.test.ts b/app/core/Snaps/location/npm.test.ts index 0839e6db295..d27491b29d6 100644 --- a/app/core/Snaps/location/npm.test.ts +++ b/app/core/Snaps/location/npm.test.ts @@ -1,4 +1,15 @@ import { NativeModules } from 'react-native'; + +// Mock the isE2E flag via a mutable variable so individual tests can toggle it. +let mockIsE2E = false; +jest.mock('../../../util/test/utils', () => ({ + get isE2E() { + return mockIsE2E; + }, + getMockServerPortInApp: jest.fn(() => 8000), +})); + +// eslint-disable-next-line import-x/first import { NpmLocation } from './npm'; // Mock RNTar native module before anything else @@ -6,20 +17,22 @@ NativeModules.RNTar = { unTar: jest.fn().mockResolvedValue('/document-dir/archive'), }; +const mockBlobFetch = jest.fn((..._args: unknown[]) => + Promise.resolve({ + flush: jest.fn(), + data: '/document-dir/archive.tgz', + respInfo: { + status: 200, + headers: { + 'content-length': '2000', + }, + }, + }), +); + jest.mock('react-native-blob-util', () => ({ config: jest.fn(() => ({ - fetch: jest.fn(() => - Promise.resolve({ - flush: jest.fn(), - data: '/document-dir/archive.tgz', - respInfo: { - status: 200, - headers: { - 'content-length': '2000', - }, - }, - }), - ), + fetch: mockBlobFetch, })), fs: { unlink: jest.fn().mockResolvedValue(undefined), @@ -46,6 +59,11 @@ jest.mock('react-native-blob-util', () => ({ })); describe('NpmLocation', () => { + beforeEach(() => { + mockBlobFetch.mockClear(); + mockIsE2E = false; + }); + // This test is heavily mocked and not necesarily a good indicator that everything works E2E. it('fetches and unpacks tarballs', async () => { const location = new NpmLocation(new URL('npm:@metamask/example-snap')); @@ -61,4 +79,32 @@ describe('NpmLocation', () => { `module.exports.onRpcRequest = () => null`, ); }); + + describe('E2E URL rewriting', () => { + it('routes tarball downloads to MockServerE2E /proxy when isE2E is true', async () => { + mockIsE2E = true; + + const location = new NpmLocation(new URL('npm:@metamask/example-snap')); + await location.fetch('snap.manifest.json'); + + expect(mockBlobFetch).toHaveBeenCalledWith( + 'GET', + expect.stringMatching( + /^http:\/\/localhost:8000\/proxy\?url=https%3A%2F%2Fregistry\.npmjs\.org%2F/, + ), + ); + }); + + it('uses the original tarball URL when isE2E is false', async () => { + mockIsE2E = false; + + const location = new NpmLocation(new URL('npm:@metamask/example-snap')); + await location.fetch('snap.manifest.json'); + + expect(mockBlobFetch).toHaveBeenCalledWith( + 'GET', + expect.stringMatching(/^https:\/\/registry\.npmjs\.org\//), + ); + }); + }); }); diff --git a/app/core/Snaps/location/npm.ts b/app/core/Snaps/location/npm.ts index 6d2ec6f09ac..f4b48a7b1e7 100644 --- a/app/core/Snaps/location/npm.ts +++ b/app/core/Snaps/location/npm.ts @@ -10,6 +10,7 @@ import { getNpmCanonicalBasePath, TARBALL_SIZE_SAFETY_LIMIT, } from '@metamask/snaps-controllers'; +import { isE2E, getMockServerPortInApp } from '../../../util/test/utils'; const { RNTar } = NativeModules; @@ -50,7 +51,17 @@ export class NpmLocation extends BaseNpmLocation { let response: FetchBlobResponse | null = null; let untarPath: string | null = null; try { - response = await this.#blobFetch('GET', tarballUrl.toString()); + // In E2E tests, route the tarball download through MockServerE2E's /proxy + // endpoint so test-specific mocks can intercept it. ReactNativeBlobUtil's + // native fetch bypasses shim.js's JS-layer fetch/XHR patches, so the + // redirect must happen here at the source URL. + const fetchUrl = isE2E + ? `http://localhost:${getMockServerPortInApp()}/proxy?url=${encodeURIComponent( + tarballUrl.toString(), + )}` + : tarballUrl.toString(); + + response = await this.#blobFetch('GET', fetchUrl); const responseInfo = response.respInfo; diff --git a/app/util/test/utils.js b/app/util/test/utils.js index fc552f6b511..095e7bb4a22 100644 --- a/app/util/test/utils.js +++ b/app/util/test/utils.js @@ -5,6 +5,7 @@ export const flushPromises = () => new Promise(setImmediate); // iOS: These are overridden by LaunchArgs at runtime export const FALLBACK_FIXTURE_SERVER_PORT = 12345; export const FALLBACK_COMMAND_QUEUE_SERVER_PORT = 2446; +export const FALLBACK_MOCK_SERVER_PORT = 8000; // E2E test configuration required in app export const testConfig = {}; @@ -42,5 +43,7 @@ export const getFixturesServerPortInApp = () => testConfig.fixtureServerPort ?? FALLBACK_FIXTURE_SERVER_PORT; export const getCommandQueueServerPortInApp = () => testConfig.commandQueueServerPort ?? FALLBACK_COMMAND_QUEUE_SERVER_PORT; +export const getMockServerPortInApp = () => + testConfig.mockServerPort ?? FALLBACK_MOCK_SERVER_PORT; export const isRc = process.env.METAMASK_ENVIRONMENT === 'rc'; diff --git a/package.json b/package.json index 55bb09b8b8a..00ab364b230 100644 --- a/package.json +++ b/package.json @@ -149,6 +149,7 @@ "feature-flags:sync": "ts-node tests/feature-flags/sync-production-flags.ts", "feature-flags:sync:check": "ts-node tests/feature-flags/sync-production-flags.ts --check", "feature-flags:sync:update": "ts-node tests/feature-flags/sync-production-flags.ts --update", + "update-snap-binary": "ts-node --transpile-only scripts/update-snap-binary.ts", "worktree:create": "yarn ts-node --transpile-only scripts/worktree-create.ts", "worktree:remove": "yarn ts-node --transpile-only scripts/worktree-remove.ts", "a:start": "scripts/perps/agentic/start-metro.sh", diff --git a/scripts/update-snap-binary.ts b/scripts/update-snap-binary.ts new file mode 100644 index 00000000000..fff14db12fe --- /dev/null +++ b/scripts/update-snap-binary.ts @@ -0,0 +1,114 @@ +import { existsSync, readdirSync, unlinkSync, mkdirSync, writeFileSync } from 'fs'; +import { resolve, join, basename } from 'path'; +import { valid } from 'semver'; + +const SNAP_BINARIES_DIR = resolve( + __dirname, + '../tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers', +); + +const RELEVANT_HEADERS = [ + 'accept-ranges', + 'content-length', + 'content-type', + 'etag', + 'vary', +]; + +function parseArgs(): { snapName: string; version: string } { + const arg = process.argv[2]; + if (!arg || !arg.startsWith('--')) { + console.error('Usage: yarn update-snap-binary --@'); + console.error('Example: yarn update-snap-binary --bip32-example-snap@2.3.0'); + process.exit(1); + } + + const nameVersion = arg.slice(2); + const atIndex = nameVersion.lastIndexOf('@'); + if (atIndex <= 0) { + console.error(`Invalid format: ${nameVersion}. Expected @`); + process.exit(1); + } + + const snapName = nameVersion.slice(0, atIndex); + const version = nameVersion.slice(atIndex + 1); + + if (!/^[a-z0-9-]+$/i.test(snapName)) { + console.error(`Invalid snap name: ${snapName}. Only alphanumeric and hyphens allowed.`); + process.exit(1); + } + + if (!valid(version)) { + console.error(`Invalid semver version: ${version}`); + process.exit(1); + } + + return { snapName, version }; +} + +function deleteOldSnapFiles(snapName: string): void { + if (!existsSync(SNAP_BINARIES_DIR)) return; + const files = readdirSync(SNAP_BINARIES_DIR); + for (const file of files) { + if (file.startsWith(`${snapName}@`)) { + const filePath = join(SNAP_BINARIES_DIR, file); + unlinkSync(filePath); + console.log(`Deleted old file: ${file}`); + } + } +} + +async function downloadSnapBinary( + snapName: string, + version: string, +): Promise { + const scopedName = `@metamask/${snapName}`; + const tarballUrl = `https://registry.npmjs.org/${scopedName}/-/${snapName}-${version}.tgz`; + + console.log(`Downloading ${scopedName}@${version} from ${tarballUrl}`); + + const response = await fetch(tarballUrl); + if (!response.ok) { + throw new Error( + `Failed to download: ${response.status} ${response.statusText}`, + ); + } + + if (!existsSync(SNAP_BINARIES_DIR)) { + mkdirSync(SNAP_BINARIES_DIR, { recursive: true }); + } + + deleteOldSnapFiles(snapName); + + const buffer = Buffer.from(await response.arrayBuffer()); + const binaryPath = resolve(SNAP_BINARIES_DIR, `${snapName}@${version}.txt`); + const headersPath = resolve(SNAP_BINARIES_DIR, `${snapName}@${version}-headers.json`); + + if (!binaryPath.startsWith(SNAP_BINARIES_DIR) || !headersPath.startsWith(SNAP_BINARIES_DIR)) { + throw new Error('Resolved path escapes target directory'); + } + + writeFileSync(binaryPath, buffer); + console.log(`Saved binary: ${basename(binaryPath)}`); + + const headers: Record = {}; + for (const headerName of RELEVANT_HEADERS) { + const value = response.headers.get(headerName); + if (value) { + headers[headerName] = value; + } + } + writeFileSync(headersPath, JSON.stringify(headers, null, 2)); + console.log(`Saved headers: ${basename(headersPath)}`); +} + +async function main(): Promise { + const { snapName, version } = parseArgs(); + await downloadSnapBinary(snapName, version); + console.log('Done.'); +} + +main().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/shim.js b/shim.js index f946306f4d6..4627256aa58 100644 --- a/shim.js +++ b/shim.js @@ -35,6 +35,7 @@ import { LaunchArguments } from 'react-native-launch-arguments'; import { FALLBACK_FIXTURE_SERVER_PORT, FALLBACK_COMMAND_QUEUE_SERVER_PORT, + FALLBACK_MOCK_SERVER_PORT, isE2E, isTest, enableApiCallLogs, @@ -114,6 +115,9 @@ if (isTest) { testConfig.commandQueueServerPort = raw?.commandQueueServerPort ? raw.commandQueueServerPort : FALLBACK_COMMAND_QUEUE_SERVER_PORT; + testConfig.mockServerPort = raw?.mockServerPort + ? raw.mockServerPort + : FALLBACK_MOCK_SERVER_PORT; } // Fix for https://github.com/facebook/react-native/issues/5667 diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/background-events-example-snap@1.0.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/background-events-example-snap@1.0.0-headers.json new file mode 100644 index 00000000000..9cbf46c675c --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/background-events-example-snap@1.0.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "12336", + "content-type": "application/octet-stream", + "etag": "\"6089ae64c9d548802d1cb3cefc4a4366\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/background-events-example-snap@1.0.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/background-events-example-snap@1.0.0.txt new file mode 100644 index 00000000000..cbb4523cb0e Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/background-events-example-snap@1.0.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip32-example-snap@2.3.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip32-example-snap@2.3.0-headers.json new file mode 100644 index 00000000000..0bfd83c492c --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip32-example-snap@2.3.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "72040", + "content-type": "application/octet-stream", + "etag": "\"f6aefd54643480c1b753fa4244a537cf\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip32-example-snap@2.3.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip32-example-snap@2.3.0.txt new file mode 100644 index 00000000000..e93d5fbd0fc Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip32-example-snap@2.3.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip44-example-snap@2.2.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip44-example-snap@2.2.0-headers.json new file mode 100644 index 00000000000..f90fcc40cba --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip44-example-snap@2.2.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "78008", + "content-type": "application/octet-stream", + "etag": "\"2868a47b39a090ac18044548fb6fa37e\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip44-example-snap@2.2.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip44-example-snap@2.2.0.txt new file mode 100644 index 00000000000..cd67d7044cd Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/bip44-example-snap@2.2.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/client-status-example-snap@1.0.3-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/client-status-example-snap@1.0.3-headers.json new file mode 100644 index 00000000000..c0030ea60e5 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/client-status-example-snap@1.0.3-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "11873", + "content-type": "application/octet-stream", + "etag": "\"84e43175ffad7735148282c566b2a933\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/client-status-example-snap@1.0.3.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/client-status-example-snap@1.0.3.txt new file mode 100644 index 00000000000..e1aaa01987b Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/client-status-example-snap@1.0.3.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/cronjob-example-snap@3.0.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/cronjob-example-snap@3.0.0-headers.json new file mode 100644 index 00000000000..31f68713e87 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/cronjob-example-snap@3.0.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "14697", + "content-type": "application/octet-stream", + "etag": "\"19f44e9e1a7ae62f4d036c5b76d585b7\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/cronjob-example-snap@3.0.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/cronjob-example-snap@3.0.0.txt new file mode 100644 index 00000000000..c277da488d3 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/cronjob-example-snap@3.0.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/dialog-example-snap@2.3.1-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/dialog-example-snap@2.3.1-headers.json new file mode 100644 index 00000000000..e709d5e1e12 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/dialog-example-snap@2.3.1-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "14985", + "content-type": "application/octet-stream", + "etag": "\"2ba3e0bc12c6102b0b8364df36d35fee\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/dialog-example-snap@2.3.1.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/dialog-example-snap@2.3.1.txt new file mode 100644 index 00000000000..838f6ceb13c Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/dialog-example-snap@2.3.1.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/error-example-snap@2.1.3-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/error-example-snap@2.1.3-headers.json new file mode 100644 index 00000000000..40dde2e6668 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/error-example-snap@2.1.3-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "7097", + "content-type": "application/octet-stream", + "etag": "\"0f020a896a5e7e71490980948e215922\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/error-example-snap@2.1.3.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/error-example-snap@2.1.3.txt new file mode 100644 index 00000000000..10d3536e558 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/error-example-snap@2.1.3.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/ethereum-provider-example-snap@3.0.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/ethereum-provider-example-snap@3.0.0-headers.json new file mode 100644 index 00000000000..548e6b8006a --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/ethereum-provider-example-snap@3.0.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "40830", + "content-type": "application/octet-stream", + "etag": "\"f7162b1783325693be06cf33e22a2046\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/ethereum-provider-example-snap@3.0.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/ethereum-provider-example-snap@3.0.0.txt new file mode 100644 index 00000000000..06e20b36602 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/ethereum-provider-example-snap@3.0.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-entropy-example-snap@2.2.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-entropy-example-snap@2.2.0-headers.json new file mode 100644 index 00000000000..9624355552b --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-entropy-example-snap@2.2.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "28663", + "content-type": "application/octet-stream", + "etag": "\"8d2d41cb8f2f7e7218f4224f6729486d\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-entropy-example-snap@2.2.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-entropy-example-snap@2.2.0.txt new file mode 100644 index 00000000000..1065c683448 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-entropy-example-snap@2.2.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-file-example-snap@1.1.3-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-file-example-snap@1.1.3-headers.json new file mode 100644 index 00000000000..209c16bfe9e --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-file-example-snap@1.1.3-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "12290", + "content-type": "application/octet-stream", + "etag": "\"8135e843e047041b4bc331ff81490d1f\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-file-example-snap@1.1.3.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-file-example-snap@1.1.3.txt new file mode 100644 index 00000000000..efc5cca5ba4 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/get-file-example-snap@1.1.3.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/images-example-snap@1.2.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/images-example-snap@1.2.0-headers.json new file mode 100644 index 00000000000..fe8abd86bfd --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/images-example-snap@1.2.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "17406", + "content-type": "application/octet-stream", + "etag": "\"53d8d18e3a90eafc45e6b99fa3963f0d\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/images-example-snap@1.2.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/images-example-snap@1.2.0.txt new file mode 100644 index 00000000000..8998a9b0ffa Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/images-example-snap@1.2.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/interactive-ui-example-snap@2.5.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/interactive-ui-example-snap@2.5.0-headers.json new file mode 100644 index 00000000000..0f0f3ea3d48 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/interactive-ui-example-snap@2.5.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "41673", + "content-type": "application/octet-stream", + "etag": "\"fb3226cb55d721daedda5e5701863529\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/interactive-ui-example-snap@2.5.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/interactive-ui-example-snap@2.5.0.txt new file mode 100644 index 00000000000..9031e162f1e Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/interactive-ui-example-snap@2.5.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/json-rpc-example-snap@2.1.3-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/json-rpc-example-snap@2.1.3-headers.json new file mode 100644 index 00000000000..d510ecdc2c6 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/json-rpc-example-snap@2.1.3-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "12621", + "content-type": "application/octet-stream", + "etag": "\"d83c6bec2ed39981ad7f84b36d055564\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/json-rpc-example-snap@2.1.3.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/json-rpc-example-snap@2.1.3.txt new file mode 100644 index 00000000000..caf235fbc2f Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/json-rpc-example-snap@2.1.3.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/jsx-example-snap@1.2.1-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/jsx-example-snap@1.2.1-headers.json new file mode 100644 index 00000000000..1ca9693b944 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/jsx-example-snap@1.2.1-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "11962", + "content-type": "application/octet-stream", + "etag": "\"c618ad778d68fb7bb01568a3f79755ad\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/jsx-example-snap@1.2.1.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/jsx-example-snap@1.2.1.txt new file mode 100644 index 00000000000..50cf4720afc Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/jsx-example-snap@1.2.1.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/lifecycle-hooks-example-snap@2.3.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/lifecycle-hooks-example-snap@2.3.0-headers.json new file mode 100644 index 00000000000..03839b4baa7 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/lifecycle-hooks-example-snap@2.3.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "7557", + "content-type": "application/octet-stream", + "etag": "\"f9b3d3ba2d306efe4add6062ae879d87\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/lifecycle-hooks-example-snap@2.3.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/lifecycle-hooks-example-snap@2.3.0.txt new file mode 100644 index 00000000000..28ecdaab88c Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/lifecycle-hooks-example-snap@2.3.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/manage-state-example-snap@3.0.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/manage-state-example-snap@3.0.0-headers.json new file mode 100644 index 00000000000..0e5e1629005 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/manage-state-example-snap@3.0.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "13369", + "content-type": "application/octet-stream", + "etag": "\"ebf53ab08e421cb48ca87a46a36453f4\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/manage-state-example-snap@3.0.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/manage-state-example-snap@3.0.0.txt new file mode 100644 index 00000000000..22213aeb0bd Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/manage-state-example-snap@3.0.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/multichain-provider-example-snap@1.0.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/multichain-provider-example-snap@1.0.0-headers.json new file mode 100644 index 00000000000..70e320ed806 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/multichain-provider-example-snap@1.0.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "42251", + "content-type": "application/octet-stream", + "etag": "\"a653b90d4181b08d66589fa3ff193d8c\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/multichain-provider-example-snap@1.0.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/multichain-provider-example-snap@1.0.0.txt new file mode 100644 index 00000000000..b87fac873ed Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/multichain-provider-example-snap@1.0.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/name-lookup-example-snap@3.1.2-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/name-lookup-example-snap@3.1.2-headers.json new file mode 100644 index 00000000000..297ae58d8f7 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/name-lookup-example-snap@3.1.2-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "7213", + "content-type": "application/octet-stream", + "etag": "\"46c1c1d932d24ba1f8525db185d6e082\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/name-lookup-example-snap@3.1.2.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/name-lookup-example-snap@3.1.2.txt new file mode 100644 index 00000000000..28f5d75cfd3 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/name-lookup-example-snap@3.1.2.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/network-example-snap@2.2.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/network-example-snap@2.2.0-headers.json new file mode 100644 index 00000000000..2c97e52da1b --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/network-example-snap@2.2.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "13022", + "content-type": "application/octet-stream", + "etag": "\"e69e583dbe6d354859b6adf0a5255a33\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/network-example-snap@2.2.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/network-example-snap@2.2.0.txt new file mode 100644 index 00000000000..33df07127c5 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/network-example-snap@2.2.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/preferences-example-snap@1.0.0-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/preferences-example-snap@1.0.0-headers.json new file mode 100644 index 00000000000..fe6311e7371 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/preferences-example-snap@1.0.0-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "11617", + "content-type": "application/octet-stream", + "etag": "\"680cc54c481db6ee835d31c4803b29b8\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/preferences-example-snap@1.0.0.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/preferences-example-snap@1.0.0.txt new file mode 100644 index 00000000000..f6fac9db1b8 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/preferences-example-snap@1.0.0.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/wasm-example-snap@2.1.5-headers.json b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/wasm-example-snap@2.1.5-headers.json new file mode 100644 index 00000000000..13628762a6f --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/wasm-example-snap@2.1.5-headers.json @@ -0,0 +1,7 @@ +{ + "accept-ranges": "bytes", + "content-length": "13547", + "content-type": "application/octet-stream", + "etag": "\"d97d99aecc904046e68bd9bc1a73f1b0\"", + "vary": "Accept-Encoding" +} diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/wasm-example-snap@2.1.5.txt b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/wasm-example-snap@2.1.5.txt new file mode 100644 index 00000000000..9a9deabf2c3 Binary files /dev/null and b/tests/api-mocking/mock-response-data/snaps/snap-binaries-and-headers/wasm-example-snap@2.1.5.txt differ diff --git a/tests/api-mocking/mock-response-data/snaps/snap-binary-mocks.ts b/tests/api-mocking/mock-response-data/snaps/snap-binary-mocks.ts new file mode 100644 index 00000000000..d18baa1bb63 --- /dev/null +++ b/tests/api-mocking/mock-response-data/snaps/snap-binary-mocks.ts @@ -0,0 +1,229 @@ +/* eslint-disable import-x/no-nodejs-modules */ +/* eslint-disable import-x/no-namespace */ +import * as fs from 'fs'; +import * as path from 'path'; +import * as semver from 'semver'; +import type { Mockttp } from 'mockttp'; +import { getDecodedProxiedURL } from '../../../smoke/notifications/utils/helpers'; + +const SNAP_BINARIES_DIR = path.resolve(__dirname, 'snap-binaries-and-headers'); + +/** + * Scans the binaries directory for files matching `@.txt` + * and returns the latest version via semver sort. + */ +export function getLocalSnapLatestVersion(snapNamePrefix: string): string { + const files = fs.readdirSync(SNAP_BINARIES_DIR); + const versions: string[] = []; + + for (const file of files) { + if (!file.startsWith(`${snapNamePrefix}@`) || !file.endsWith('.txt')) { + continue; + } + const version = file + .slice(`${snapNamePrefix}@`.length) + .replace(/\.txt$/, ''); + if (semver.valid(version)) { + versions.push(version); + } + } + + if (versions.length === 0) { + throw new Error( + `No local binary found for snap "${snapNamePrefix}". ` + + `Run: yarn update-snap-binary --${snapNamePrefix}@`, + ); + } + + versions.sort(semver.rcompare); + return versions[0]; +} + +interface CreateSnapMockOptions { + mockServer: Mockttp; + snapNamePrefix: string; + specificVersion?: string; +} + +/** + * Registers a mockttp rule that intercepts the npm registry tarball download + * for the given snap and returns the local binary file. + */ +export async function createSnapMock( + options: CreateSnapMockOptions, +): Promise { + const { mockServer, snapNamePrefix, specificVersion } = options; + const version = specificVersion ?? getLocalSnapLatestVersion(snapNamePrefix); + + const binaryPath = path.join( + SNAP_BINARIES_DIR, + `${snapNamePrefix}@${version}.txt`, + ); + const headersPath = path.join( + SNAP_BINARIES_DIR, + `${snapNamePrefix}@${version}-headers.json`, + ); + + if (!fs.existsSync(binaryPath)) { + throw new Error( + `Snap binary not found: ${binaryPath}. ` + + `Run: yarn update-snap-binary --${snapNamePrefix}@${version}`, + ); + } + + if (!fs.existsSync(headersPath)) { + throw new Error( + `Snap headers not found: ${headersPath}. ` + + `Run: yarn update-snap-binary --${snapNamePrefix}@${version}`, + ); + } + + const rawBody = fs.readFileSync(binaryPath); + const headers = JSON.parse(fs.readFileSync(headersPath, 'utf-8')); + + const expectedUrlSubstring = `registry.npmjs.org/@metamask/${snapNamePrefix}/-/${snapNamePrefix}-${version}.tgz`; + + await mockServer + .forGet('/proxy') + .matching((request) => { + const decodedUrl = getDecodedProxiedURL(request.url); + return decodedUrl.includes(expectedUrlSubstring); + }) + .thenCallback(() => ({ + statusCode: 200, + rawBody, + headers, + })); +} + +// --- Individual snap mock functions --- + +export async function mockBackgroundEventsSnap( + mockServer: Mockttp, +): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'background-events-example-snap', + }); +} + +export async function mockBip32Snap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'bip32-example-snap' }); +} + +export async function mockBip44Snap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'bip44-example-snap' }); +} + +export async function mockClientStatusSnap(mockServer: Mockttp): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'client-status-example-snap', + }); +} + +export async function mockCronjobSnap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'cronjob-example-snap' }); +} + +export async function mockDialogSnap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'dialog-example-snap' }); +} + +export async function mockErrorSnap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'error-example-snap' }); +} + +export async function mockEthereumProviderSnap( + mockServer: Mockttp, +): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'ethereum-provider-example-snap', + }); +} + +export async function mockGetEntropySnap(mockServer: Mockttp): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'get-entropy-example-snap', + }); +} + +export async function mockGetFileSnap(mockServer: Mockttp): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'get-file-example-snap', + }); +} + +export async function mockImagesSnap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'images-example-snap' }); +} + +export async function mockInteractiveUiSnap( + mockServer: Mockttp, +): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'interactive-ui-example-snap', + }); +} + +export async function mockJsonRpcSnap(mockServer: Mockttp): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'json-rpc-example-snap', + }); +} + +export async function mockJsxSnap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'jsx-example-snap' }); +} + +export async function mockLifecycleHooksSnap( + mockServer: Mockttp, +): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'lifecycle-hooks-example-snap', + }); +} + +export async function mockManageStateSnap(mockServer: Mockttp): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'manage-state-example-snap', + }); +} + +export async function mockMultichainProviderSnap( + mockServer: Mockttp, +): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'multichain-provider-example-snap', + }); +} + +export async function mockNameLookupSnap(mockServer: Mockttp): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'name-lookup-example-snap', + }); +} + +export async function mockNetworkSnap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'network-example-snap' }); +} + +export async function mockPreferencesSnap(mockServer: Mockttp): Promise { + return createSnapMock({ + mockServer, + snapNamePrefix: 'preferences-example-snap', + }); +} + +export async function mockWasmSnap(mockServer: Mockttp): Promise { + return createSnapMock({ mockServer, snapNamePrefix: 'wasm-example-snap' }); +} diff --git a/tests/smoke/snaps/test-snap-background-events.spec.ts b/tests/smoke/snaps/test-snap-background-events.spec.ts index aef5322eacc..fb6d20ac50f 100644 --- a/tests/smoke/snaps/test-snap-background-events.spec.ts +++ b/tests/smoke/snaps/test-snap-background-events.spec.ts @@ -8,6 +8,8 @@ import Assertions from '../../framework/Assertions'; import Matchers from '../../framework/Matchers'; import { BrowserViewSelectorsIDs } from '../../../app/components/Views/BrowserTab/BrowserView.testIds'; import { TestSnapResultSelectorWebIDS } from '../../selectors/Browser/TestSnaps.selectors'; +import { Mockttp } from 'mockttp'; +import { mockBackgroundEventsSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -19,6 +21,9 @@ describe(SmokeSnaps('Background Events Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockBackgroundEventsSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -35,7 +40,6 @@ describe(SmokeSnaps('Background Events Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { const futureDate = new Date(Date.now() + 5_000).toISOString(); @@ -59,7 +63,6 @@ describe(SmokeSnaps('Background Events Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('backgroundEventDurationInput', 'PT5S'); @@ -81,7 +84,6 @@ describe(SmokeSnaps('Background Events Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { // Intentionally scheduling an event for 1 hour into the future, so it @@ -118,18 +120,26 @@ describe(SmokeSnaps('Background Events Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { const pastDate = new Date(Date.now() - 5_000).toISOString(); await TestSnaps.fillMessage('backgroundEventDateInput', pastDate); await TestSnaps.tapButton('scheduleBackgroundEventWithDateButton'); - await Assertions.expectTextDisplayed( - 'Cannot schedule an event in the past.', - { timeout: 30000 }, - ); - await TestSnaps.dismissAlert(); + // iOS shows the error as a native alert; Android renders it in the + // web-view result span as JSON with escaped quotes. + if (device.getPlatform() === 'ios') { + await Assertions.expectTextDisplayed( + 'Cannot schedule an event in the past.', + { timeout: 30000 }, + ); + } else { + await TestSnaps.checkResultSpanIncludes( + 'scheduleBackgroundEventResultSpan', + 'Cannot schedule an event in the past.', + { timeout: 30000 }, + ); + } }, ); }); diff --git a/tests/smoke/snaps/test-snap-bip-32.spec.ts b/tests/smoke/snaps/test-snap-bip-32.spec.ts index b244d7cb201..09855a44a84 100644 --- a/tests/smoke/snaps/test-snap-bip-32.spec.ts +++ b/tests/smoke/snaps/test-snap-bip-32.spec.ts @@ -5,6 +5,8 @@ import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import Assertions from '../../framework/Assertions'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; +import { Mockttp } from 'mockttp'; +import { mockBip32Snap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -16,6 +18,9 @@ describe(SmokeSnaps('BIP-32 Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockBip32Snap(mockServer); + }, }, async () => { await loginToApp(); @@ -32,7 +37,6 @@ describe(SmokeSnaps('BIP-32 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('getPublicKeyBip32Button'); @@ -49,7 +53,6 @@ describe(SmokeSnaps('BIP-32 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('messageSecp256k1Input', 'foo bar'); @@ -69,7 +72,6 @@ describe(SmokeSnaps('BIP-32 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('messageEd25519Input', 'foo bar'); @@ -89,7 +91,6 @@ describe(SmokeSnaps('BIP-32 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('messageEd25519Bip32Input', 'foo bar'); @@ -109,7 +110,6 @@ describe(SmokeSnaps('BIP-32 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.selectInDropdown('bip32EntropyDropDown', 'SRP 1'); @@ -130,7 +130,6 @@ describe(SmokeSnaps('BIP-32 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.selectInDropdown('bip32EntropyDropDown', 'SRP 2'); @@ -151,17 +150,25 @@ describe(SmokeSnaps('BIP-32 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.selectInDropdown('bip32EntropyDropDown', 'Invalid'); await TestSnaps.fillMessage('messageSecp256k1Input', 'bar baz'); await TestSnaps.tapButton('signMessageBip32Secp256k1Button'); - await Assertions.expectTextDisplayed( - 'Entropy source with ID "invalid" not found.', - { timeout: 30000 }, - ); - await TestSnaps.dismissAlert(); + // iOS shows the error as a native alert; Android renders it in the + // web-view result span as JSON with escaped quotes. + if (device.getPlatform() === 'ios') { + await Assertions.expectTextDisplayed( + 'Entropy source with ID "invalid" not found.', + { timeout: 30000 }, + ); + } else { + await TestSnaps.checkResultSpanIncludes( + 'bip32MessageResultSecp256k1Span', + 'Entropy source with ID', + { timeout: 30000 }, + ); + } }, ); }); diff --git a/tests/smoke/snaps/test-snap-bip-44.spec.ts b/tests/smoke/snaps/test-snap-bip-44.spec.ts index 625d1edaefa..6037d70c2e8 100644 --- a/tests/smoke/snaps/test-snap-bip-44.spec.ts +++ b/tests/smoke/snaps/test-snap-bip-44.spec.ts @@ -5,10 +5,12 @@ import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; import Assertions from '../../framework/Assertions'; +import { Mockttp } from 'mockttp'; +import { mockBip44Snap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); -describe.skip(SmokeSnaps('BIP-44 Snap Tests'), () => { +describe(SmokeSnaps('BIP-44 Snap Tests'), () => { it('can connect to BIP-44 snap', async () => { await withFixtures( { @@ -16,6 +18,9 @@ describe.skip(SmokeSnaps('BIP-44 Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockBip44Snap(mockServer); + }, }, async () => { await loginToApp(); @@ -32,7 +37,6 @@ describe.skip(SmokeSnaps('BIP-44 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('getPublicKeyBip44Button'); @@ -49,7 +53,6 @@ describe.skip(SmokeSnaps('BIP-44 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('messageBip44Input', '1234'); @@ -68,7 +71,6 @@ describe.skip(SmokeSnaps('BIP-44 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.selectInDropdown('bip44EntropyDropDown', 'SRP 1'); @@ -88,7 +90,6 @@ describe.skip(SmokeSnaps('BIP-44 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.selectInDropdown('bip44EntropyDropDown', 'SRP 2'); @@ -108,17 +109,25 @@ describe.skip(SmokeSnaps('BIP-44 Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.selectInDropdown('bip44EntropyDropDown', 'Invalid'); await TestSnaps.fillMessage('messageBip44Input', 'foo bar'); await TestSnaps.tapButton('signMessageBip44Button'); - await Assertions.expectTextDisplayed( - 'Entropy source with ID "invalid" not found.', - { timeout: 30000 }, - ); - await TestSnaps.dismissAlert(); + // iOS shows the error as a native alert; Android renders it in the + // web-view result span as JSON with escaped quotes. + if (device.getPlatform() === 'ios') { + await Assertions.expectTextDisplayed( + 'Entropy source with ID "invalid" not found.', + { timeout: 30000 }, + ); + } else { + await TestSnaps.checkResultSpanIncludes( + 'bip44SignResultSpan', + 'Entropy source with ID', + { timeout: 30000 }, + ); + } }, ); }); diff --git a/tests/smoke/snaps/test-snap-client-status.spec.ts b/tests/smoke/snaps/test-snap-client-status.spec.ts index 7050699650f..14a1ac21701 100644 --- a/tests/smoke/snaps/test-snap-client-status.spec.ts +++ b/tests/smoke/snaps/test-snap-client-status.spec.ts @@ -6,6 +6,8 @@ import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; import sdkPackageJson from '@metamask/snaps-sdk/package.json'; import packageJson from '../../../package.json'; +import { Mockttp } from 'mockttp'; +import { mockClientStatusSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -17,6 +19,9 @@ describe(SmokeSnaps('Client Status Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockClientStatusSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -33,7 +38,6 @@ describe(SmokeSnaps('Client Status Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('sendClientStatusButton'); diff --git a/tests/smoke/snaps/test-snap-cronjob.spec.ts b/tests/smoke/snaps/test-snap-cronjob.spec.ts index 661e8628e12..255e11e867e 100644 --- a/tests/smoke/snaps/test-snap-cronjob.spec.ts +++ b/tests/smoke/snaps/test-snap-cronjob.spec.ts @@ -5,6 +5,8 @@ import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; import { Assertions } from '../../framework'; +import { Mockttp } from 'mockttp'; +import { mockCronjobSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -16,6 +18,9 @@ describe(SmokeSnaps('Cronjob Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockCronjobSnap(mockServer); + }, }, async () => { await loginToApp(); diff --git a/tests/smoke/snaps/test-snap-dialog.spec.ts b/tests/smoke/snaps/test-snap-dialog.spec.ts index 57caef21c53..add35d62998 100644 --- a/tests/smoke/snaps/test-snap-dialog.spec.ts +++ b/tests/smoke/snaps/test-snap-dialog.spec.ts @@ -7,6 +7,8 @@ import Gestures from '../../framework/Gestures'; import { Matchers } from '../../framework'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; +import { Mockttp } from 'mockttp'; +import { mockDialogSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -18,6 +20,9 @@ describe(SmokeSnaps('Dialog Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockDialogSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -35,7 +40,6 @@ describe(SmokeSnaps('Dialog Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('sendAlertButton'); @@ -56,7 +60,6 @@ describe(SmokeSnaps('Dialog Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('sendConfirmationButton'); @@ -73,7 +76,6 @@ describe(SmokeSnaps('Dialog Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('sendConfirmationButton'); @@ -92,7 +94,6 @@ describe(SmokeSnaps('Dialog Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('sendCustomButton'); diff --git a/tests/smoke/snaps/test-snap-ethereum-provider.spec.ts b/tests/smoke/snaps/test-snap-ethereum-provider.spec.ts index d09da55b93f..6f58a7d1991 100644 --- a/tests/smoke/snaps/test-snap-ethereum-provider.spec.ts +++ b/tests/smoke/snaps/test-snap-ethereum-provider.spec.ts @@ -11,6 +11,7 @@ import { Mockttp } from 'mockttp'; import { setupRemoteFeatureFlagsMock } from '../../api-mocking/helpers/remoteFeatureFlagsHelper'; import { confirmationFeatureFlags } from '../../api-mocking/mock-responses/feature-flags-mocks'; import { mockGenesisBlocks } from './mocks'; +import { mockEthereumProviderSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -28,6 +29,7 @@ describe(SmokeSnaps('Ethereum Provider Snap Tests'), () => { Object.assign({}, ...confirmationFeatureFlags), ); await mockGenesisBlocks(mockServer); + await mockEthereumProviderSnap(mockServer); }, }, async () => { diff --git a/tests/smoke/snaps/test-snap-get-entropy.spec.ts b/tests/smoke/snaps/test-snap-get-entropy.spec.ts index 6ee0b2a23ec..00f826aec9c 100644 --- a/tests/smoke/snaps/test-snap-get-entropy.spec.ts +++ b/tests/smoke/snaps/test-snap-get-entropy.spec.ts @@ -5,9 +5,32 @@ import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; import Assertions from '../../framework/Assertions'; +import { Mockttp } from 'mockttp'; +import { mockGetEntropySnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); +/** + * The account-activity mock WebSocket (started with default fixtures) keeps the + * iOS UI busy in Detox's view; disable sync for the test body so gestures and + * webview scripts are not blocked waiting for idle. Same idea as + * test-snap-network-access.spec.ts (WebSocket section). + */ +async function withIosDetoxSyncDisabledForAccountActivityWs( + fn: () => Promise, +): Promise { + if (device.getPlatform() === 'ios') { + await device.disableSynchronization(); + } + try { + return await fn(); + } finally { + if (device.getPlatform() === 'ios') { + await device.enableSynchronization(); + } + } +} + describe(SmokeSnaps('Get Entropy Snap Tests'), () => { it('connects to the Get Entropy Snap', async () => { await withFixtures( @@ -16,13 +39,18 @@ describe(SmokeSnaps('Get Entropy Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockGetEntropySnap(mockServer); + }, }, async () => { - await loginToApp(); - await navigateToBrowserView(); - await TestSnaps.navigateToTestSnap(); + await withIosDetoxSyncDisabledForAccountActivityWs(async () => { + await loginToApp(); + await navigateToBrowserView(); + await TestSnaps.navigateToTestSnap(); - await TestSnaps.installSnap('connectGetEntropyButton'); + await TestSnaps.installSnap('connectGetEntropyButton'); + }); }, ); }); @@ -32,19 +60,20 @@ describe(SmokeSnaps('Get Entropy Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { - await TestSnaps.fillMessage('entropyMessageInput', '1234'); - await TestSnaps.tapButton('signEntropyMessageButton'); - await Assertions.expectTextDisplayed('Signature request', { - description: 'Snap signature request should be visible', + await withIosDetoxSyncDisabledForAccountActivityWs(async () => { + await TestSnaps.fillMessage('entropyMessageInput', '1234'); + await TestSnaps.tapButton('signEntropyMessageButton'); + await Assertions.expectTextDisplayed('Signature request', { + description: 'Snap signature request should be visible', + }); + await TestSnaps.approveSignRequest(); + await TestSnaps.checkResultSpan( + 'entropySignResultSpan', + '"0x9341785782b512c86235612365f1076b16731ed9473beb4d0804c30b7fcc3a055aa7103b02dc64014d923220712dfbef023ddcf6327b313ea2dfd4d83dc5a53e1c5e7f4e10bce49830eded302294054df8a7a46e5b6cb3e50eec564ecba17941"', + ); }); - await TestSnaps.approveSignRequest(); - await TestSnaps.checkResultSpan( - 'entropySignResultSpan', - '"0x9341785782b512c86235612365f1076b16731ed9473beb4d0804c30b7fcc3a055aa7103b02dc64014d923220712dfbef023ddcf6327b313ea2dfd4d83dc5a53e1c5e7f4e10bce49830eded302294054df8a7a46e5b6cb3e50eec564ecba17941"', - ); }, ); }); @@ -65,20 +94,24 @@ describe(SmokeSnaps('Get Entropy Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { - await TestSnaps.selectInDropdown('getEntropyDropDown', entropySource); - await TestSnaps.fillMessage('entropyMessageInput', '5678'); - await TestSnaps.tapButton('signEntropyMessageButton'); - await Assertions.expectTextDisplayed('Signature request', { - description: 'Snap signature request should be visible', + await withIosDetoxSyncDisabledForAccountActivityWs(async () => { + await TestSnaps.selectInDropdown( + 'getEntropyDropDown', + entropySource, + ); + await TestSnaps.fillMessage('entropyMessageInput', '5678'); + await TestSnaps.tapButton('signEntropyMessageButton'); + await Assertions.expectTextDisplayed('Signature request', { + description: 'Snap signature request should be visible', + }); + await TestSnaps.approveSignRequest(); + await TestSnaps.checkResultSpan( + 'entropySignResultSpan', + `"${result}"`, + ); }); - await TestSnaps.approveSignRequest(); - await TestSnaps.checkResultSpan( - 'entropySignResultSpan', - `"${result}"`, - ); }, ); }, @@ -89,18 +122,28 @@ describe(SmokeSnaps('Get Entropy Snap Tests'), () => { { fixture: new FixtureBuilder().withMultiSRPKeyringController().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { - await TestSnaps.selectInDropdown('getEntropyDropDown', 'Invalid'); - await TestSnaps.fillMessage('entropyMessageInput', 'foo bar'); - await TestSnaps.tapButton('signEntropyMessageButton'); - await TestSnaps.approveSignRequest(); - await Assertions.expectTextDisplayed( - 'Entropy source with ID "invalid" not found.', - { timeout: 30000 }, - ); - await TestSnaps.dismissAlert(); + await withIosDetoxSyncDisabledForAccountActivityWs(async () => { + await TestSnaps.selectInDropdown('getEntropyDropDown', 'Invalid'); + await TestSnaps.fillMessage('entropyMessageInput', 'foo bar'); + await TestSnaps.tapButton('signEntropyMessageButton'); + await TestSnaps.approveSignRequest(); + // iOS shows the error as a native alert; Android renders it in the + // web-view result span as JSON with escaped quotes. + if (device.getPlatform() === 'ios') { + await Assertions.expectTextDisplayed( + 'Entropy source with ID "invalid" not found.', + { timeout: 30000 }, + ); + } else { + await TestSnaps.checkResultSpanIncludes( + 'entropySignResultSpan', + 'Entropy source with ID', + { timeout: 30000 }, + ); + } + }); }, ); }); diff --git a/tests/smoke/snaps/test-snap-get-file.spec.ts b/tests/smoke/snaps/test-snap-get-file.spec.ts index 81d73a5043f..181c462ea11 100644 --- a/tests/smoke/snaps/test-snap-get-file.spec.ts +++ b/tests/smoke/snaps/test-snap-get-file.spec.ts @@ -4,6 +4,8 @@ import { navigateToBrowserView } from '../../flows/browser.flow'; import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; +import { Mockttp } from 'mockttp'; +import { mockGetFileSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -15,6 +17,9 @@ describe(SmokeSnaps('Get File Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockGetFileSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -31,7 +36,6 @@ describe(SmokeSnaps('Get File Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('sendGetFileTextButton'); diff --git a/tests/smoke/snaps/test-snap-get-preferences.spec.ts b/tests/smoke/snaps/test-snap-get-preferences.spec.ts index d38b31316ea..01adaf20dc3 100644 --- a/tests/smoke/snaps/test-snap-get-preferences.spec.ts +++ b/tests/smoke/snaps/test-snap-get-preferences.spec.ts @@ -4,6 +4,8 @@ import TestSnaps from '../../page-objects/Browser/TestSnaps'; import { SmokeSnaps } from '../../tags'; import { loginToApp } from '../../flows/wallet.flow'; import { navigateToBrowserView } from '../../flows/browser.flow'; +import { Mockttp } from 'mockttp'; +import { mockPreferencesSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -20,6 +22,9 @@ describe(SmokeSnaps('Get Preferences Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockPreferencesSnap(mockServer); + }, }, async () => { await loginToApp(); diff --git a/tests/smoke/snaps/test-snap-image.spec.ts b/tests/smoke/snaps/test-snap-image.spec.ts index d4db368b542..0445b8dba24 100644 --- a/tests/smoke/snaps/test-snap-image.spec.ts +++ b/tests/smoke/snaps/test-snap-image.spec.ts @@ -5,6 +5,8 @@ import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; import { Assertions, Matchers } from '../../framework'; +import { Mockttp } from 'mockttp'; +import { mockImagesSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -16,6 +18,9 @@ describe(SmokeSnaps('Image Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockImagesSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -32,7 +37,6 @@ describe(SmokeSnaps('Image Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('showSVGImage'); @@ -50,7 +54,6 @@ describe(SmokeSnaps('Image Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('showPNGImage'); diff --git a/tests/smoke/snaps/test-snap-installed.spec.ts b/tests/smoke/snaps/test-snap-installed.spec.ts index 8906f2b67ae..ee3972ca67d 100644 --- a/tests/smoke/snaps/test-snap-installed.spec.ts +++ b/tests/smoke/snaps/test-snap-installed.spec.ts @@ -5,6 +5,8 @@ import { SmokeSnaps } from '../../tags'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; import { loginToApp } from '../../flows/wallet.flow'; import { navigateToBrowserView } from '../../flows/browser.flow'; +import { Mockttp } from 'mockttp'; +import { mockErrorSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -16,6 +18,9 @@ describe(SmokeSnaps('Installed Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockErrorSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -36,7 +41,6 @@ describe(SmokeSnaps('Installed Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('sendErrorButton'); diff --git a/tests/smoke/snaps/test-snap-interactive-ui.spec.ts b/tests/smoke/snaps/test-snap-interactive-ui.spec.ts index d5034746257..0d32e8c1206 100644 --- a/tests/smoke/snaps/test-snap-interactive-ui.spec.ts +++ b/tests/smoke/snaps/test-snap-interactive-ui.spec.ts @@ -7,6 +7,8 @@ import TestSnaps from '../../page-objects/Browser/TestSnaps'; import { Assertions } from '../../framework'; import Matchers from '../../framework/Matchers'; import { DateTime } from 'luxon'; +import { Mockttp } from 'mockttp'; +import { mockInteractiveUiSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -18,6 +20,9 @@ describe(SmokeSnaps('Interactive UI Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockInteractiveUiSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -34,7 +39,6 @@ describe(SmokeSnaps('Interactive UI Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('createDialogButton'); @@ -80,7 +84,6 @@ describe(SmokeSnaps('Interactive UI Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('createDialogDisabledButton'); diff --git a/tests/smoke/snaps/test-snap-jsx.spec.ts b/tests/smoke/snaps/test-snap-jsx.spec.ts index b831098ec81..261f70e2639 100644 --- a/tests/smoke/snaps/test-snap-jsx.spec.ts +++ b/tests/smoke/snaps/test-snap-jsx.spec.ts @@ -5,6 +5,8 @@ import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; import { Assertions, Gestures, Matchers } from '../../framework'; +import { Mockttp } from 'mockttp'; +import { mockJsxSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -16,6 +18,9 @@ describe(SmokeSnaps('JSX Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockJsxSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -32,7 +37,6 @@ describe(SmokeSnaps('JSX Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('displayJsxButton'); diff --git a/tests/smoke/snaps/test-snap-lifecycle.spec.ts b/tests/smoke/snaps/test-snap-lifecycle.spec.ts index 7f766131c39..261fd6350c1 100644 --- a/tests/smoke/snaps/test-snap-lifecycle.spec.ts +++ b/tests/smoke/snaps/test-snap-lifecycle.spec.ts @@ -5,6 +5,8 @@ import { SmokeSnaps } from '../../tags'; import Assertions from '../../framework/Assertions'; import { loginToApp } from '../../flows/wallet.flow'; import { navigateToBrowserView } from '../../flows/browser.flow'; +import { Mockttp } from 'mockttp'; +import { mockLifecycleHooksSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -16,6 +18,9 @@ describe(SmokeSnaps('Lifecycle hooks Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockLifecycleHooksSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -39,7 +44,6 @@ describe(SmokeSnaps('Lifecycle hooks Snap Tests'), () => { .build(), restartDevice: true, skipReactNativeReload: true, - disableSynchronization: true, }, async () => { try { diff --git a/tests/smoke/snaps/test-snap-manage-state.spec.ts b/tests/smoke/snaps/test-snap-manage-state.spec.ts index 1fd372d7fca..0be7ce03871 100644 --- a/tests/smoke/snaps/test-snap-manage-state.spec.ts +++ b/tests/smoke/snaps/test-snap-manage-state.spec.ts @@ -4,6 +4,8 @@ import { navigateToBrowserView } from '../../flows/browser.flow'; import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; +import { Mockttp } from 'mockttp'; +import { mockManageStateSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -15,6 +17,9 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockManageStateSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -33,7 +38,6 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('dataStateInput', '"bar"'); @@ -55,7 +59,6 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('clearStateButton'); @@ -71,7 +74,6 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('dataUnencryptedStateInput', '"bar"'); @@ -96,7 +98,6 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('clearStateUnencryptedButton'); @@ -117,7 +118,6 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('dataManageStateInput', '23'); @@ -138,7 +138,6 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('clearManageStateButton'); @@ -160,7 +159,6 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage( @@ -181,7 +179,6 @@ describe(SmokeSnaps('Manage State Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.tapButton('clearUnencryptedManageStateButton'); diff --git a/tests/smoke/snaps/test-snap-management.spec.ts b/tests/smoke/snaps/test-snap-management.spec.ts index b39d0cda6b4..57e80e0c7da 100644 --- a/tests/smoke/snaps/test-snap-management.spec.ts +++ b/tests/smoke/snaps/test-snap-management.spec.ts @@ -10,6 +10,8 @@ import SnapSettingsView from '../../page-objects/Settings/SnapSettingsView'; import { Assertions } from '../../framework'; import BrowserView from '../../page-objects/Browser/BrowserView'; import AccountMenu from '../../page-objects/AccountMenu/AccountMenu'; +import { Mockttp } from 'mockttp'; +import { mockDialogSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -21,6 +23,9 @@ describe(SmokeSnaps('Snap Management Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockDialogSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -37,7 +42,6 @@ describe(SmokeSnaps('Snap Management Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await BrowserView.tapCloseBrowserButton(); @@ -70,7 +74,6 @@ describe(SmokeSnaps('Snap Management Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await BrowserView.tapCloseBrowserButton(); @@ -104,7 +107,6 @@ describe(SmokeSnaps('Snap Management Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await BrowserView.tapCloseBrowserButton(); diff --git a/tests/smoke/snaps/test-snap-multichain-provider.spec.ts b/tests/smoke/snaps/test-snap-multichain-provider.spec.ts index 319afc3fd64..3d6fa81523e 100644 --- a/tests/smoke/snaps/test-snap-multichain-provider.spec.ts +++ b/tests/smoke/snaps/test-snap-multichain-provider.spec.ts @@ -11,6 +11,7 @@ import { Mockttp } from 'mockttp'; import { setupRemoteFeatureFlagsMock } from '../../api-mocking/helpers/remoteFeatureFlagsHelper'; import { confirmationFeatureFlags } from '../../api-mocking/mock-responses/feature-flags-mocks'; import { mockGenesisBlocks } from './mocks'; +import { mockMultichainProviderSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -28,6 +29,7 @@ describe(SmokeSnaps('Multichain Provider Snap Tests'), () => { Object.assign({}, ...confirmationFeatureFlags), ); await mockGenesisBlocks(mockServer); + await mockMultichainProviderSnap(mockServer); }, }, async () => { diff --git a/tests/smoke/snaps/test-snap-name-lookup.spec.ts b/tests/smoke/snaps/test-snap-name-lookup.spec.ts index 8ac3cd61bb2..dd15e572a87 100644 --- a/tests/smoke/snaps/test-snap-name-lookup.spec.ts +++ b/tests/smoke/snaps/test-snap-name-lookup.spec.ts @@ -12,6 +12,8 @@ import BrowserView from '../../page-objects/Browser/BrowserView'; import TransactionConfirmView from '../../page-objects/Send/TransactionConfirmView'; import TokenOverview from '../../page-objects/wallet/TokenOverview'; import NetworkListModal from '../../page-objects/Network/NetworkListModal'; +import { Mockttp } from 'mockttp'; +import { mockNameLookupSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -25,6 +27,9 @@ describe(SmokeSnaps('Name Lookup Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockNameLookupSnap(mockServer); + }, }, async () => { await loginToApp(); diff --git a/tests/smoke/snaps/test-snap-network-access.spec.ts b/tests/smoke/snaps/test-snap-network-access.spec.ts index e6fb95b598d..3166a1d7b6a 100644 --- a/tests/smoke/snaps/test-snap-network-access.spec.ts +++ b/tests/smoke/snaps/test-snap-network-access.spec.ts @@ -7,6 +7,8 @@ import TestSnaps from '../../page-objects/Browser/TestSnaps'; import { getAnvilPortForTest } from '../../framework/fixtures/FixtureUtils'; import { LocalNodeType } from '../../framework'; import { defaultOptions } from '../../seeder/anvil-manager'; +import { Mockttp } from 'mockttp'; +import { mockNetworkSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -27,6 +29,9 @@ describe(SmokeSnaps('Network Access Snap Tests'), () => { }, }, ], + testSpecificMock: async (mockServer: Mockttp) => { + await mockNetworkSnap(mockServer); + }, }, async () => { await loginToApp(); diff --git a/tests/smoke/snaps/test-snap-rpc.spec.ts b/tests/smoke/snaps/test-snap-rpc.spec.ts index e46d522c612..2e88191611d 100644 --- a/tests/smoke/snaps/test-snap-rpc.spec.ts +++ b/tests/smoke/snaps/test-snap-rpc.spec.ts @@ -4,6 +4,11 @@ import { SmokeSnaps } from '../../tags'; import { loginToApp } from '../../flows/wallet.flow'; import { navigateToBrowserView } from '../../flows/browser.flow'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; +import { Mockttp } from 'mockttp'; +import { + mockBip32Snap, + mockJsonRpcSnap, +} from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -15,6 +20,10 @@ describe(SmokeSnaps('Snap RPC Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockBip32Snap(mockServer); + await mockJsonRpcSnap(mockServer); + }, }, async () => { await loginToApp(); diff --git a/tests/smoke/snaps/test-snap-uilinks.spec.ts b/tests/smoke/snaps/test-snap-uilinks.spec.ts index 48f5f7b673a..4341fbc0bc6 100644 --- a/tests/smoke/snaps/test-snap-uilinks.spec.ts +++ b/tests/smoke/snaps/test-snap-uilinks.spec.ts @@ -5,6 +5,8 @@ import { SmokeSnaps } from '../../tags'; import { loginToApp } from '../../flows/wallet.flow'; import { navigateToBrowserView } from '../../flows/browser.flow'; import { Assertions, Matchers } from '../../framework'; +import { Mockttp } from 'mockttp'; +import { mockDialogSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -16,6 +18,9 @@ describe(SmokeSnaps('UI Links Snap Test'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockDialogSnap(mockServer); + }, }, async () => { await loginToApp(); diff --git a/tests/smoke/snaps/test-snap-wasm.spec.ts b/tests/smoke/snaps/test-snap-wasm.spec.ts index cbf0c43c32f..8cab441cbe2 100644 --- a/tests/smoke/snaps/test-snap-wasm.spec.ts +++ b/tests/smoke/snaps/test-snap-wasm.spec.ts @@ -4,6 +4,8 @@ import { navigateToBrowserView } from '../../flows/browser.flow'; import FixtureBuilder from '../../framework/fixtures/FixtureBuilder'; import { withFixtures } from '../../framework/fixtures/FixtureHelper'; import TestSnaps from '../../page-objects/Browser/TestSnaps'; +import { Mockttp } from 'mockttp'; +import { mockWasmSnap } from '../../api-mocking/mock-response-data/snaps/snap-binary-mocks'; jest.setTimeout(150_000); @@ -15,6 +17,9 @@ describe(SmokeSnaps('WASM Snap Tests'), () => { restartDevice: true, skipReactNativeReload: true, disableSynchronization: true, + testSpecificMock: async (mockServer: Mockttp) => { + await mockWasmSnap(mockServer); + }, }, async () => { await loginToApp(); @@ -31,7 +36,6 @@ describe(SmokeSnaps('WASM Snap Tests'), () => { { fixture: new FixtureBuilder().build(), skipReactNativeReload: true, - disableSynchronization: true, }, async () => { await TestSnaps.fillMessage('wasmInput', '23');