From c07e477c1377da5555e8c55623d9eeed3b1b115b Mon Sep 17 00:00:00 2001 From: PeterYinusa <53189696+PeterYinusa@users.noreply.github.com> Date: Tue, 15 Mar 2022 13:17:48 -0300 Subject: [PATCH] E2e metrics (#13904) * remove metrics build * remove segment server from tests * enable cors * mock segment globally * metrics e2e test * running test builds * move file * destructuring --- .circleci/config.yml | 86 ----------------------- app/scripts/lib/segment.js | 6 +- package.json | 5 +- test/e2e/helpers.js | 26 +------ test/e2e/metrics.spec.js | 57 --------------- {development => test/e2e}/mock-e2e.js | 20 ++---- test/e2e/tests/metrics.spec.js | 61 ++++++++++++++++ test/e2e/tests/phishing-detection.spec.js | 1 - 8 files changed, 74 insertions(+), 188 deletions(-) delete mode 100644 test/e2e/metrics.spec.js rename {development => test/e2e}/mock-e2e.js (50%) create mode 100644 test/e2e/tests/metrics.spec.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 76992feca..bf6513533 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -56,9 +56,6 @@ workflows: - prep-build-test-flask: requires: - prep-deps - - prep-build-test-metrics: - requires: - - prep-deps - test-storybook: requires: - prep-deps @@ -87,12 +84,6 @@ workflows: - test-e2e-firefox-snaps: requires: - prep-build-test-flask - - test-e2e-chrome-metrics: - requires: - - prep-build-test-metrics - - test-e2e-firefox-metrics: - requires: - - prep-build-test-metrics - test-unit: requires: - prep-deps @@ -137,8 +128,6 @@ workflows: - test-mozilla-lint-flask - test-e2e-chrome - test-e2e-firefox - - test-e2e-chrome-metrics - - test-e2e-firefox-metrics - test-e2e-chrome-snaps - test-e2e-firefox-snaps - benchmark: @@ -338,27 +327,6 @@ jobs: - dist-test - builds-test - prep-build-test-metrics: - executor: node-browsers-medium-plus - steps: - - checkout - - attach_workspace: - at: . - - run: - name: Build extension for testing metrics - command: yarn build:test:metrics - - run: - name: Move test build to 'dist-test-metrics' to avoid conflict with production build - command: mv ./dist ./dist-test-metrics - - run: - name: Move test zips to 'builds-test' to avoid conflict with production build - command: mv ./builds ./builds-test-metrics - - persist_to_workspace: - root: . - paths: - - dist-test-metrics - - builds-test-metrics - prep-build-storybook: executor: node-browsers steps: @@ -553,33 +521,6 @@ jobs: path: test-artifacts destination: test-artifacts - test-e2e-chrome-metrics: - executor: node-browsers - steps: - - checkout - - run: - name: Re-Install Chrome - command: ./.circleci/scripts/chrome-install.sh - - attach_workspace: - at: . - - run: - name: Move test build to dist - command: mv ./dist-test-metrics ./dist - - run: - name: Move test zips to builds - command: mv ./builds-test-metrics ./builds - - run: - name: test:e2e:chrome:metrics - command: | - if .circleci/scripts/test-run-e2e.sh - then - yarn test:e2e:chrome:metrics --retries 2 - fi - no_output_timeout: 20m - - store_artifacts: - path: test-artifacts - destination: test-artifacts - test-e2e-firefox: executor: node-browsers-medium-plus steps: @@ -607,33 +548,6 @@ jobs: path: test-artifacts destination: test-artifacts - test-e2e-firefox-metrics: - executor: node-browsers - steps: - - checkout - - run: - name: Install Firefox - command: ./.circleci/scripts/firefox-install.sh - - attach_workspace: - at: . - - run: - name: Move test build to dist - command: mv ./dist-test-metrics ./dist - - run: - name: Move test zips to builds - command: mv ./builds-test-metrics ./builds - - run: - name: test:e2e:firefox:metrics - command: | - if .circleci/scripts/test-run-e2e.sh - then - yarn test:e2e:firefox:metrics --retries 2 - fi - no_output_timeout: 20m - - store_artifacts: - path: test-artifacts - destination: test-artifacts - benchmark: executor: node-browsers-medium-plus steps: diff --git a/app/scripts/lib/segment.js b/app/scripts/lib/segment.js index 3b7db70ce..bb52c42d8 100644 --- a/app/scripts/lib/segment.js +++ b/app/scripts/lib/segment.js @@ -1,8 +1,8 @@ import Analytics from 'analytics-node'; import { SECOND } from '../../../shared/constants/time'; -const isDevOrTestEnvironment = Boolean( - process.env.METAMASK_DEBUG || process.env.IN_TEST, +const isDevEnvironment = Boolean( + process.env.METAMASK_DEBUG && !process.env.IN_TEST, ); const SEGMENT_WRITE_KEY = process.env.SEGMENT_WRITE_KEY ?? null; const SEGMENT_HOST = process.env.SEGMENT_HOST ?? null; @@ -82,7 +82,7 @@ export const createSegmentMock = (flushAt = SEGMENT_FLUSH_AT) => { }; export const segment = - !SEGMENT_WRITE_KEY || (isDevOrTestEnvironment && !SEGMENT_HOST) + !SEGMENT_WRITE_KEY || (isDevEnvironment && !SEGMENT_HOST) ? createSegmentMock(SEGMENT_FLUSH_AT, SEGMENT_FLUSH_INTERVAL) : new Analytics(SEGMENT_WRITE_KEY, { host: SEGMENT_HOST, diff --git a/package.json b/package.json index 0ef86bc43..1fd4c6a12 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,11 @@ "dist": "yarn build prod", "build": "yarn lavamoat:build", "build:dev": "node development/build/index.js", - "start:test": "yarn build testDev", + "start:test": "SEGMENT_HOST='https://api.segment.io' SEGMENT_WRITE_KEY='FAKE' yarn build testDev", "benchmark:chrome": "SELENIUM_BROWSER=chrome node test/e2e/benchmark.js", "benchmark:firefox": "SELENIUM_BROWSER=firefox node test/e2e/benchmark.js", - "build:test": "yarn build test", + "build:test": "SEGMENT_HOST='https://api.segment.io' SEGMENT_WRITE_KEY='FAKE' yarn build test", "build:test:flask": "yarn build test --build-type flask", - "build:test:metrics": "SEGMENT_HOST='http://localhost:9090' SEGMENT_WRITE_KEY='FAKE' yarn build test", "test": "yarn lint && yarn test:unit && yarn test:unit:jest", "dapp": "node development/static-server.js node_modules/@metamask/test-dapp/dist --port 8080", "dapp-chain": "GANACHE_ARGS='-b 2' concurrently -k -n ganache,dapp -p '[{time}][{name}]' 'yarn ganache:start' 'sleep 5 && yarn dapp'", diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 3d8e46f4a..fc4b1d8db 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -1,13 +1,9 @@ const path = require('path'); -const sinon = require('sinon'); const BigNumber = require('bignumber.js'); const mockttp = require('mockttp'); const createStaticServer = require('../../development/create-static-server'); -const { - createSegmentServer, -} = require('../../development/lib/create-segment-server'); -const { setupMocking } = require('../../development/mock-e2e'); const enLocaleMessages = require('../../app/_locales/en/messages.json'); +const { setupMocking } = require('./mock-e2e'); const Ganache = require('./ganache'); const FixtureServer = require('./fixture-server'); const { buildWebDriver } = require('./webdriver'); @@ -27,7 +23,6 @@ async function withFixtures(options, testSuite) { fixtures, ganacheOptions, driverOptions, - mockSegment, title, failOnConsoleError = true, dappPath = undefined, @@ -38,11 +33,9 @@ async function withFixtures(options, testSuite) { const fixtureServer = new FixtureServer(); const ganacheServer = new Ganache(); const https = await mockttp.generateCACertificate(); - const mockServer = mockttp.getLocal({ https }); + const mockServer = mockttp.getLocal({ https, cors: true }); let secondaryGanacheServer; let dappServer; - let segmentServer; - let segmentStub; let webDriver; let failed = false; @@ -82,17 +75,6 @@ async function withFixtures(options, testSuite) { dappServer.on('error', reject); }); } - if (mockSegment) { - segmentStub = sinon.stub(); - segmentServer = createSegmentServer((_request, response, events) => { - for (const event of events) { - segmentStub(event); - } - response.statusCode = 200; - response.end(); - }); - await segmentServer.start(9090); - } await setupMocking(mockServer, testSpecificMock); await mockServer.start(8000); if ( @@ -106,7 +88,6 @@ async function withFixtures(options, testSuite) { await testSuite({ driver, - segmentStub, mockServer, }); @@ -154,9 +135,6 @@ async function withFixtures(options, testSuite) { }); }); } - if (segmentServer) { - await segmentServer.stop(); - } await mockServer.stop(); } } diff --git a/test/e2e/metrics.spec.js b/test/e2e/metrics.spec.js deleted file mode 100644 index 141b56192..000000000 --- a/test/e2e/metrics.spec.js +++ /dev/null @@ -1,57 +0,0 @@ -const { strict: assert } = require('assert'); -const waitUntilCalled = require('../lib/wait-until-called'); -const { convertToHexValue, withFixtures, tinyDelayMs } = require('./helpers'); - -/** - * WARNING: These tests must be run using a build created with `yarn build:test:metrics`, so that it has - * the correct Segment host and write keys set. Otherwise this test will fail. - */ -describe('Segment metrics', function () { - this.timeout(0); - - it('should send first three Page metric events upon fullscreen page load', async function () { - const ganacheOptions = { - accounts: [ - { - secretKey: - '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', - balance: convertToHexValue(25000000000000000000), - }, - ], - }; - await withFixtures( - { - fixtures: 'metrics-enabled', - ganacheOptions, - title: this.test.title, - mockSegment: true, - }, - async ({ driver, segmentStub }) => { - const threeSegmentEventsReceived = waitUntilCalled(segmentStub, null, { - callCount: 3, - }); - await driver.delay(tinyDelayMs); - await driver.navigate(); - - await driver.fill('#password', 'correct horse battery staple'); - await driver.press('#password', driver.Key.ENTER); - - await threeSegmentEventsReceived(); - - assert.ok(segmentStub.called, 'Segment should receive metrics'); - - const firstSegmentEvent = segmentStub.getCall(0).args[0]; - assert.equal(firstSegmentEvent.name, 'Home'); - assert.equal(firstSegmentEvent.context.page.path, '/'); - - const secondSegmentEvent = segmentStub.getCall(1).args[0]; - assert.equal(secondSegmentEvent.name, 'Unlock Page'); - assert.equal(secondSegmentEvent.context.page.path, '/unlock'); - - const thirdSegmentEvent = segmentStub.getCall(2).args[0]; - assert.equal(thirdSegmentEvent.name, 'Home'); - assert.equal(thirdSegmentEvent.context.page.path, '/'); - }, - ); - }); -}); diff --git a/development/mock-e2e.js b/test/e2e/mock-e2e.js similarity index 50% rename from development/mock-e2e.js rename to test/e2e/mock-e2e.js index 4fde023d5..012115e74 100644 --- a/development/mock-e2e.js +++ b/test/e2e/mock-e2e.js @@ -1,24 +1,10 @@ async function setupMocking(server, testSpecificMock) { await server.forAnyRequest().thenPassThrough(); - await server - .forOptions('https://gas-api.metaswap.codefi.network/networks/1/gasPrices') - .thenCallback(() => { - return { - headers: { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - 'Access-Control-Allow-Headers': 'content-type,x-client-id', - }, - statusCode: 200, - }; - }); - await server .forGet('https://gas-api.metaswap.codefi.network/networks/1/gasPrices') .thenCallback(() => { return { - headers: { 'Access-Control-Allow-Origin': '*' }, statusCode: 200, json: { SafeGasPrice: '1', @@ -28,6 +14,12 @@ async function setupMocking(server, testSpecificMock) { }; }); + await server.forPost('https://api.segment.io/v1/batch').thenCallback(() => { + return { + statusCode: 200, + }; + }); + testSpecificMock(server); } diff --git a/test/e2e/tests/metrics.spec.js b/test/e2e/tests/metrics.spec.js new file mode 100644 index 000000000..e7bfe3842 --- /dev/null +++ b/test/e2e/tests/metrics.spec.js @@ -0,0 +1,61 @@ +const { strict: assert } = require('assert'); +const { convertToHexValue, withFixtures } = require('../helpers'); + +describe('Segment metrics', function () { + async function mockSegment(mockServer) { + mockServer.reset(); + await mockServer.forAnyRequest().thenPassThrough(); + return await mockServer + .forPost('https://api.segment.io/v1/batch') + .withJsonBodyIncluding({ batch: [{ type: 'page' }] }) + .times(3) + .thenCallback(() => { + return { + statusCode: 200, + }; + }); + } + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: convertToHexValue(25000000000000000000), + }, + ], + }; + it('should send first three Page metric events upon fullscreen page load', async function () { + await withFixtures( + { + fixtures: 'metrics-enabled', + ganacheOptions, + title: this.test.title, + }, + async ({ driver, mockServer }) => { + const mockedEndpoints = await mockSegment(mockServer); + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + await driver.wait(async () => { + const isPending = await mockedEndpoints.isPending(); + return isPending === false; + }, 10000); + const mockedRequests = await mockedEndpoints.getSeenRequests(); + assert.equal(mockedRequests.length, 3); + const [firstMock, secondMock, thirdMock] = mockedRequests; + let [mockJson] = firstMock.body.json.batch; + let { title, path } = mockJson.context.page; + assert.equal(title, 'Home'); + assert.equal(path, '/'); + [mockJson] = secondMock.body.json.batch; + ({ title, path } = mockJson.context.page); + assert.equal(title, 'Unlock Page'); + assert.equal(path, '/unlock'); + [mockJson] = thirdMock.body.json.batch; + ({ title, path } = mockJson.context.page); + assert.equal(title, 'Home'); + assert.equal(path, '/'); + }, + ); + }); +}); diff --git a/test/e2e/tests/phishing-detection.spec.js b/test/e2e/tests/phishing-detection.spec.js index a198de3c0..1e6095343 100644 --- a/test/e2e/tests/phishing-detection.spec.js +++ b/test/e2e/tests/phishing-detection.spec.js @@ -10,7 +10,6 @@ describe('Phishing Detection', function () { ) .thenCallback(() => { return { - headers: { 'Access-Control-Allow-Origin': '*' }, statusCode: 200, json: { version: 2,