Skip to content

Commit

Permalink
refactor: plugins file refactor
Browse files Browse the repository at this point in the history
Signed-off-by: Jakub Mucha <jakub.mucha@icloud.com>
  • Loading branch information
drptbl committed Dec 11, 2020
1 parent 45cb4e4 commit 3ae1ab3
Showing 1 changed file with 20 additions and 288 deletions.
308 changes: 20 additions & 288 deletions plugins/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,6 @@
const path = require('path');
const fs = require('fs');
const helpers = require('../helpers');
const puppeteer = require('puppeteer-core');
const fetch = require('node-fetch');
const { pageElements } = require('../pages/metamask/page');
const {
welcomePageElements,
firstTimeFlowPageElements,
metametricsPageElements,
firstTimeFlowFormPageElements,
revealSeedPageElements,
} = require('../pages/metamask/first-time-flow-page');
const { mainPageElements } = require('../pages/metamask/main-page');
const { unlockPageElements } = require('../pages/metamask/unlock-page');
const {
notificationPageElements,
permissionsPageElements,
confirmPageElements,
} = require('../pages/metamask/notification-page');

let puppeteerBrowser;
let mainWindow;
let metamaskWindow;
let walletAddress;
const puppeteer = require('../commands/puppeteer');
const metamask = require('../commands/metamask');

/**
* @type {Cypress.PluginConfig}
Expand Down Expand Up @@ -53,7 +31,7 @@ module.exports = (on, config) => {
}

// NOTE: extensions cannot be loaded in headless Chrome
const metamaskPath = await prepareMetamask();
const metamaskPath = await helpers.prepareMetamask();
arguments_.extensions.push(metamaskPath);
return arguments_;
});
Expand All @@ -66,85 +44,65 @@ module.exports = (on, config) => {
console.warn('\u001B[33m', 'WARNING:', message, '\u001B[0m');
},
initPuppeteer: async () => {
const connected = await initPuppeteer();
const connected = await puppeteer.init();
return connected;
},
assignWindows: async () => {
const assigned = await assignWindows();
const assigned = await puppeteer.assignWindows();
return assigned;
},
switchToCypressWindow: async () => {
const switched = await switchToCypressWindow();
const switched = await puppeteer.switchToCypressWindow();
return switched;
},
switchToMetamaskWindow: async () => {
const switched = await switchToMetamaskWindow();
const switched = await puppeteer.switchToMetamaskWindow();
return switched;
},
switchToMetamaskNotification: async () => {
const notificationPage = await switchToMetamaskNotification();
const notificationPage = await puppeteer.switchToMetamaskNotification();
return notificationPage;
},
confirmMetamaskWelcomePage: async () => {
const confirmed = await confirmMetamaskWelcomePage();
const confirmed = await metamask.confirmWelcomePage();
return confirmed;
},
unlockMetamask: async password => {
const unlocked = await unlockMetamask(password);
const unlocked = await metamask.unlock(password);
return unlocked;
},
importMetamaskWallet: async ({ secretWords, password }) => {
const imported = await importMetamaskWallet(secretWords, password);
const imported = await metamask.importWallet(secretWords, password);
return imported;
},
changeMetamaskNetwork: async network => {
const networkChanged = await changeMetamaskNetwork(network);
const networkChanged = await metamask.changeNetwork(network);
return networkChanged;
},
acceptMetamaskAccess: async () => {
const accepted = await acceptMetamaskAccess();
const accepted = await metamask.acceptAccess();
return accepted;
},
confirmMetamaskTransaction: async () => {
const confirmed = await confirmMetamaskTransaction();
const confirmed = await metamask.confirmTransaction();
return confirmed;
},
rejectMetamaskTransaction: async () => {
const rejected = await rejectMetamaskTransaction();
const rejected = await metamask.rejectTransaction();
return rejected;
},
getMetamaskWalletAddress: async () => {
const walletAddress = await getMetamaskWalletAddress();
const walletAddress = await metamask.getWalletAddress();
return walletAddress;
},
setupMetamask: async ({ secretWords, network, password }) => {
if (secretWords === undefined && process.env.SECRET_WORDS) {
secretWords = process.env.SECRET_WORDS;
}

await initPuppeteer();
await assignWindows();
await metamaskWindow.waitForTimeout(1000);
if ((await metamaskWindow.$(unlockPageElements.unlockPage)) === null) {
await confirmMetamaskWelcomePage();
await importMetamaskWallet(secretWords, password);
await changeMetamaskNetwork(network);
walletAddress = await getMetamaskWalletAddress();
await switchToCypressWindow();
return true;
} else {
await unlockMetamask(password);
walletAddress = await getMetamaskWalletAddress();
await switchToCypressWindow();
return true;
}
},
fetchMetamaskWalletAddress: async () => {
return walletAddress;
return metamask.walletAddress;
},
setupMetamask: async ({ secretWords, network, password }) => {
return metamask.initialSetup({ secretWords, network, password });
},
});

// setup config
if (process.env.BASE_URL) {
config.baseUrl = process.env.BASE_URL;
}
Expand All @@ -156,229 +114,3 @@ module.exports = (on, config) => {

return config;
};

async function waitFor(selector, page = metamaskWindow) {
await page.waitForFunction(
`document.querySelector('${selector}') && document.querySelector('${selector}').clientHeight != 0`,
{ visible: true },
);
// puppeteer going too fast breaks metamask in corner cases
await page.waitForTimeout(300);
}

async function waitAndClick(selector, page = metamaskWindow) {
await waitFor(selector, page);
await page.evaluate(
selector => document.querySelector(selector).click(),
selector,
);
}

async function waitAndType(selector, value, page = metamaskWindow) {
await waitFor(selector, page);
const element = await page.$(selector);
await element.type(value);
}

async function waitAndGetValue(selector, page = metamaskWindow) {
await waitFor(selector, page);
const element = await page.$(selector);
const property = await element.getProperty('value');
const value = await property.jsonValue();
return value;
}

async function waitAndSetValue(text, selector, page = metamaskWindow) {
await waitFor(selector, page);
await page.evaluate(
selector => (document.querySelector(selector).value = ''),
selector,
);
await page.focus(selector);
await page.keyboard.type(text);
}

async function waitForText(selector, text, page = metamaskWindow) {
await waitFor(selector, page);
await page.waitForFunction(
`document.querySelector('${selector}').innerText.toLowerCase().includes('${text}')`,
);
}

async function prepareMetamask() {
const release = await helpers.getMetamaskReleases();
const downloadsDirectory = path.resolve(__dirname, 'downloads');
if (!fs.existsSync(downloadsDirectory)) {
fs.mkdirSync(downloadsDirectory);
}
const downloadDestination = path.join(downloadsDirectory, release.filename);
await helpers.download(release.downloadUrl, downloadDestination);
const metamaskDirectory = path.join(downloadsDirectory, 'metamask');
await helpers.extract(downloadDestination, metamaskDirectory);
return metamaskDirectory;
}

async function initPuppeteer() {
const debuggerDetails = await fetch('http://localhost:9222/json/version');
const debuggerDetailsConfig = await debuggerDetails.json();
const webSocketDebuggerUrl = debuggerDetailsConfig.webSocketDebuggerUrl;

puppeteerBrowser = await puppeteer.connect({
browserWSEndpoint: webSocketDebuggerUrl,
ignoreHTTPSErrors: true,
// eslint-disable-next-line unicorn/no-null
defaultViewport: null,
});
return puppeteerBrowser.isConnected();
}

async function assignWindows() {
let pages = await puppeteerBrowser.pages();
for (const page of pages) {
if (page.url().includes('integration')) {
mainWindow = page;
} else if (page.url().includes('extension')) {
metamaskWindow = page;
}
}
return true;
}

async function switchToCypressWindow() {
await mainWindow.bringToFront();
return true;
}

async function switchToMetamaskWindow() {
await metamaskWindow.bringToFront();
return true;
}

async function switchToMetamaskNotification() {
let pages = await puppeteerBrowser.pages();
for (const page of pages) {
if (page.url().includes('notification')) {
await page.bringToFront();
return page;
}
}
}

async function confirmMetamaskWelcomePage() {
await fixBlankMetamask();
await waitAndClick(welcomePageElements.confirmButton);
return true;
}

async function unlockMetamask(password) {
await fixBlankMetamask();
await waitAndType(unlockPageElements.passwordInput, password);
await waitAndClick(unlockPageElements.unlockButton);
return true;
}

async function importMetamaskWallet(secretWords, password) {
await waitAndClick(firstTimeFlowPageElements.importWalletButton);
await waitAndClick(metametricsPageElements.optOutAnalyticsButton);
await waitAndType(
firstTimeFlowFormPageElements.secretWordsInput,
secretWords,
);
await waitAndType(firstTimeFlowFormPageElements.passwordInput, password);
await waitAndType(
firstTimeFlowFormPageElements.confirmPasswordInput,
password,
);
await waitAndClick(firstTimeFlowFormPageElements.termsCheckbox);
await waitAndClick(firstTimeFlowFormPageElements.importButton);

// metamask hangs, reload as workaround
// await waitAndClick(endOfFlowPageElements.allDoneButton);
await waitFor(pageElements.loadingSpinner);
await metamaskWindow.reload();
await waitAndClick(revealSeedPageElements.remindLaterButton);
await waitFor(mainPageElements.walletOverview);

// close popup if present
if ((await metamaskWindow.$(mainPageElements.popup.container)) !== null) {
await waitAndClick(mainPageElements.popup.closeButton);
}
return true;
}

async function changeMetamaskNetwork(network) {
await waitAndClick(mainPageElements.networkSwitcher.button);
if (network === 'main') {
await waitAndClick(mainPageElements.networkSwitcher.networkButton(0));
} else if (network === 'ropsten') {
await waitAndClick(mainPageElements.networkSwitcher.networkButton(1));
} else if (network === 'kovan') {
await waitAndClick(mainPageElements.networkSwitcher.networkButton(2));
} else if (network === 'rinkeby') {
await waitAndClick(mainPageElements.networkSwitcher.networkButton(3));
} else if (network === 'goerli') {
await waitAndClick(mainPageElements.networkSwitcher.networkButton(4));
} else if (network === 'localhost') {
await waitAndClick(mainPageElements.networkSwitcher.networkButton(5));
}
await waitForText(mainPageElements.networkSwitcher.networkName, network);
return true;
}

async function acceptMetamaskAccess() {
await metamaskWindow.waitForTimeout(3000);
const notificationPage = await switchToMetamaskNotification();
await waitAndClick(notificationPageElements.nextButton, notificationPage);
await waitAndClick(permissionsPageElements.connectButton, notificationPage);
await metamaskWindow.waitForTimeout(3000);
return true;
}

async function confirmMetamaskTransaction() {
await metamaskWindow.waitForTimeout(3000);
const notificationPage = await switchToMetamaskNotification();
const currentGasFee = await waitAndGetValue(
confirmPageElements.gasFeeInput,
notificationPage,
);
const newGasFee = (Number(currentGasFee) + 10).toString();
await waitAndSetValue(
newGasFee,
confirmPageElements.gasFeeInput,
notificationPage,
);
await waitAndClick(confirmPageElements.confirmButton, notificationPage);
await metamaskWindow.waitForTimeout(3000);
return true;
}

async function rejectMetamaskTransaction() {
await metamaskWindow.waitForTimeout(3000);
const notificationPage = await switchToMetamaskNotification();
await waitAndClick(confirmPageElements.rejectButton, notificationPage);
await metamaskWindow.waitForTimeout(3000);
return true;
}

async function getMetamaskWalletAddress() {
await waitAndClick(mainPageElements.options.button);
await waitAndClick(mainPageElements.options.accountDetailsButton);
const walletAddress = await waitAndGetValue(
mainPageElements.accountModal.walletAddressInput,
);
await waitAndClick(mainPageElements.accountModal.closeButton);
return walletAddress;
}

// workaround for metamask random blank page on first run
async function fixBlankMetamask() {
await metamaskWindow.waitForTimeout(1000);
for (let times = 0; times < 5; times++) {
if ((await metamaskWindow.$(welcomePageElements.app)) === null) {
await metamaskWindow.reload();
await metamaskWindow.waitForTimeout(2000);
} else {
break;
}
}
}

0 comments on commit 3ae1ab3

Please sign in to comment.