Testing front end code using rollup, tape-modern, and puppeteer.
These are just some notes for me to write down so that I have a good cheatsheet to set this up in the future.
Using rollup to build front end code is the way to go, it is small and provides tree shaking and the plugins are easy to manage. Using rollup to build a test bundle and using puppeteer to run the test bundle will create a chromium head browser and give you similar results as if you are running it in the browser.
We need to install our dependencies
npm install --save-dev rollup tape-modern puppeteer
npm install --save-dev rollup-plugin-node-resolve
npm install --save-dev rollup-plugin-commonjs
npm install --save-dev sirv tape-browser-color
We need to setup our test directory:
mkdir test
mkdir test/public test/src
npx @twilson63/html test/public/index.html
touch test/src/main.js
modify the index.html to work for the test suite
create a separate rollup config pipeline
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default [{
...
}, {
input: 'test/src/main.js',
output: {
file: 'test/public/bundle.js',
format: 'iife',
name: 'tests'
},
plugins: [
resolve(),
commonjs()
]
}]
Here we are creating a new rollup build pipeline this pipeline will use the main.js in our test/src folder which should contain our tape tests.
write main.js as you would any tape tests or it can be an aggregate file for calling all of your test files.
import { test, done } from 'tape-modern'
import color from 'tape-browser-color'
import mymodule from '../..'
color() // add your test print out to the page for visual debugging
test('my first test', t => {
t.ok(true)
})
window.done = done // for puppeteer
We need to create a runner file to run the tests using puppeteer.
touch test/runner.js
const http = require('http');
const ports = require('port-authority');
const sirv = require('sirv');
const puppeteer = require('puppeteer');
async function go() {
const port = await ports.find(1234);
console.log(`found available port: ${port}`);
const server = http.createServer(sirv('test/public'));
server.listen(port);
await ports.wait(port).catch(() => {}); // workaround windows gremlins
const browser = await puppeteer.launch({args: ['--no-sandbox']});
const page = await browser.newPage();
page.on('console', msg => {
console[msg.type()](msg.text());
});
await page.goto(`http://localhost:${port}`);
await page.evaluate(() => done);
await browser.close();
server.close();
}
go();
The nice thing about this code is that it is completely agnostic and should work with all projects using this setup.
{
...
"scripts: {
"build": "rollup -c",
"autobuild": "rollup -cw",
"test:browser": "npm run build && w3 test/public",
"test": "node test/runner.js",
"pretest": "npm run build"
}
}