Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
fix: selector issues, useless timeouts, reorganise tests (#145)
Browse files Browse the repository at this point in the history
* fix: update ganache, fix test depending on goerli

* fix: bugs in selectors, less timeout, reorganise structure

* update yarn

* chore: improve root hooks

* try to increase timeout

* better ci

* add screenshot uploading to ci

* fix screenshot name

* run screenshot on failed test

* fix lint

* change viewport

* fix tests

* fix#123124

* fix tests

* whyyyyyyyyyyyyyyyyyyyyyyyyy

* please

* fix testing dapp

* dunno anymore

* fix lint

* fix typo in selector

* update dapp loading

* refactor script fetching for `index.html`

* fix dam sing test

Co-authored-by: Bernard <bero4net@gmail.com>
  • Loading branch information
mpetrunic and BeroBurny committed Dec 15, 2022
1 parent c0a41aa commit babdd28
Show file tree
Hide file tree
Showing 24 changed files with 676 additions and 613 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache: yarn
node-version: "16"
- name: Install
run: yarn install --frozen-lockfile
Expand All @@ -26,7 +25,12 @@ jobs:
- name: Lint
run: yarn run lint
- name: Tests
run: xvfb-run --auto-servernum yarn run test
run: xvfb-run --auto-servernum yarn run test --timeout 50000
- uses: actions/upload-artifact@v3
if: always()
with:
name: debug_screenshots
path: ./*.png

maybe-release:
name: release
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ dist
/metamask
.idea
*.log
test/dapp/data.js
test/dapp/data.js
*.png
10 changes: 10 additions & 0 deletions .mocharc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
parallel: false
recursive: true
color: true
timeout: 20000
exit: true
require:
- 'ts-node/register'
- 'test/global.ts'
spec:
- 'test/**/*.spec.ts'
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"devDependencies": {
"@jest/types": "^27.1.1",
"@types/chai": "^4.2.22",
"@types/mocha": "^7.0.2",
"@types/mocha": "^9.1.1",
"@typescript-eslint/eslint-plugin": "^4.15.0",
"@typescript-eslint/parser": "^4.15.0",
"chai": "^4.3.4",
Expand All @@ -55,7 +55,7 @@
"eslint-plugin-prettier": "^3.3.1",
"ganache": "^7.4.3",
"jest-environment-node": "^27.1.1",
"mocha": "7.2.0",
"mocha": "^10.0.0",
"prettier": "^2.2.1",
"puppeteer": "14.0.0",
"serve-handler": "5.0.8",
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ElementHandle, Page } from 'puppeteer';

// TODO: change text() with '.';
export const getElementByContent = (page: Page, text: string, type = '*'): Promise<ElementHandle | null> =>
page.waitForXPath(`//${type}[contains(text(), '${text}')]`);
page.waitForXPath(`//${type}[contains(text(), '${text}')]`, { timeout: 20000 });

export const getInputByLabel = (
page: Page,
Expand Down
1 change: 0 additions & 1 deletion src/metamask/confirmTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,5 @@ export const confirmTransaction = (page: Page, getSingedIn: GetSingedIn, version

await clickOnButton(page, 'Save');
}

await clickOnButton(page, 'Confirm');
};
1 change: 1 addition & 0 deletions src/metamask/helpers/deleteAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export const deleteAccount = (page: Page, version?: string) => async (accountNum
await openAccountDropdown(page);
await clickOnElement(page, 'Remove account');
await clickOnButton(page, 'Remove');
await page.reload();
};
6 changes: 4 additions & 2 deletions src/metamask/helpers/getTokenBalance.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Page } from 'puppeteer';

import { clickOnButton } from '../../helpers';

export const getTokenBalance = (page: Page) => async (tokenSymbol: string): Promise<number> => {
await page.bringToFront();
await page.waitForTimeout(1000);

await clickOnButton(page, 'Assets');
await page.waitForSelector('.asset-list-item__token-button');
const assetListItems = await page.$$('.asset-list-item__token-button');

for (let index = 0; index < assetListItems.length; index++) {
Expand Down
2 changes: 2 additions & 0 deletions src/metamask/sign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export const sign = (page: Page, getSingedIn: GetSingedIn, version?: string) =>
if (!(await getSingedIn())) {
throw new Error("You haven't signed in yet");
}

await page.waitForTimeout(500);
await page.reload();

await clickOnButton(page, 'Sign');
Expand Down
2 changes: 1 addition & 1 deletion src/metamask/switchNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ export const switchNetwork = (page: Page, version?: string) => async (network =

const networkButton = (await page.$$('li.dropdown-menu-item'))[networkIndex];
await networkButton.click();

await page.reload();
await page.waitForXPath(`//*[text() = '${networkFullName}']`);
};
8 changes: 4 additions & 4 deletions src/setup/setupMetaMask.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Browser, Page } from 'puppeteer';
import { Browser, BrowserContext, Page } from 'puppeteer';

import { getMetaMask } from '../metamask';
import { Dappeteer, MetaMaskOptions } from '../types';
Expand All @@ -12,12 +12,12 @@ type Step<Options> = (page: Page, options?: Options) => void;
const defaultMetaMaskSteps: Step<MetaMaskOptions>[] = [confirmWelcomeScreen, importAccount, closePopup, showTestNets];

export async function setupMetaMask<Options = MetaMaskOptions>(
browser: Browser,
browser: Browser | BrowserContext,
options?: Options,
steps: Step<Options>[] = defaultMetaMaskSteps,
): Promise<Dappeteer> {
const page = await closeHomeScreen(browser);

page.setViewport({ height: 1200, width: 800 });
// goes through the installation steps required by MetaMask
for (const step of steps) {
await step(page, options);
Expand All @@ -26,7 +26,7 @@ export async function setupMetaMask<Options = MetaMaskOptions>(
return getMetaMask(page);
}

async function closeHomeScreen(browser: Browser): Promise<Page> {
async function closeHomeScreen(browser: Browser | BrowserContext): Promise<Page> {
return new Promise((resolve, reject) => {
browser.on('targetcreated', async (target) => {
if (target.url().match('chrome-extension://[a-z]+/home.html')) {
Expand Down
126 changes: 126 additions & 0 deletions test/basic.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { expect, use } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { Page } from 'puppeteer';

import * as dappeteer from '../src';
import { clickOnLogo, openProfileDropdown } from '../src/helpers';

import { PASSWORD, TestContext } from './global';
import { clickElement } from './utils/utils';

use(chaiAsPromised);

describe('basic interactions', async function () {
let metamask: dappeteer.Dappeteer;
let testPage: Page;

before(async function (this: TestContext) {
testPage = await this.browser.newPage();
await testPage.goto('http://localhost:8080/', { waitUntil: 'networkidle0' });
metamask = this.metamask;
try {
await clickElement(testPage, '.connect-button');
await metamask.approve();
} catch (e) {
//ignored
}
});

after(async function () {
await testPage.close();
});

it('should be able to sign', async () => {
await clickElement(testPage, '.sign-button');

await metamask.sign();

await testPage.waitForSelector('#signed');
});

it('should switch network', async () => {
await metamask.switchNetwork('localhost');

const selectedNetwork = await metamask.page.evaluate(
() => (document.querySelector('.network-display > span:nth-child(2)') as HTMLSpanElement).innerHTML,
);
expect(selectedNetwork).to.be.equal('Localhost 8545');
});

it('should return eth balance', async () => {
await metamask.switchNetwork('localhost');
const tokenBalance: number = await metamask.helpers.getTokenBalance('ETH');
expect(tokenBalance).to.be.greaterThan(0);
});

it('should return 0 token balance when token not found', async () => {
const tokenBalance: number = await metamask.helpers.getTokenBalance('FARTBUCKS');
expect(tokenBalance).to.be.equal(0);
});

// TODO: cover more cases
it('should add token', async () => {
await metamask.switchNetwork('kovan');
await metamask.addToken({
tokenAddress: '0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa',
symbol: 'KAKI',
});
await metamask.switchNetwork('local');
});

it('should add network with required params', async () => {
await metamask.addNetwork({
networkName: 'Binance Smart Chain',
rpc: 'https://data-seed-prebsc-1-s1.binance.org:8545/',
chainId: 97,
symbol: 'BNB',
});

const selectedNetwork = await metamask.page.evaluate(
() => (document.querySelector('.network-display > span:nth-child(2)') as HTMLSpanElement).innerHTML,
);
expect(selectedNetwork).to.be.equal('Binance Smart Chain');
await metamask.switchNetwork('local');
});

it('should fail to add network with wrong chain ID', async () => {
await expect(
metamask.addNetwork({
networkName: 'Optimistic Ethereum Testnet Kovan',
rpc: 'https://kovan.optimism.io/',
chainId: 420,
symbol: 'KUR',
}),
).to.be.rejectedWith(SyntaxError);

await clickOnLogo(metamask.page);
});

it('should import private key', async () => {
const countAccounts = async (): Promise<number> => {
await openProfileDropdown(metamask.page);
const container = await metamask.page.$('.account-menu__accounts');
const count = (await container.$$('.account-menu__account')).length;
await openProfileDropdown(metamask.page);
return count;
};

const beforeImport = await countAccounts();
await metamask.importPK('4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b10');
const afterImport = await countAccounts();

expect(beforeImport + 1).to.be.equal(afterImport);
await metamask.helpers.deleteAccount(2);
});

it('should throw error on wrong key', async () => {
await expect(
metamask.importPK('4f3edf983ac636a65a$@!ce7c78d9aa706d3b113bce9c46f30d7d21715b23b10'),
).to.be.rejectedWith(SyntaxError);
});

it('should lock and unlock', async () => {
await metamask.lock();
await metamask.unlock(PASSWORD);
});
});
60 changes: 60 additions & 0 deletions test/contract.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { expect } from 'chai';
import { Page } from 'puppeteer';

import { Dappeteer } from '../src';

import { Contract } from './deploy';
import { TestContext } from './global';
import { clickElement, pause } from './utils/utils';

describe('contract interactions', async function () {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let contract: Contract;
let testPage: Page;
let metamask: Dappeteer;

before(async function (this: TestContext) {
testPage = await this.browser.newPage();
await testPage.goto('http://localhost:8080/', { waitUntil: 'load' });
metamask = this.metamask;
contract = this.contract;
try {
await clickElement(testPage, '.connect-button');
await metamask.approve();
} catch (e) {
//ignored
}
});

after(async function (this: TestContext) {
await testPage.close();
});

it('should have increased count', async () => {
await metamask.switchAccount(1);
await metamask.switchNetwork('local');
await pause(1);
const counterBefore = await getCounterNumber(contract);
// click increase button
await clickElement(testPage, '.increase-button');
await pause(1);
// submit tx
await metamask.confirmTransaction();
await testPage.waitForSelector('#txSent');
await pause(1);

const counterAfter = await getCounterNumber(contract);

expect(counterAfter).to.be.equal(counterBefore + 1);
await metamask.switchNetwork('main');
});
});

function getCounterNumber(contract): Promise<number> {
return contract.methods
.count()
.call()
.then((res) => {
return Number(res);
});
}
13 changes: 6 additions & 7 deletions test/dapp/main.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
async function start() {
const web3 = new Web3(window.web3.currentProvider);
let accounts = [];

const web3 = new Web3(window.ethereum);
console.log(web3);
const counterContract = new web3.eth.Contract(ContractInfo.abi, ContractInfo.address);

const increaseButton = document.querySelector('.increase-button');
increaseButton.addEventListener('click', async function () {
const accounts = await web3.eth.getAccounts();
await counterContract.methods.increase().send({ from: accounts[0] });
const txSent = document.createElement('div');
txSent.id = 'txSent';
Expand All @@ -14,7 +15,6 @@ async function start() {

const increaseFeesButton = document.querySelector('.increase-fees-button');
increaseFeesButton.addEventListener('click', async function () {
const accounts = await web3.eth.getAccounts();
await counterContract.methods.increase().send({ from: accounts[0] });
const txSent = document.createElement('div');
txSent.id = 'feesTxSent';
Expand All @@ -23,24 +23,23 @@ async function start() {

const connectButton = document.querySelector('.connect-button');
connectButton.addEventListener('click', async function () {
await ethereum.enable();
accounts = await web3.eth.requestAccounts();
const connected = document.createElement('div');
connected.id = 'connected';
document.body.appendChild(connected);
});

const signButton = document.querySelector('.sign-button');
signButton.addEventListener('click', async function () {
const accounts = await web3.eth.getAccounts();
await web3.eth.personal.sign('TEST', accounts[0]);
const message = web3.utils.sha3('TEST');
await web3.eth.sign(message, accounts[0]);
const signed = document.createElement('div');
signed.id = 'signed';
document.body.appendChild(signed);
});

const transferButton = document.querySelector('.transfer-button');
transferButton.addEventListener('click', async function () {
const accounts = await web3.eth.getAccounts();
await web3.eth.sendTransaction({ to: accounts[0], from: accounts[0], value: web3.utils.toWei('0.01') });
const transfer = document.createElement('div');
transfer.id = 'transferred';
Expand Down
75 changes: 74 additions & 1 deletion test/dapp/web3.min.js

Large diffs are not rendered by default.

0 comments on commit babdd28

Please sign in to comment.