# How to Run End-to-End Tests with WebdriverIO in the Chrome Extension Boilerplate

> Learn to run end-to-end tests with WebdriverIO in the jonghakseo Chrome Extension Boilerplate. Automate testing by injecting your extension into Chrome or Firefox and executing tests efficiently.

- Repository: [JongHak Seo/chrome-extension-boilerplate-react-vite](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite)
- Tags: how-to-guide
- Published: 2026-03-05

---

**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:

1. **Package** – Build and compress the extension into a distributable ZIP (or XPI for Firefox)
2. **Configure** – Load the built extension into WebdriverIO browser capabilities
3. **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.

```bash

# 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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`:

```typescript
// 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:

```bash

# 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:

```bash

# 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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/wdio.browser.conf.ts).

### Running Individual Spec Files

During development, run a single test file directly to speed up debugging:

```bash

# 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 to `true`, the configuration runs browsers in **headless mode** and increases `maxInstances` to 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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/.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 zip` to create the distributable archive in `dist-zip` before testing.
- **Configuration layers**: [`wdio.conf.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/wdio.conf.ts) provides base settings, while [`wdio.browser.conf.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/wdio.browser.conf.ts) handles browser-specific extension injection via Base64 encoding (Chrome) or `installAddOn` (Firefox).
- **Execution commands**: Use `pnpm e2e` for Chrome and `pnpm e2e:firefox` for Firefox; both automatically handle the build step.
- **Environment adaptability**: The `IS_CI` and `IS_FIREFOX` flags 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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/wdio.browser.conf.ts) file compared to the base [`wdio.conf.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/wdio.conf.ts)?

The [`wdio.conf.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/wdio.conf.ts) file contains framework-agnostic settings like test file patterns, Mocha timeouts, and reporter configurations. The [`wdio.browser.conf.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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.