This is a port of jest-puppeteer to Vitest. Some of the documentation may still refer to Jest specific things so please report any issues.
vitest-puppeteer is a Vitest preset designed for seamless integration with Puppeteer, enabling end-to-end testing in a browser environment. With a simple API, it allows you to launch browsers and interact with web pages, making it perfect for testing UI interactions in web applications.
- Getting Started
- Recipes
- vitest-puppeteer Configuration
- API Reference
- Troubleshooting
- Acknowledgements
To start using vitest-puppeteer, you’ll need to install the following packages:
npm install --save-dev vitest-puppeteer puppeteer vitestThis will install Vitest (the testing framework), Puppeteer (the headless browser tool), and vitest-puppeteer (the integration between the two).
In your Vitest configuration file (vitest.config.js), add vitest-puppeteer as the environment and globalSetup:
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
environment: "vitest-environment-puppeteer",
globalSetup: "vitest-environment-puppeteer/global-init",
},
});This will configure Vitest to use Puppeteer for running your tests.
Once you’ve configured Vitest, you can start writing tests using Puppeteer’s page object, which is automatically provided by vitest-puppeteer.
Create a test file (e.g., google.test.js):
import "expect-puppeteer";
describe("Google Homepage", () => {
beforeAll(async () => {
await page.goto("https://google.com");
});
it('should display "google" text on page', async () => {
await expect(page).toMatchTextContent(/Google/);
});
});This example test navigates to Google’s homepage and checks if the page contains the word "Google". vitest-puppeteer simplifies working with Puppeteer by exposing the page object, allowing you to write tests using a familiar syntax.
If you’re using TypeScript, make sure to include vitest-puppeteer to include the necessary type definitions.
import "vitest-puppeteer";
import "expect-puppeteer";
describe("Google Homepage", (): void => {
beforeAll(async (): Promise<void> => {
await page.goto("https://google.com");
});
it('should display "google" text on page', async (): Promise<void> => {
await expect(page).toMatchTextContent(/Google/);
});
});Argos is a powerful tool for visual testing, allowing you to track visual changes introduced by each pull request. By integrating Argos with vitest-puppeteer, you can easily capture and compare screenshots to maintain the visual consistency of your application.
To get started, check out the Puppeteer Quickstart Guide.
Writing tests with Puppeteer’s core API can be verbose. The expect-puppeteer library simplifies this by adding custom matchers, such as checking for text content or interacting with elements. Some examples:
- Assert that a page contains certain text:
await expect(page).toMatchTextContent("Expected text");- Simulate a button click:
await expect(page).toClick("button", { text: "Submit" });- Fill out a form:
await expect(page).toFillForm('form[name="login"]', {
username: "testuser",
password: "password",
});Debugging can sometimes be tricky in headless browser environments. vitest-puppeteer provides a helpful debug() function, which pauses test execution and opens the browser for manual inspection:
await vitestPuppeteer.debug();To prevent the test from timing out, increase Vitest’s timeout:
vi.setTimeout(300000); // 5 minutesThis can be particularly useful when you need to step through interactions or inspect the state of the page during test execution.
If your tests depend on a running server (e.g., an Express app), you can configure vitest-puppeteer to automatically start and stop the server before and after tests:
export default {
server: {
command: "node server.js",
port: 4444,
},
};This eliminates the need to manually manage your server during testing.
You can easily customize the Puppeteer instance used in your tests by modifying the vitest-puppeteer.config.js file. For example, if you want to launch Firefox instead of Chrome:
export default {
launch: {
browser: "firefox",
headless: process.env.HEADLESS !== "false",
},
};This file allows you to configure browser options, set up browser contexts, and more.
vitest-puppeteer supports various configuration formats through cosmiconfig, allowing flexible ways to define your setup. By default, the configuration is looked for at the root of your project, but you can also define a custom path using the VITEST_PUPPETEER_CONFIG environment variable.
Possible configuration formats:
- A
"vitest-puppeteer"key in yourpackage.json. - A
.vitest-puppeteerrcfile (JSON, YAML, or JavaScript). - A
.vitest-puppeteer.config.jsor.vitest-puppeteer.config.cjsfile that exports a configuration object.
Example of a basic configuration file (vitest-puppeteer.config.js):
export default {
launch: {
headless: process.env.HEADLESS !== "false",
dumpio: true, // Show browser console logs
},
browserContext: "default", // Use "incognito" if you want isolated sessions per test
server: {
command: "node server.js",
port: 4444,
launchTimeout: 10000,
debug: true,
},
};You can further extend this configuration to connect to a remote instance of Chrome or customize the environment for your test runs.
vitest-puppeteer exposes several global objects and methods to facilitate test writing:
-
global.browser: Provides access to the Puppeteer Browser instance.Example:
const page = await browser.newPage(); await page.goto("https://example.com");
-
global.page: The default Puppeteer Page object, automatically created and available in tests.Example:
await page.type("#input", "Hello World");
-
global.context: Gives access to the browser context, useful for isolating tests in separate contexts. -
global.expect(page): The enhancedexpectAPI provided byexpect-puppeteer. You can use this to make assertions on the Puppeteerpage.Example:
await expect(page).toMatchTextContent("Expected text on page");
-
global.vitestPuppeteer.debug(): Suspends test execution, allowing you to inspect the browser and debug.Example:
await vitestPuppeteer.debug();
-
global.vitestPuppeteer.resetPage(): Resets thepageobject before each test.Example:
beforeEach(async () => { await vitestPuppeteer.resetPage(); });
-
global.vitestPuppeteer.resetBrowser(): Resets thebrowser,context, andpageobjects, ensuring a clean slate for each test.Example:
beforeEach(async () => { await vitestPuppeteer.resetBrowser(); });
These methods simplify the setup and teardown process for tests, making it easier to work with Puppeteer in a Vitest environment.
In CI environments, tests may occasionally time out due to limited resources. vitest-puppeteer allows you to control the number of workers used to run tests. Running tests serially can help avoid these timeouts:
Run tests in a single process:
vitest run --no-file-parallelismAlternatively, you can limit the number of parallel workers:
vitest run --maxWorkers=2This ensures that your CI environment doesn’t get overloaded by too many concurrent processes, which can improve the reliability of your tests.
Sometimes, failures happen only in CI environments and not locally. In such cases, use the debug() method to open a browser during CI runs and inspect the page manually:
await vitestPuppeteer.debug();To avoid test timeouts in CI, set a larger timeout during the debugging process:
vitest.setTimeout(600000); // 10 minutesvitest-puppeteer introduces global variables like page, browser, context, etc., which ESLint may flag as undefined. You can prevent this by adding these globals to your ESLint configuration:
// .eslintrc.js
export default {
env: {
jest: true,
},
globals: {
page: true,
browser: true,
context: true,
puppeteerConfig: true,
vitestPuppeteer: true,
},
};This configuration will prevent ESLint from throwing errors about undefined globals.
Special thanks to Fumihiro Xue for providing an excellent Jest Puppeteer example, which served as an inspiration for this package.