How to Run End-to-End Tests with WebdriverIO in the Chrome Extension Boilerplate
The project ships a complete WebdriverIO v9 setup that packages your extension into a ZIP file, injects it into real Chrome or Firefox instances, and executes automated tests using pnpm e2e or pnpm e2e:firefox.
The jonghakseo/chrome-extension-boilerplate-react-vite repository provides a production-ready testing framework for browser extensions. Understanding how to run end-to-end tests with WebdriverIO ensures your extension behaves correctly in real browser environments before deployment.
Prerequisites and Test Workflow Overview
Before executing tests, the workflow requires a packaged extension artifact. The test runner follows a three-stage process:
- Package – Build and compress the extension into a distributable ZIP (or XPI for Firefox)
- Configure – Load the built extension into WebdriverIO browser capabilities
- Execute – Run the test suite against the injected extension in a real browser
This approach validates the actual user experience rather than mocking browser APIs.
Packaging the Extension for Testing
Building the Distribution Archive
The pnpm zip command triggers the build pipeline and creates an archive in the dist-zip directory. For Chrome, this produces a .zip file; for Firefox, it generates an .xpi file.
# Build and package for Chrome (default)
pnpm zip
# The output appears in dist-zip/<name>.zip
The WebdriverIO configuration dynamically reads the latest file from dist-zip, eliminating manual path updates between test runs.
Configuring WebdriverIO for Chrome Extensions
Base Configuration (wdio.conf.ts)
The file tests/e2e/config/wdio.conf.ts establishes the foundation for all test executions. It defines the test file locations, framework settings (Mocha), and global timeouts.
Key responsibilities include:
- Specifying the test file pattern (
tests/e2e/specs/*.ts) - Configuring Mocha options and retry logic
- Setting default timeout values for asynchronous operations
Browser-Specific Configuration (wdio.browser.conf.ts)
The tests/e2e/config/wdio.browser.conf.ts file extends the base configuration and handles the critical task of injecting the built extension into the browser session.
For Chrome, it encodes the ZIP file as Base64 and passes it via goog:chromeOptions.extensions:
// Simplified logic from wdio.browser.conf.ts
const extensionPath = getLatestZipFromDistZip();
const extensionBase64 = fs.readFileSync(extensionPath).toString('base64');
capabilities: {
browserName: 'chrome',
'goog:chromeOptions': {
extensions: [extensionBase64]
}
}
For Firefox, it utilizes the browser.installAddOn command after session initialization to load the XPI file.
The configuration also exposes a helper command getExtensionPath() that allows tests to retrieve the extension ID or URL for interaction.
Running End-to-End Tests with WebdriverIO
Testing Against Chrome
Execute the complete test suite against Chrome using the npm script wrapper:
# Runs pnpm zip, then turbo e2e, then wdio
pnpm e2e
This command ensures the extension is freshly built before testing begins.
Testing Against Firefox
For Firefox compatibility testing, use the dedicated Firefox script:
# Sets IS_FIREFOX=true, builds, and runs tests
pnpm e2e:firefox
The IS_FIREFOX environment flag triggers the Firefox-specific capabilities in wdio.browser.conf.ts.
Running Individual Spec Files
During development, run a single test file directly to speed up debugging:
# Bypass the npm scripts and run wdio directly with a specific spec
pnpm dlx wdio run tests/e2e/config/wdio.browser.conf.ts --spec tests/e2e/specs/page-popup.test.ts
This approach skips the build step, so ensure you have run pnpm zip recently.
CI/CD Integration and Environment Flags
The WebdriverIO configuration adapts its behavior based on environment variables, enabling seamless local and CI execution:
IS_CI: When set totrue, the configuration runs browsers in headless mode and increasesmaxInstancesto parallelize tests across multiple browser sessions. This optimizes execution speed in GitHub Actions or other CI environments.IS_FIREFOX: Switches the browser capability from Chrome to Firefox and adjusts the extension loading mechanism accordingly.
The .github/workflows/e2e.yml file demonstrates this integration, executing pnpm e2e and pnpm e2e:firefox in a GitHub Actions runner with the appropriate environment flags set.
Summary
- Package first: Always run
pnpm zipto create the distributable archive indist-zipbefore testing. - Configuration layers:
wdio.conf.tsprovides base settings, whilewdio.browser.conf.tshandles browser-specific extension injection via Base64 encoding (Chrome) orinstallAddOn(Firefox). - Execution commands: Use
pnpm e2efor Chrome andpnpm e2e:firefoxfor Firefox; both automatically handle the build step. - Environment adaptability: The
IS_CIandIS_FIREFOXflags ensure tests run optimally in both local development and continuous integration pipelines.
Frequently Asked Questions
How do I debug a failing WebdriverIO test in this project?
Run a single spec file directly using pnpm dlx wdio run tests/e2e/config/wdio.browser.conf.ts --spec <path-to-spec>. This bypasses the full suite and build steps, allowing you to focus on the failing test. You can also add debugger statements in your test code and run with the --inspect flag for Node.js debugging.
Can I run end-to-end tests with WebdriverIO against both Chrome and Firefox simultaneously?
The current npm scripts run browsers sequentially, but you can create a custom script that executes both pnpm e2e and pnpm e2e:firefox in parallel terminals or CI jobs. The wdio.browser.conf.ts dynamically selects the browser based on the IS_FIREFOX environment variable, ensuring the correct extension format (ZIP vs XPI) is loaded for each browser.
What is the purpose of the wdio.browser.conf.ts file compared to the base wdio.conf.ts?
The wdio.conf.ts file contains framework-agnostic settings like test file patterns, Mocha timeouts, and reporter configurations. The wdio.browser.conf.ts extends this base and adds browser-specific logic: it locates the latest extension package in dist-zip, encodes it for the target browser (Base64 for Chrome, binary for Firefox), and injects it into the browser capabilities before the session starts.
How does the project handle extension IDs when running WebdriverIO tests?
The wdio.browser.conf.ts configuration adds a custom WebdriverIO command getExtensionPath() that extracts the extension ID from the browser session after the extension is loaded. This allows test files in tests/e2e/specs/ to navigate to specific extension pages (like the popup or options page) using the dynamic chrome-extension://<id>/ URL pattern, ensuring tests work regardless of the randomly generated extension ID.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →