npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jm-wdio-failed-rerun-runner

v0.0.1

Published

A WebdriverIO helper that reruns only tests that failed in the initial run.

Readme

jm-wdio-failed-rerun-runner

jm-wdio-failed-rerun-runner runs a normal WebdriverIO pass first, records tests that fail, and then starts focused rerun passes for only those failed tests.

The package is useful when you want a rerun step after the main run finishes, instead of framework-level retries during the test body.

Installation

npm install --save-dev jm-wdio-failed-rerun-runner

A runnable demo project lives in example/.

Usage

Run it from the CLI:

npx wdio-failed-rerun-runner run ./wdio.conf.ts

CLI options:

  • --max-reruns <count>: maximum focused rerun rounds. Defaults to 1.
  • --no-pass-on-successful-rerun: keep the initial failing exit code even when focused reruns pass.
  • --manifest-path <path>: write the initial-run failure manifest to a known path.
  • --rerun-manifest-path <path>: write rerun failure manifests to a known path.

Example

Run an initial test suite with up to two focused rerun rounds and store manifest files:

npx wdio-failed-rerun-runner run ./wdio.conf.ts \
  --max-reruns 2 \
  --manifest-path ./artifacts/initial-failures.ndjson \
  --rerun-manifest-path ./artifacts/rerun-failures.ndjson

If two tests failed in the first run, only those specs/titles are rerun:

{
  "attempt": "initial",
  "framework": "mocha",
  "spec": "./test/specs/login.spec.ts",
  "fullTitle": "login flow should login with valid credentials"
}

Or call the public API from Node.js:

import { runFailedTestsRerun } from 'jm-wdio-failed-rerun-runner'

const result = await runFailedTestsRerun('./wdio.conf.ts', {
    maxReruns: 1
})

process.exit(result.exitCode)

How It Works

  1. The launcher sets WDIO_FAILED_RERUN_RETRY=0 and injects FailedTestRerunService into the first WDIO run. The service is injected by the absolute path of the built service entry (exported as FAILED_RERUN_SERVICE_PATH), so it loads regardless of the installed package name. Because the path points into the package's build directory on disk, bundling this package into another artifact is not supported.
  2. The worker service records failed Mocha afterTest events and Cucumber afterScenario events into an NDJSON manifest.
  3. If the first run passes, the launcher exits with 0 and does not rerun anything.
  4. If the first run fails and the manifest contains failures, the launcher groups failures by framework and spec.
  5. Each group is rerun with WDIO_FAILED_RERUN_RETRY set to the focused rerun round, one spec value, and a framework-specific exact-title filter: mochaOpts.grep for Mocha, or cucumberOpts.name for Cucumber scenarios.
  6. If maxReruns is greater than 1, later rounds are planned only from failures that still failed in the previous round.

The implementation is deliberately a small sequential orchestration. It does not model runner phases with a state machine.

API

runFailedTestsRerun(configPath, options)

Important options:

  • args: WDIO launcher args to pass into every run.
  • maxReruns: maximum focused rerun rounds. Defaults to 1.
  • passOnSuccessfulRerun: return 0 when focused reruns pass. Defaults to true.
  • manifestPath: manifest path for the initial run. Defaults to a temp file.
  • rerunManifestPath: manifest path for rerun rounds. Defaults to temp files.
  • run: injectable runner function for tests or custom launchers.

The result includes the final exitCode, all run attempts, and unresolved failures.

Advanced callers and tests can create a rerunner with local adapters:

import { createFailedTestsRerunner } from 'jm-wdio-failed-rerun-runner'

const rerunner = createFailedTestsRerunner({
    run: customWdioRun,
    manifests: customManifestStore,
    retryEnv: customRetryEnv
})

const result = await rerunner.run('./wdio.conf.ts')

The default runFailedTestsRerun function is the normal entry point. The factory is for cases that need to substitute the WDIO runner, manifest storage, or retry environment boundary.

During the initial run, workers inherit WDIO_FAILED_RERUN_RETRY=0. During focused reruns, workers inherit WDIO_FAILED_RERUN_RETRY=1 for the first rerun round, 2 for the second, and so on. The launcher restores the previous environment value after each WDIO launch.

Failure Handling

If a worker exits with failure before any failed test is recorded, the launcher keeps the failing exit code and does not guess which tests to rerun.

If a rerun exits with failure but writes no failure records, the final result stays failed. This preserves hard failures such as setup errors, process crashes, and invalid grep filters.

Recorded errors preserve standard Error fields plus serializable cause and custom enumerable properties. This keeps the manifest useful for diagnostics without allowing non-JSON values to break writes.

BrowserStack Support

When the suite runs through @wdio/browserstack-service, focused reruns follow the same environment contract BrowserStack uses for its own failed-test reruns:

  • During each focused rerun the launcher sets BROWSERSTACK_RERUN=true and BROWSERSTACK_RERUN_TESTS=<comma-separated spec files> for that rerun's spec group.
  • The BrowserStack service launcher reads these variables to narrow the run to the failed spec files, and BrowserStack Test Observability tags the rerun build with failed_tests_rerun: true instead of treating it as an unrelated new build.
  • The previous values of both variables are restored after each rerun, so an outer BrowserStack-triggered rerun (for example one started from the Observability dashboard) is not affected during the initial run.
  • BrowserStack parses BROWSERSTACK_RERUN_TESTS by splitting on commas, so a spec path that itself contains a comma cannot be represented. Such reruns still happen, but without the BrowserStack rerun marking.

No extra configuration is needed: keep @wdio/browserstack-service in services in the WDIO config, and run the rerun runner as usual. Projects that do not use BrowserStack are unaffected because nothing else reads these variables.

Advanced callers can substitute the boundary with a custom adapter:

import { createFailedTestsRerunner } from 'jm-wdio-failed-rerun-runner'

const rerunner = createFailedTestsRerunner({
    browserstackEnv: {
        withRerun: (specs, run) => run()
    }
})

Framework Support

Mocha failures are selected by full title with mochaOpts.grep.

Cucumber scenario failures are selected by scenario name with cucumberOpts.name. If a feature file contains duplicate scenario names, WebdriverIO's name filter can still match more than one scenario; use unique scenario names for precise focused reruns.

Development

The source is TypeScript-only. Internal imports use the package #src/* alias, which maps to src during type-checking and to build at runtime.

npm test

npm test builds the package and runs unit plus integration tests.

npm run check

npm run check runs ESLint, type-checks source and tests, then runs the suite with coverage.

npm run coverage

npm run coverage runs Vitest with coverage output.

Failed Rerun Runner Diagram

Execution Flow

flowchart TD
    A["runFailedTestsRerun(configPath, options)"] --> B["Inject FailedTestRerunService"]
    B --> C["Set WDIO_FAILED_RERUN_RETRY=0"]
    C --> D["Run normal WDIO launcher pass"]
    D --> E{"Initial exit code is 0?"}
    E -- "yes" --> F["Return success without rerun"]
    E -- "no" --> G["Read initial NDJSON manifest"]
    G --> H{"Any failed tests recorded?"}
    H -- "no" --> I["Return original failure"]
    H -- "yes" --> J["Group failures by spec file"]
    J --> K["Build exact full-title grep per spec"]
    K --> L["Set WDIO_FAILED_RERUN_RETRY=round+1"]
    L --> M["Run one focused rerun per spec group"]
    M --> N["Read rerun manifests"]
    N --> O{"Failures remain and rounds left?"}
    O -- "yes" --> J
    O -- "no" --> P["Return final exit code and unresolved failures"]

Data Contract

flowchart LR
    A["afterTest(test, result)"] --> B{"result.passed?"}
    B -- "true" --> C["Ignore"]
    B -- "false" --> D["FailedTestRecord"]
    D --> E["NDJSON manifest"]
    E --> F["createRerunSpecPlans(records)"]
    F --> G["{ spec, grep, tests }"]
    G --> H["WDIO args: spec + mochaOpts.grep"]

Key Guarantees

  • Passing tests are not written to the manifest.
  • Initial workers see WDIO_FAILED_RERUN_RETRY=0; first focused rerun workers see 1.
  • Rerun specs are planned from recorded failures, not from all specs in the config.
  • Multiple failed tests in one spec share a single exact-title grep.
  • Later rerun rounds are based only on the previous round's unresolved failures.
  • If failure data is missing, the launcher preserves the failing exit code instead of widening the rerun.