# CucumberJS JSON Reporter

> A WebdriverIO reporter that creates CucumberJS JSON files

## What does it do[​](#what-does-it-do "Direct link to What does it do")

This reporter will generate a **Cucumber JSON file** for each feature that is being tested. The JSON file can be used with whatever report you want to use like for example [multiple-cucumber-html-reporter](https://github.com/WasiqB/multiple-cucumber-html-reporter).

**Note:** Cucumber keeps its JSON format in maintenance mode since [cucumber-js 7.3.0](https://github.com/cucumber/cucumber-js/blob/v7.3.0/CHANGELOG.md#730-2021-06-17) (June 2021): the format gets no new features, but it is not removed. Cucumber recommends its [`message` formatter](https://github.com/cucumber/cucumber-js/blob/v13.3.0/docs/formatters.md#json) for new tools. Report tools such as [multiple-cucumber-html-reporter](https://github.com/WasiqB/multiple-cucumber-html-reporter), which is actively maintained (4.5.0 in October 2026), read only the JSON format ([NDJSON support is an open request](https://github.com/WasiqB/multiple-cucumber-html-reporter/issues/193)), and this reporter writes it.

It will also add metadata about the running instance to the feature file and last but not least, it will give you the opportunity to add attachments to the JSON output.

The JSON follows the Cucumber JSON format: the reporter reads the line numbers of the scenarios, steps and tags from the feature files, and hooks are steps with `hidden: true`. It also adds `metadata` to each feature and `embeddings` (attachments) to the steps, which [multiple-cucumber-html-reporter](https://github.com/WasiqB/multiple-cucumber-html-reporter) uses. When a worker runs several feature files (grouped specs), the reporter writes one file for each feature.

With `cucumberOpts.order: 'random'`, the examples of a Scenario Outline whose name has no `<placeholder>` can get the line of another row of the Examples table.

With the Cucumber `retry` option, a scenario has only the steps of its last try, as in the JSON of Cucumber.

The reporter needs the steps of the scenarios. With `cucumberOpts.scenarioLevelReporter: true`, the framework reports no steps: the reporter logs a warning and makes no report.

## Installation[​](#installation "Direct link to Installation")

The easiest way is to keep `@wdio/cucumberjs-json-reporter` as a devDependency in your `package.json`, via:

```
npm install @wdio/cucumberjs-json-reporter --save-dev
```

Instructions on how to install `WebdriverIO` can be found [here](https://webdriver.io/docs/gettingstarted).

## Configuration[​](#configuration "Direct link to Configuration")

Configure the output directory in your wdio.conf.js file:

```
export const config = {

    // ...

    reporters: [

        // Like this with the default options, see the options below

        'cucumberjs-json',



        // OR like this if you want to set the folder

        [ 'cucumberjs-json', {

                jsonFolder: '.tmp/new/',

            },

        ],

    ],

  // ...

}
```

> DON'T USE BOTH WAYS OF ADDING THE REPORTER, THIS IS JUST AN EXAMPLE!

## Options[​](#options "Direct link to Options")

### `jsonFolder`[​](#jsonfolder "Direct link to jsonfolder")

* **Type:** `String`
* **Mandatory:** No
* **Default:** `.tmp/json/`

The directory where the JSON files, generated by this report, will be stored, relative from where the script is started.

**N.B.:** If you use a npm script from the command line, like for example `npm run test` the `jsonFolder` will be relative from the path where the script is executed. Executing it from the root of your project will also create the `jsonFolder` in the root of you project.

### `language`[​](#language "Direct link to language")

* **Type:** `String`
* **Mandatory:** No
* **Default:** `cucumberOpts.language`, else `en`

The language in which the Gherkin scenarios are written (defaults to English). The list of language codes and its keywords can be found [here](https://cucumber.io/docs/gherkin/languages/).

A `# language:` header in a feature file is used for that file. For the other files, the reporter uses `cucumberOpts.language`, as Cucumber does: this option is used only when `cucumberOpts.language` is not set, and a different value gives a warning. With an unknown language code, the reporter logs a warning and uses `en`.

### `disableHooks`[​](#disablehooks "Direct link to disablehooks")

* **Type:** `boolean`
* **Mandatory:** No
* **Default:** `false`

Hook details will not be part of generation if this property sets to `true`.

### `reportFilePerRetry`[​](#reportfileperretry "Direct link to reportfileperretry")

* **Type:** `boolean`
* **Mandatory:** No
* **Default:** `true`

When a spec is retried the report will be appended to the existing report file from the previous tries if this property is set to `false`.

With `false`, all the workers of a feature (for example with other capabilities) write one file, `<feature id>.json`. The reporter also adds to the file of an earlier run: remove the `jsonFolder` before a run (see `onPrepare` in [Use it with multiple-cucumber-html-reporter](#use-it-with-multiple-cucumber-html-reporter)). An earlier file that is not valid JSON is kept as `<name>.json.invalid-<time>`, and the reporter writes a new file.

**Example**: `['cucumberjs-json', { jsonFolder: '.tmp/new/', disableHooks: true }]`

## Metadata[​](#metadata "Direct link to Metadata")

As said, this report can automatically store the metadata of the current machine / device the feature has been executed on.

To customize this you can add it by adding the following object to your `capabilities`

```
// Example wdio.conf.js

export const config = {

    //..

    capabilities: [

        {

            browserName: 'chrome',

            // Add this

            'cjson:metadata': {

                // For a browser

                browser: {

                    name: 'chrome',

                    version: '58',

                },

                // for an app

                app: {

                  name: 'name.of.app.ipa',

                  version: '1.2.3',

                },

                device: 'MacBook Pro 15',

                platform: {

                    name: 'OSX',

                    version: '10.12.6'

                }

            },

        },

    ],

};
```

> The metadata object needs to have the `cjson` prefix, otherwise it will not work!

With TypeScript, add `@wdio/cucumberjs-json-reporter` to the `types` in your `tsconfig.json` to type the `cjson:metadata` capability:

```
{

    "compilerOptions": {

        "types": ["node", "@wdio/globals/types", "@wdio/cucumberjs-json-reporter"]

    }

}
```

### Metadata values[​](#metadata-values "Direct link to Metadata values")

#### `metadata.app.name`[​](#metadataappname "Direct link to metadataappname")

* **Type:** `string`

**e.g.:** The name of the app.

#### `metadata.app.version`[​](#metadataappversion "Direct link to metadataappversion")

* **Type:** `string`

**e.g.:** The version of the app.

#### `metadata.browser.name`[​](#metadatabrowsername "Direct link to metadatabrowsername")

* **Type:** `string`
* **Possible values:** `internet explorer | edge | chrome | firefox | safari`

#### `metadata.browser.version`[​](#metadatabrowserversion "Direct link to metadatabrowserversion")

* **Type:** `string`

**e.g.:** The version of the browser, this can be added manual or retrieved during the execution of the tests to get the exact version number.

#### `metadata.device`[​](#metadatadevice "Direct link to metadatadevice")

* **Type:** `string`

**e.g.:** A name that represents the type of device. For example, if you run it on a virtual machine, you can place it here `Virtual Machine`, or the name of the mobile, like for example `iPhone 7 Plus`.

#### `metadata.platform.name`[​](#metadataplatformname "Direct link to metadataplatformname")

* **Type:** `string`
* **Possible values:** `windows | osx | linux | ubuntu | android | ios`

#### `metadata.platform.version`[​](#metadataplatformversion "Direct link to metadataplatformversion")

* **Type:** `string`

**e.g.:** The version of the platform

> The browser name and version come from the capabilities of the session. They replace `browser` of the metadata, which is used only when the session does not give them (else `No metadata.browser.name available`).

> Without `device`, the device is `Device name not known`. Without `platform.name`, the reporter uses the `platformName` of the capabilities (`mac…` gives `osx`, `windows…` gives `windows`), else `Platform name not known`. Without `platform.version`, it uses `appium:platformVersion`, else `Version not known`.

> With an `app` in the capabilities (`appium:app`) or in the metadata, the reporter writes `app` (the file name of the app and `metadata.app.version`) instead of `browser`.

## Attachment[​](#attachment "Direct link to Attachment")

You have the option to attach data to the JSON file in all these hooks / steps:

* Before(All)
* After(All)
* Given
* When
* Then
* And

An attachment from a `BeforeAll` hook goes to the first step of the first scenario of the worker, and an attachment from an `AfterAll` hook to the last step of the last scenario: the Cucumber JSON format has attachments only on steps.

The only thing you need to provide is the following code in your step files.

For ES Modules (ESM)

```
import cucumberJson from '@wdio/cucumberjs-json-reporter';



// Attach a string (if no type is provided it will automatically default to `text/plain`

cucumberJson.attach('just a string');

cucumberJson.attach('just a second string', 'text/plain');



// Attach JSON: an object, or a string that is already JSON (it stays as it is)

cucumberJson.attach({"json-string": true}, 'application/json');

cucumberJson.attach('{"json-string": true}', 'application/json');



// Attach a screenshot in a before hook

cucumberJson.attach(await browser.takeScreenshot(), 'image/png');
```

For CommonJS (CJS)

```
const { attach } = require("@wdio/cucumberjs-json-reporter");



// Attach a string (if no type is provided it will automatically default to `text/plain`

attach('just a string');

attach('just a second string', 'text/plain');



// Attach JSON

attach({"json-string": true}, 'application/json');



// Attach a screenshot in a before hook

attach(await browser.takeScreenshot(), 'image/png');
```

## Use it with multiple-cucumber-html-reporter[​](#use-it-with-multiple-cucumber-html-reporter "Direct link to Use it with multiple-cucumber-html-reporter")

This reporter only creates the JSON files. A reporter runs in each worker, so it cannot create one report for all workers.

To create an HTML report with the [multiple-cucumber-html-reporter](https://github.com/WasiqB/multiple-cucumber-html-reporter) module, add the following to your config file.

* Install the module with

  ```
  npm install multiple-cucumber-html-reporter --save-dev
  ```

* Add this to your configuration file

  ```
  import fs from 'node:fs/promises'

  // Import the module

  import { generate } from 'multiple-cucumber-html-reporter'



  // Example wdio.conf.js

  export const config = {

    //..



    // =====

    // Hooks

    // =====

    /**

     * Gets executed once before all workers get launched.

     */

    onPrepare: () => {

      // Remove the `.tmp/` folder that holds the json and report files

      return fs.rm('.tmp/', { recursive: true, force: true });

    },

    /**

     * Gets executed after all workers got shut down and the process is about to exit.

     */

    onComplete: () => {

      // Generate the report when all tests are done. Return the promise:

      // without it, WebdriverIO can exit before the report is written

      return generate({

        // Required

        // This part needs to be the same path where you store the JSON files

        // default = '.tmp/json/'

        jsonDir: '.tmp/json/',

        reportPath: '.tmp/report/',

        // for more options see https://multiple-cucumber-html-reporter.com/docs/options

      });

    }

  }
  ```

## Parallel mode[​](#parallel-mode "Direct link to Parallel mode")

The reporter does not support [`cucumberOpts.parallelMode`](https://webdriver.io/docs/parallel-tests) yet. When scenarios run at the same time, steps and attachments can be in the wrong scenario of the JSON file, and the reporter logs a warning.

## Older WebdriverIO Versions[​](#older-webdriverio-versions "Direct link to Older WebdriverIO Versions")

This package supports WebdriverIO v10 and later. For WebdriverIO v9, use the community package [`wdio-cucumberjs-json-reporter`](https://github.com/webdriverio-community/wdio-cucumberjs-json-reporter). To move from that package to this one, see the [v10 migration guide](https://webdriver.io/docs/v10-migration#cucumber-json-reporter).

> This module only creates the JSON files, not a report. To create an HTML report, see [Use it with multiple-cucumber-html-reporter](#use-it-with-multiple-cucumber-html-reporter).
