Test Runner Commands
Run server-side commands for tests with @web/test-runner.
Usage
Install the library:
npm i -D @web/test-runner-helpers
Built-in commands
We provide a set of built-in commands to use during testing.
Viewport
The setViewport
command allows changing the browser's viewport in a test. The function is async and should be awaited.
setViewport
is supported in @web/test-runner-chrome
, -puppeteer
and -playwright
.
View example
import { setViewport } from '@web/test-runner-commands';
describe('my component', () => {
it('works on 360x640', async () => {
await setViewport({ width: 360, height: 640 });
console.log(window.innerWidth);
console.log(window.innerHeight);
});
it('works on 400x800', async () => {
await setViewport({ width: 400, height: 800 });
console.log(window.innerWidth);
console.log(window.innerHeight);
});
});
Emulate media
The emulateMedia
command allows changing browser media queries. The function is async and should be awaited.
emulateMedia
is supported in @web/test-runner-chrome
, -puppeteer
and -playwright
. The reducedMotion
option is not supported by playwright.
View example
import { emulateMedia } from '@web/test-runner-commands';
it('can emulate print media type', async () => {
await emulateMedia({ media: 'print' });
expect(matchMedia('print').matches).to.be.true;
await emulateMedia({ media: 'screen' });
expect(matchMedia('screen').matches).to.be.true;
});
it('can emulate color scheme', async () => {
await emulateMedia({ colorScheme: 'dark' });
expect(matchMedia('(prefers-color-scheme: dark)').matches).to.be.true;
await emulateMedia({ colorScheme: 'light' });
expect(matchMedia('(prefers-color-scheme: light)').matches).to.be.true;
});
it('can emulate reduced motion', async () => {
await emulateMedia({ reducedMotion: 'reduce' });
expect(matchMedia('(prefers-reduced-motion: reduce)').matches).to.be.true;
await emulateMedia({ reducedMotion: 'no-preference' });
expect(matchMedia('(prefers-reduced-motion: no-preference)').matches).to.be.true;
});
Set user agent
The setUserAgent
changes the browser's user agent. The function is async and should be awaited.
setUserAgent
is supported in @web/test-runner-chrome
and -puppeteer
View example
import { setUserAgent } from '@web/test-runner-commands';
it('can set the user agent', async () => {
const userAgent = 'my custom user agent';
expect(navigator.userAgent).to.not.equal(userAgent);
await setUserAgent(userAgent);
expect(navigator.userAgent).to.equal(userAgent);
});
Custom commands
To create a custom command, you first need to add a test runner plugin which implements the executeCommand
function.
This function receives the currently executing command, optional command payload from the browser, and the associated test session. The command runs on the server, giving you access to things like the browser launcher, file system, or any NodeJS libraries you want to use.
By returning a non-null or undefined value from this function, the test runner will assume you have processed it, not call any other plugins and return the return value to the browser. The function can be async.
View example
const fs = require('fs');
function myPlugin() {
return {
name: 'my-plugin',
executeCommand({ command, payload }) {
if (command === 'my-command') {
fs.writeFileSync('./my-file.json', JSON.stringify(payload));
return true;
}
},
};
}
module.exports = {
plugins: [myPlugin()],
};
The executeCommand
function receives the current test session, you can use this to access the browser launcher instance for advanced functionalities not available from the browser. Because there are different kinds of browser launchers, you need to use the type
property to adjust the behavior of your plugin.
View example
export function takeScreenshotPlugin() {
return {
name: 'take-screen-command',
async executeCommand({ command, payload, session }) {
if (command === 'take-screenshot') {
if (session.browser.type === 'puppeteer') {
const page = session.browser.getPage(session.id);
const screenshot = await page.screenshot();
return true;
}
if (session.browser.type === 'playwright') {
const page = session.browser.getPage(session.id);
const screenshot = await page.screenshot();
return true;
}
throw new Error(
`Taking screenshots is not supported for browser type ${session.browser.type}.`,
);
}
return false;
},
};
}
After implementing your plugin, it can be called from the browser using the executeServerCommand
function. Any data passed in the second parameter is received by the server plugin. It should be serializable to JSON.
View example
import { executeServerCommand } from '@web/test-runner-commands';
it('my test', async () => {
await executeServerCommand('my-command');
await executeServerCommand('my-command', { foo: 'bar' });
});