mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Fixed firefox Snaps + add initial end-to-end tests (#13671)
* Changed registryUrl for snaps only in firefox Fixed getPlatform to only be imported into metamask-controller in flask Removed snaps specific testrunner script and use run-all with a cli option * Fixed flakey tests * Removed unneeded await * Added delay * Fixed linting
This commit is contained in:
parent
0e41bd4399
commit
1f55af3151
@ -53,6 +53,9 @@ workflows:
|
||||
- prep-build-test:
|
||||
requires:
|
||||
- prep-deps
|
||||
- prep-build-test-flask:
|
||||
requires:
|
||||
- prep-deps
|
||||
- prep-build-test-metrics:
|
||||
requires:
|
||||
- prep-deps
|
||||
@ -78,6 +81,12 @@ workflows:
|
||||
- test-e2e-firefox:
|
||||
requires:
|
||||
- prep-build-test
|
||||
- test-e2e-chrome-snaps:
|
||||
requires:
|
||||
- prep-build-test-flask
|
||||
- test-e2e-firefox-snaps:
|
||||
requires:
|
||||
- prep-build-test-flask
|
||||
- test-e2e-chrome-metrics:
|
||||
requires:
|
||||
- prep-build-test-metrics
|
||||
@ -130,6 +139,8 @@ workflows:
|
||||
- test-e2e-firefox
|
||||
- test-e2e-chrome-metrics
|
||||
- test-e2e-firefox-metrics
|
||||
- test-e2e-chrome-snaps
|
||||
- test-e2e-firefox-snaps
|
||||
- benchmark:
|
||||
requires:
|
||||
- prep-build-test
|
||||
@ -283,6 +294,28 @@ jobs:
|
||||
- dist-flask
|
||||
- builds-flask
|
||||
|
||||
prep-build-test-flask:
|
||||
executor: node-browsers-medium-plus
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Build extension for testing
|
||||
command: yarn build:test:flask
|
||||
- run:
|
||||
name: Move test build to 'dist-test' to avoid conflict with production build
|
||||
command: mv ./dist ./dist-test-flask
|
||||
- run:
|
||||
name: Move test zips to 'builds-test' to avoid conflict with production build
|
||||
command: mv ./builds ./builds-test-flask
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- dist-test-flask
|
||||
- builds-test-flask
|
||||
|
||||
|
||||
prep-build-test:
|
||||
executor: node-browsers-medium-plus
|
||||
steps:
|
||||
@ -465,6 +498,60 @@ jobs:
|
||||
path: test-artifacts
|
||||
destination: test-artifacts
|
||||
|
||||
test-e2e-firefox-snaps:
|
||||
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-flask ./dist
|
||||
- run:
|
||||
name: Move test zips to builds
|
||||
command: mv ./builds-test-flask ./builds
|
||||
- run:
|
||||
name: test:e2e:firefox:snaps
|
||||
command: |
|
||||
if .circleci/scripts/test-run-e2e.sh
|
||||
then
|
||||
yarn test:e2e:firefox:snaps --retries 2
|
||||
fi
|
||||
no_output_timeout: 20m
|
||||
- store_artifacts:
|
||||
path: test-artifacts
|
||||
destination: test-artifacts
|
||||
|
||||
test-e2e-chrome-snaps:
|
||||
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-flask ./dist
|
||||
- run:
|
||||
name: Move test zips to builds
|
||||
command: mv ./builds-test-flask ./builds
|
||||
- run:
|
||||
name: test:e2e:chrome:snaps
|
||||
command: |
|
||||
if .circleci/scripts/test-run-e2e.sh
|
||||
then
|
||||
yarn test:e2e:chrome:snaps --retries 2
|
||||
fi
|
||||
no_output_timeout: 20m
|
||||
- store_artifacts:
|
||||
path: test-artifacts
|
||||
destination: test-artifacts
|
||||
|
||||
test-e2e-chrome-metrics:
|
||||
executor: node-browsers
|
||||
steps:
|
||||
|
@ -74,6 +74,7 @@ import { MILLISECOND } from '../../shared/constants/time';
|
||||
import {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
MESSAGE_TYPE,
|
||||
PLATFORM_FIREFOX,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
POLLING_TOKEN_ENVIRONMENT_TYPES,
|
||||
SUBJECT_TYPES,
|
||||
@ -134,6 +135,10 @@ import {
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} from './controllers/permissions';
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
import { getPlatform } from './lib/util';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
export const METAMASK_CONTROLLER_EVENTS = {
|
||||
// Fired after state changes that impact the extension badge (unapproved msg count)
|
||||
// The process of updating the badge happens in app/scripts/background.js.
|
||||
@ -607,7 +612,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
],
|
||||
});
|
||||
|
||||
const usingFirefox = getPlatform() === PLATFORM_FIREFOX;
|
||||
|
||||
this.snapController = new SnapController({
|
||||
npmRegistryUrl: usingFirefox ? 'https://registry.npmjs.cf/' : undefined,
|
||||
endowmentPermissionNames: Object.values(EndowmentPermissions),
|
||||
terminateAllSnaps: this.workerController.terminateAllSnaps.bind(
|
||||
this.workerController,
|
||||
|
@ -18,6 +18,7 @@
|
||||
"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: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",
|
||||
@ -30,8 +31,10 @@
|
||||
"test:unit:mocha": "mocha './app/**/*.test.js'",
|
||||
"test:e2e:chrome": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js",
|
||||
"test:e2e:chrome:metrics": "SELENIUM_BROWSER=chrome node test/e2e/run-e2e-test.js test/e2e/metrics.spec.js",
|
||||
"test:e2e:chrome:snaps": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js --snaps",
|
||||
"test:e2e:firefox": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js",
|
||||
"test:e2e:firefox:metrics": "SELENIUM_BROWSER=firefox node test/e2e/run-e2e-test.js test/e2e/metrics.spec.js",
|
||||
"test:e2e:firefox:snaps": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js --snaps",
|
||||
"test:e2e:single": "node test/e2e/run-e2e-test.js",
|
||||
"test:coverage:mocha": "nyc --reporter=text --reporter=html yarn test:unit:mocha",
|
||||
"test:coverage:jest": "yarn test:unit:jest --coverage --maxWorkers=2",
|
||||
|
@ -17,6 +17,10 @@ async function main() {
|
||||
type: 'string',
|
||||
choices: ['chrome', 'firefox'],
|
||||
})
|
||||
.option('snaps', {
|
||||
description: `run snaps e2e tests`,
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('retries', {
|
||||
description:
|
||||
'Set how many times the test should be retried upon failure.',
|
||||
@ -26,16 +30,22 @@ async function main() {
|
||||
.strict()
|
||||
.help('help');
|
||||
|
||||
const { browser, retries } = argv;
|
||||
const { browser, retries, snaps } = argv;
|
||||
|
||||
const testDir = path.join(__dirname, 'tests');
|
||||
const metamaskUiTest = path.join(__dirname, 'metamask-ui.spec.js');
|
||||
let testDir = path.join(__dirname, 'tests');
|
||||
|
||||
if (snaps) {
|
||||
testDir = path.join(__dirname, 'snaps');
|
||||
}
|
||||
|
||||
const testFilenames = await fs.readdir(testDir);
|
||||
const testPaths = testFilenames.map((filename) =>
|
||||
path.join(testDir, filename),
|
||||
);
|
||||
const allE2eTestPaths = [...testPaths, metamaskUiTest];
|
||||
|
||||
if (!snaps) {
|
||||
testPaths.push(path.join(__dirname, 'metamask-ui.spec.js'));
|
||||
}
|
||||
|
||||
const runE2eTestPath = path.join(__dirname, 'run-e2e-test.js');
|
||||
|
||||
@ -47,7 +57,7 @@ async function main() {
|
||||
args.push('--retries', retries);
|
||||
}
|
||||
|
||||
for (const testPath of allE2eTestPaths) {
|
||||
for (const testPath of testPaths) {
|
||||
await runInShell('node', [...args, testPath]);
|
||||
}
|
||||
}
|
||||
|
98
test/e2e/snaps/test-snap-confirm.spec.js
Normal file
98
test/e2e/snaps/test-snap-confirm.spec.js
Normal file
@ -0,0 +1,98 @@
|
||||
const { strict: assert } = require('assert');
|
||||
const { withFixtures } = require('../helpers');
|
||||
|
||||
describe('Test Snap Confirm', function () {
|
||||
it('can pop up a snap confirm and get its result', async function () {
|
||||
const ganacheOptions = {
|
||||
accounts: [
|
||||
{
|
||||
secretKey:
|
||||
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
|
||||
balance: 25000000000000000000,
|
||||
},
|
||||
],
|
||||
};
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: 'imported-account',
|
||||
ganacheOptions,
|
||||
title: this.test.title,
|
||||
driverOptions: {
|
||||
type: 'flask',
|
||||
},
|
||||
},
|
||||
async ({ driver }) => {
|
||||
await driver.navigate();
|
||||
|
||||
// enter pw into extension
|
||||
await driver.fill('#password', 'correct horse battery staple');
|
||||
await driver.press('#password', driver.Key.ENTER);
|
||||
|
||||
// navigate to test snaps page and connect
|
||||
await driver.driver.get('https://metamask.github.io/test-snaps/');
|
||||
await driver.fill('.snapId', 'npm:@metamask/test-snap-confirm');
|
||||
await driver.clickElement({
|
||||
text: 'Connect To Confirm Snap',
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
// switch to metamask extension and click connect
|
||||
await driver.waitUntilXWindowHandles(2, 5000, 10000);
|
||||
let windowHandles = await driver.getAllWindowHandles();
|
||||
await driver.switchToWindowWithTitle(
|
||||
'MetaMask Notification',
|
||||
windowHandles,
|
||||
);
|
||||
await driver.clickElement(
|
||||
{
|
||||
text: 'Connect',
|
||||
tag: 'button',
|
||||
},
|
||||
10000,
|
||||
);
|
||||
|
||||
await driver.delay(2000);
|
||||
|
||||
// approve install of snap
|
||||
await driver.waitUntilXWindowHandles(2, 5000, 10000);
|
||||
windowHandles = await driver.getAllWindowHandles();
|
||||
await driver.switchToWindowWithTitle(
|
||||
'MetaMask Notification',
|
||||
windowHandles,
|
||||
);
|
||||
await driver.clickElement({
|
||||
text: 'Approve & Install',
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
// click send inputs on test snap page
|
||||
await driver.waitUntilXWindowHandles(1, 5000, 10000);
|
||||
windowHandles = await driver.getAllWindowHandles();
|
||||
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
|
||||
await driver.clickElement({
|
||||
text: 'Send Inputs to Hello Snap',
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
// hit 'approve' on the custom confirm
|
||||
await driver.waitUntilXWindowHandles(2, 5000, 10000);
|
||||
windowHandles = await driver.getAllWindowHandles();
|
||||
await driver.switchToWindowWithTitle(
|
||||
'MetaMask Notification',
|
||||
windowHandles,
|
||||
);
|
||||
await driver.clickElement({
|
||||
text: 'Approve',
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
// check the results of the custom confirm
|
||||
await driver.waitUntilXWindowHandles(1, 5000, 10000);
|
||||
windowHandles = await driver.getAllWindowHandles();
|
||||
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
|
||||
const confirmResult = await driver.findElement('.sendResults');
|
||||
assert.equal(await confirmResult.getText(), 'true');
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
90
test/e2e/snaps/test-snap-error.spec.js
Normal file
90
test/e2e/snaps/test-snap-error.spec.js
Normal file
@ -0,0 +1,90 @@
|
||||
const { strict: assert } = require('assert');
|
||||
const { withFixtures } = require('../helpers');
|
||||
const { PAGES } = require('../webdriver/driver');
|
||||
|
||||
describe('Test Snap Error', function () {
|
||||
it('can pop up a snap error and see the error', async function () {
|
||||
const ganacheOptions = {
|
||||
accounts: [
|
||||
{
|
||||
secretKey:
|
||||
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
|
||||
balance: 25000000000000000000,
|
||||
},
|
||||
],
|
||||
};
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: 'imported-account',
|
||||
ganacheOptions,
|
||||
title: this.test.title,
|
||||
driverOptions: { type: 'flask' },
|
||||
},
|
||||
async ({ driver }) => {
|
||||
await driver.navigate();
|
||||
|
||||
// enter pw into extension
|
||||
await driver.fill('#password', 'correct horse battery staple');
|
||||
await driver.press('#password', driver.Key.ENTER);
|
||||
|
||||
// navigate to test snaps page and connect
|
||||
await driver.driver.get('https://metamask.github.io/test-snaps/');
|
||||
await driver.fill('.snapId2', 'npm:@metamask/test-snap-error');
|
||||
await driver.clickElement({
|
||||
text: 'Connect Error Snap',
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
// switch to metamask extension and click connect
|
||||
await driver.waitUntilXWindowHandles(2, 5000, 10000);
|
||||
let windowHandles = await driver.getAllWindowHandles();
|
||||
await driver.switchToWindowWithTitle(
|
||||
'MetaMask Notification',
|
||||
windowHandles,
|
||||
);
|
||||
await driver.clickElement(
|
||||
{
|
||||
text: 'Connect',
|
||||
tag: 'button',
|
||||
},
|
||||
10000,
|
||||
);
|
||||
|
||||
await driver.delay(2000);
|
||||
|
||||
// approve install of snap
|
||||
windowHandles = await driver.getAllWindowHandles();
|
||||
await driver.switchToWindowWithTitle(
|
||||
'MetaMask Notification',
|
||||
windowHandles,
|
||||
);
|
||||
await driver.clickElement({
|
||||
text: 'Approve & Install',
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
// click send inputs on test snap page
|
||||
await driver.waitUntilXWindowHandles(1, 5000, 10000);
|
||||
windowHandles = await driver.getAllWindowHandles();
|
||||
await driver.switchToWindowWithTitle('Test Snaps', windowHandles);
|
||||
await driver.clickElement({
|
||||
text: 'Send Test to Error Snap',
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
await driver.navigate(PAGES.HOME);
|
||||
|
||||
const error = await driver.findElement(
|
||||
'.home-notification__content-container',
|
||||
);
|
||||
const text = await error.getText();
|
||||
assert.equal(
|
||||
text.includes(
|
||||
"Snap Error: 'random error inside'. Error Code: '-32603'",
|
||||
),
|
||||
true,
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
@ -69,7 +69,7 @@ class ChromeDriver {
|
||||
for (let i = 0; i < extensions.length; i++) {
|
||||
const extension = extensions[i].shadowRoot
|
||||
const name = extension.querySelector('#name').textContent
|
||||
if (name === "${extensionName}") {
|
||||
if (name.startsWith("${extensionName}")) {
|
||||
return extensions[i].getAttribute("id")
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ class Driver {
|
||||
const ignoredLogTypes = ['WARNING'];
|
||||
const ignoredErrorMessages = [
|
||||
// Third-party Favicon 404s show up as errors
|
||||
'favicon.ico - Failed to load resource: the server responded with a status of 404 (Not Found)',
|
||||
'favicon.ico - Failed to load resource: the server responded with a status of 404',
|
||||
// Sentry rate limiting
|
||||
'Failed to load resource: the server responded with a status of 429',
|
||||
// 4Byte
|
||||
|
@ -31,9 +31,10 @@ class FirefoxDriver {
|
||||
* @param {Object} options - the options for the build
|
||||
* @param options.responsive
|
||||
* @param options.port
|
||||
* @param options.type
|
||||
* @returns {Promise<{driver: !ThenableWebDriver, extensionUrl: string, extensionId: string}>}
|
||||
*/
|
||||
static async build({ responsive, port }) {
|
||||
static async build({ responsive, port, type }) {
|
||||
const templateProfile = fs.mkdtempSync(TEMP_PROFILE_PATH_PREFIX);
|
||||
const options = new firefox.Options().setProfile(templateProfile);
|
||||
options.setProxy(proxy.manual({ https: HTTPS_PROXY_HOST }));
|
||||
@ -48,9 +49,13 @@ class FirefoxDriver {
|
||||
const driver = builder.build();
|
||||
const fxDriver = new FirefoxDriver(driver);
|
||||
|
||||
const extensionId = await fxDriver.installExtension(
|
||||
`builds/metamask-firefox-${version}.zip`,
|
||||
);
|
||||
let extensionString = `builds/metamask-firefox-${version}.zip`;
|
||||
|
||||
if (type) {
|
||||
extensionString = `builds/metamask-${type}-firefox-${version}.zip`;
|
||||
}
|
||||
|
||||
const extensionId = await fxDriver.installExtension(extensionString);
|
||||
const internalExtensionId = await fxDriver.getInternalId();
|
||||
|
||||
if (responsive) {
|
||||
|
@ -4,14 +4,14 @@ const Driver = require('./driver');
|
||||
const ChromeDriver = require('./chrome');
|
||||
const FirefoxDriver = require('./firefox');
|
||||
|
||||
async function buildWebDriver({ responsive, port } = {}) {
|
||||
async function buildWebDriver({ responsive, port, type } = {}) {
|
||||
const browser = process.env.SELENIUM_BROWSER;
|
||||
|
||||
const {
|
||||
driver: seleniumDriver,
|
||||
extensionId,
|
||||
extensionUrl,
|
||||
} = await buildBrowserWebDriver(browser, { responsive, port });
|
||||
} = await buildBrowserWebDriver(browser, { responsive, port, type });
|
||||
await setupFetchMocking(seleniumDriver);
|
||||
const driver = new Driver(seleniumDriver, browser, extensionUrl);
|
||||
|
||||
|
@ -43,7 +43,7 @@ export default class PermissionConnect extends Component {
|
||||
extensionId: PropTypes.string,
|
||||
iconUrl: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
origin: PropTypes.string.isRequired,
|
||||
origin: PropTypes.string,
|
||||
subjectType: PropTypes.string,
|
||||
}),
|
||||
isRequestingAccounts: PropTypes.bool.isRequired,
|
||||
|
Loading…
Reference in New Issue
Block a user