1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

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
This commit is contained in:
PeterYinusa 2022-03-15 13:17:48 -03:00 committed by GitHub
parent 524ddcfaf4
commit c07e477c13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 188 deletions

View File

@ -56,9 +56,6 @@ workflows:
- prep-build-test-flask: - prep-build-test-flask:
requires: requires:
- prep-deps - prep-deps
- prep-build-test-metrics:
requires:
- prep-deps
- test-storybook: - test-storybook:
requires: requires:
- prep-deps - prep-deps
@ -87,12 +84,6 @@ workflows:
- test-e2e-firefox-snaps: - test-e2e-firefox-snaps:
requires: requires:
- prep-build-test-flask - prep-build-test-flask
- test-e2e-chrome-metrics:
requires:
- prep-build-test-metrics
- test-e2e-firefox-metrics:
requires:
- prep-build-test-metrics
- test-unit: - test-unit:
requires: requires:
- prep-deps - prep-deps
@ -137,8 +128,6 @@ workflows:
- test-mozilla-lint-flask - test-mozilla-lint-flask
- test-e2e-chrome - test-e2e-chrome
- test-e2e-firefox - test-e2e-firefox
- test-e2e-chrome-metrics
- test-e2e-firefox-metrics
- test-e2e-chrome-snaps - test-e2e-chrome-snaps
- test-e2e-firefox-snaps - test-e2e-firefox-snaps
- benchmark: - benchmark:
@ -338,27 +327,6 @@ jobs:
- dist-test - dist-test
- builds-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: prep-build-storybook:
executor: node-browsers executor: node-browsers
steps: steps:
@ -553,33 +521,6 @@ jobs:
path: test-artifacts path: test-artifacts
destination: 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: test-e2e-firefox:
executor: node-browsers-medium-plus executor: node-browsers-medium-plus
steps: steps:
@ -607,33 +548,6 @@ jobs:
path: test-artifacts path: test-artifacts
destination: 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: benchmark:
executor: node-browsers-medium-plus executor: node-browsers-medium-plus
steps: steps:

View File

@ -1,8 +1,8 @@
import Analytics from 'analytics-node'; import Analytics from 'analytics-node';
import { SECOND } from '../../../shared/constants/time'; import { SECOND } from '../../../shared/constants/time';
const isDevOrTestEnvironment = Boolean( const isDevEnvironment = Boolean(
process.env.METAMASK_DEBUG || process.env.IN_TEST, process.env.METAMASK_DEBUG && !process.env.IN_TEST,
); );
const SEGMENT_WRITE_KEY = process.env.SEGMENT_WRITE_KEY ?? null; const SEGMENT_WRITE_KEY = process.env.SEGMENT_WRITE_KEY ?? null;
const SEGMENT_HOST = process.env.SEGMENT_HOST ?? null; const SEGMENT_HOST = process.env.SEGMENT_HOST ?? null;
@ -82,7 +82,7 @@ export const createSegmentMock = (flushAt = SEGMENT_FLUSH_AT) => {
}; };
export const segment = export const segment =
!SEGMENT_WRITE_KEY || (isDevOrTestEnvironment && !SEGMENT_HOST) !SEGMENT_WRITE_KEY || (isDevEnvironment && !SEGMENT_HOST)
? createSegmentMock(SEGMENT_FLUSH_AT, SEGMENT_FLUSH_INTERVAL) ? createSegmentMock(SEGMENT_FLUSH_AT, SEGMENT_FLUSH_INTERVAL)
: new Analytics(SEGMENT_WRITE_KEY, { : new Analytics(SEGMENT_WRITE_KEY, {
host: SEGMENT_HOST, host: SEGMENT_HOST,

View File

@ -14,12 +14,11 @@
"dist": "yarn build prod", "dist": "yarn build prod",
"build": "yarn lavamoat:build", "build": "yarn lavamoat:build",
"build:dev": "node development/build/index.js", "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:chrome": "SELENIUM_BROWSER=chrome node test/e2e/benchmark.js",
"benchmark:firefox": "SELENIUM_BROWSER=firefox 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: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", "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": "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'", "dapp-chain": "GANACHE_ARGS='-b 2' concurrently -k -n ganache,dapp -p '[{time}][{name}]' 'yarn ganache:start' 'sleep 5 && yarn dapp'",

View File

@ -1,13 +1,9 @@
const path = require('path'); const path = require('path');
const sinon = require('sinon');
const BigNumber = require('bignumber.js'); const BigNumber = require('bignumber.js');
const mockttp = require('mockttp'); const mockttp = require('mockttp');
const createStaticServer = require('../../development/create-static-server'); 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 enLocaleMessages = require('../../app/_locales/en/messages.json');
const { setupMocking } = require('./mock-e2e');
const Ganache = require('./ganache'); const Ganache = require('./ganache');
const FixtureServer = require('./fixture-server'); const FixtureServer = require('./fixture-server');
const { buildWebDriver } = require('./webdriver'); const { buildWebDriver } = require('./webdriver');
@ -27,7 +23,6 @@ async function withFixtures(options, testSuite) {
fixtures, fixtures,
ganacheOptions, ganacheOptions,
driverOptions, driverOptions,
mockSegment,
title, title,
failOnConsoleError = true, failOnConsoleError = true,
dappPath = undefined, dappPath = undefined,
@ -38,11 +33,9 @@ async function withFixtures(options, testSuite) {
const fixtureServer = new FixtureServer(); const fixtureServer = new FixtureServer();
const ganacheServer = new Ganache(); const ganacheServer = new Ganache();
const https = await mockttp.generateCACertificate(); const https = await mockttp.generateCACertificate();
const mockServer = mockttp.getLocal({ https }); const mockServer = mockttp.getLocal({ https, cors: true });
let secondaryGanacheServer; let secondaryGanacheServer;
let dappServer; let dappServer;
let segmentServer;
let segmentStub;
let webDriver; let webDriver;
let failed = false; let failed = false;
@ -82,17 +75,6 @@ async function withFixtures(options, testSuite) {
dappServer.on('error', reject); 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 setupMocking(mockServer, testSpecificMock);
await mockServer.start(8000); await mockServer.start(8000);
if ( if (
@ -106,7 +88,6 @@ async function withFixtures(options, testSuite) {
await testSuite({ await testSuite({
driver, driver,
segmentStub,
mockServer, mockServer,
}); });
@ -154,9 +135,6 @@ async function withFixtures(options, testSuite) {
}); });
}); });
} }
if (segmentServer) {
await segmentServer.stop();
}
await mockServer.stop(); await mockServer.stop();
} }
} }

View File

@ -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, '/');
},
);
});
});

View File

@ -1,24 +1,10 @@
async function setupMocking(server, testSpecificMock) { async function setupMocking(server, testSpecificMock) {
await server.forAnyRequest().thenPassThrough(); 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 await server
.forGet('https://gas-api.metaswap.codefi.network/networks/1/gasPrices') .forGet('https://gas-api.metaswap.codefi.network/networks/1/gasPrices')
.thenCallback(() => { .thenCallback(() => {
return { return {
headers: { 'Access-Control-Allow-Origin': '*' },
statusCode: 200, statusCode: 200,
json: { json: {
SafeGasPrice: '1', 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); testSpecificMock(server);
} }

View File

@ -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, '/');
},
);
});
});

View File

@ -10,7 +10,6 @@ describe('Phishing Detection', function () {
) )
.thenCallback(() => { .thenCallback(() => {
return { return {
headers: { 'Access-Control-Allow-Origin': '*' },
statusCode: 200, statusCode: 200,
json: { json: {
version: 2, version: 2,