As dAppeteer is Puppeteer with MetaMask. Using it with jest is pretty similar to jest-puppeteer
.
You can use jest preset provided by dappeteer without installing additional packages
{
"preset": "@chainsafe/dappeteer"
}
Write your test
describe('Ethereum', () => {
beforeAll(async () => {
await page.goto('https://ethereum.org/en/');
});
it('should be titled "Home | ethereum.org"', async () => {
await expect(page.title()).resolves.toMatch('Home | ethereum.org');
});
});
To configure Dappeteer to use custom config values as metamaskVersion
or own seed
phrase you need to create file dappeteer.config.js
that exports config object
example of dappeteer.config.js
/** @type {import('@chainsafe/dappeteer').DappeteerJestConfig} */
const config = {
dappeteer: {
metamaskVersion: 'v10.14.0',
},
metamask: {
seed: 'already turtle birth enroll since owner keep patch skirt drift any dinner',
password: 'password1234',
},
};
module.exports = config;
In case you need more customisable use case you can rebuild it from scratch.
First let's define our entry jest.config.js
// jest.config.js
module.exports = {
globalSetup: './setup.js',
globalTeardown: './teardown.js',
testEnvironment: './environment.js',
};
Then create setup.js
with responsibility to start Puppeteer with MetaMask and teardown.js
for clean up after tests
// setup.js
const { writeFile } = require('fs').promises;
const os = require('os');
const path = require('path');
const { launch, setupMetaMask } = require('@chainsafe/dappeteer');
const mkdirp = require('mkdirp');
const puppeteer = require('puppeteer');
const { metaMaskOptions, PUPPETEER_CONFIG } = require('./jest.config');
const DIR = path.join(os.tmpdir(), 'jest_dappeteer_global_setup');
module.exports = async function () {
const browser = await launch(puppeteer, PUPPETEER_CONFIG);
try {
await setupMetaMask(browser, metaMaskOptions);
global.browser = browser;
} catch (error) {
console.log(error);
throw error;
}
mkdirp.sync(DIR);
await writeFile(path.join(DIR, 'wsEndpoint'), browser.wsEndpoint());
};
// teardown.js
const os = require('os');
const path = require('path');
const rimraf = require('rimraf');
const DIR = path.join(os.tmpdir(), 'jest_dappeteer_global_setup');
module.exports = async function () {
// close the browser instance
await global.browser.close();
// clean-up the wsEndpoint file
rimraf.sync(DIR);
};
And for the end we need a custom Test Environment for dAppeteer to inject features into the tests
// environment.js
const {readFile} = require('fs').promises;
const os = require('os');
const path = require('path');
const puppeteer = require('puppeteer');
const NodeEnvironment = require('jest-environment-node');
const { getMetaMaskWindow } = require('@chainsafe/dappeteer');
const DIR = path.join(os.tmpdir(), 'jest_dappeteer_global_setup');
class DappeteerEnvironment extends NodeEnvironment {
async setup() {
await super.setup();
// get the wsEndpoint
const wsEndpoint = await readFile(path.join(DIR, 'wsEndpoint'), 'utf8');
if (!wsEndpoint) throw new Error('wsEndpoint not found');
// connect to puppeteer
const browser = await puppeteer.connect({
browserWSEndpoint: wsEndpoint,
});
this.global.browser = browser;
this.global.metamask = await getMetaMaskWindow(browser);
}
}
module.exports = DappeteerEnvironment;