# Jest reporter

> Send every Jest test result to Probara from any CI with @probara/jest-reporter — install, configure and see your runs.

`@probara/jest-reporter` is a [Jest](https://jestjs.io) reporter that sends every test result of a
`jest` command to Probara: each attempt with its status, duration and error, linked to its test
case, with the steps, attachments and links your tests add. Cases that are missing are created, and
the run is closed once everything is in.

It is open source, published on [npm](https://www.npmjs.com/package/@probara/jest-reporter) at
`0.1.0`, and lives in the
[probara-sdk repository](https://github.com/cynch-me/probara-sdk/tree/main/packages/jest-reporter).
Before 1.0, a minor version may bring breaking changes: pin the version
([upgrading](https://docs.probara.net/en/developers/ci-integrations/jest/migrating/#upgrading-the-reporter)).

## What you get

- **One result per attempt**, `jest.retryTimes` retries included, with Jest's own verdict:
  `test.failing` is honored, and `test.skip` and `test.todo` are sent as skipped.
- **The same automation keys as `probara import junit`** on jest-junit output, so switching from
  the JUnit import keeps every case and its history.
- **Linking** by a case id in a test or `describe` title (`SHOP-12 adds an item`) or with
  `probara.id()`.
- **Test helpers** that work in every Jest worker, in `node` and `jsdom` alike:
  `probara.step()`, `probara.attach()`, `probara.link()`, `probara.issue()`,
  `probara.parameters()`, and the title, suite, tags and fields of a new case.
- **Console output** of each test as attachments, and **run selection**: run only the tests of a
  run created in Probara.
- **Runs** with a name, environment, milestone, test plan, configurations and tags; one run for
  every shard of a sharded job; one run per `--watch` session.
- **It never breaks your test run.** A reporting problem is logged, never thrown, and Jest's exit
  code stays the tests' own. What could not be sent can be kept in a file and sent later.

## Before you start

| You need                                              | Why                                                                                                                          |
| ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Node.js 22.12 or later                                | The package's `engines` range.                                                                                               |
| Jest 29.6 or later                                    | The peer range: 29.6 is the first Jest that tells a reporter when each test starts. Tested on 29.7 and the latest 30.        |
| jest-circus, Jest's default test runner               | The `probara.*` helpers and the setup file read its state. Under `testRunner: 'jest-jasmine2'` tests report, helpers do not. |
| A paid plan (**Pro** or **Enterprise**, or any trial) | Reporting from CI is not part of the Free plan. On Free, Probara answers `403 forbidden`.                                    |
| A Probara **owner** or **admin**                      | Only owners and admins create and revoke app tokens.                                                                         |
| The **Project ID** to report into                     | Such as `SHOP`: a capital letter, then capital letters or digits.                                                            |

## 1. Create an app token

The reporter signs in with an [app token](https://docs.probara.net/en/developers/authentication/#app-tokens): a token that
belongs to your organization, not to a person. It uses no seat and keeps working when the person
who created it leaves.

1. In Probara, open **Workspace › Integrations** and select the **Jest** card.
2. Open the **Access tokens** tab and select **Create an app token**.
3. Enter a **Token name** after what uses it (the repository or the pipeline) and select
   **Create token**.
4. Select **Copy token** in **Copy your new token**. It is shown once: store it right away as a CI
   secret named `PROBARA_API_TOKEN`.

The [Jest integration guide](https://docs.probara.net/en/guides/integrations/jest/) covers the card, managing and revoking
tokens, and what Probara shows for runs an app token creates.

## 2. Install the reporter

```bash
npm install --save-dev @probara/jest-reporter
```

## 3. Add it to the Jest config

Add the reporter after `default` (the one you read in the terminal), with your Project ID:

```js
// jest.config.js
module.exports = {
  reporters: ['default', ['@probara/jest-reporter', { projectId: 'SHOP' }]],
};
```

A config that is an ES module (`jest.config.mjs`, or `jest.config.js` in a package with
`"type": "module"`) exports the same entry:

```js
// jest.config.mjs
export default {
  reporters: ['default', ['@probara/jest-reporter', { projectId: 'SHOP' }]],
};
```

You can leave `projectId` out and set `PROBARA_PROJECT` in the environment instead. The token never
goes in the config: the config is committed, and the reporter reads the token from
`PROBARA_API_TOKEN`.

### The setup file

Two features need to act inside each test file, so they need the reporter's setup file:
[`captureOutput`](https://docs.probara.net/en/developers/ci-integrations/jest/steps-and-attachments/#console-output) (the
console output of each test) and [run selection](https://docs.probara.net/en/developers/ci-integrations/jest/run-selection/).
Add it once; without those features turned on, it does nothing:

```js
// jest.config.js
module.exports = {
  reporters: ['default', ['@probara/jest-reporter', { projectId: 'SHOP' }]],
  setupFilesAfterEnv: ['@probara/jest-reporter/setup'],
};
```

Everything else, the `probara.*` helpers included, works without it.

## 4. Run your tests with the token

Give the step that runs `jest` the secret. In GitHub Actions:

```yaml
- name: Run Jest tests
  run: npx jest
  env:
    PROBARA_API_TOKEN: ${{ secrets.PROBARA_API_TOKEN }}
```

There is no separate upload step: the reporter sends the results at the end of the same command.
[CI providers](https://docs.probara.net/en/developers/ci-integrations/jest/ci-providers/) has complete pipelines for GitHub
Actions, GitLab CI, Jenkins, CircleCI, Azure Pipelines, Bitbucket Pipelines and Buildkite.

## What you see

Without a token and a project the reporter stays off and quiet, so local runs send nothing. In CI it
logs on stderr, in `[probara]` lines, and ends with the link to the run:

```text
$ npx jest
[probara] Sending 3 results of 3 tests (3 passed, 0 failed, 0 skipped, 0 blocked)
[probara] Recorded 3 results (2 new cases, 0 unmatched) in R-1 (closed): https://app.probara.net/projects/SHOP/runs/R-1
```

In Probara, the run appears in the project's run list as an automated run, named after the CI build
(such as `Jest #42`), with its branch, commit and build URL. It shows the **Jest** app and the
token's name (such as **Jest · unit-ci**) instead of a person.

## How Jest maps to Probara

| Jest                                                 | In Probara                                                                |
| ---------------------------------------------------- | ------------------------------------------------------------------------- |
| A test                                               | A test case, matched by its automation key or linked by a case id         |
| Each attempt (`jest.retryTimes` retries too)         | A result in the run, with its status, duration, start time and error      |
| `test.skip`, `test.todo`, a skipped `describe`       | A skipped result (`Todo` in the notes of a todo)                          |
| `probara.step()` calls                               | The steps of the result, nested, with their status, duration and error    |
| `probara.attach()`, the console with `captureOutput` | Files of the result, or of the step they were attached in                 |
| `probara.link()`, `probara.issue()`                  | Links of the result                                                       |
| Other `probara.*` calls in the test                  | The title, suite, tags, fields and steps of a new case; result parameters |
| A test file whose `afterAll` hook throws             | One more failed result, as jest-junit writes it                           |
| The `jest` command                                   | One automated run, named after the CI build, closed at the end            |

A test file Jest cannot run (a syntax error, a failing import) has no tests to report: the reporter
names it in one warning.

## Same cases as the JUnit import

The reporter gives each test the automation key `probara import junit` gives it on the report of
[jest-junit](https://github.com/jest-community/jest-junit) written with
`JEST_JUNIT_ADD_FILE_ATTRIBUTE=true`: the test file, then `>` between spaces, then the `describe`
blocks and the title joined by spaces, without the case ids. For these two test files:

```js
// tests/cart.test.js
describe('cart', () => {
  test('SHOP-12 adds an item', () => {
    expect([1, 2]).toHaveLength(2);
  });

  test('removes an item', () => {
    expect([1].filter((item) => item !== 1)).toEqual([]);
  });
});
```

```js
// tests/login.test.js
describe('login', () => {
  test('logs in with a valid password', () => {
    expect('secret').toHaveLength(6);
  });
});
```

the reporter sends:

```json
[
  {
    "automationKey": "tests/cart.test.js > cart adds an item",
    "caseDisplayId": "SHOP-12",
    "status": "passed"
  },
  { "automationKey": "tests/cart.test.js > cart removes an item", "status": "passed" },
  {
    "automationKey": "tests/login.test.js > login logs in with a valid password",
    "status": "passed"
  }
]
```

If your jest-junit reports had no file attribute (its default), set `keyIncludesFile: false`: the
keys then leave the file out, like those reports. Either way a test keeps its case and its history
when you switch ([migrating from the JUnit import](https://docs.probara.net/en/developers/ci-integrations/jest/migrating/#from-the-junit-import)).

## Reporting never breaks your test run

The reporter never throws into Jest and never changes its exit code: a failed test fails the
command, a reporting problem does not. Every problem (a wrong setting, Probara unreachable, a
refused token) is logged on stderr, never with the token, and the tests keep their outcome.
`probara.*` calls never throw into a test either: a call Probara cannot use is left out with a
warning. There is no option to fail the command on a reporting error; to keep what could not be
sent, set a [results file](https://docs.probara.net/en/developers/ci-integrations/jest/results-and-retries/#results-file).

## Reference

| Page                                                                                | What it covers                                                                                |
| ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| [Configuration](https://docs.probara.net/en/developers/ci-integrations/jest/configuration/)                 | Every option, its variable, type and default; precedence; network, proxies and watch mode     |
| [Linking tests to cases](https://docs.probara.net/en/developers/ci-integrations/jest/linking/)              | Case ids in titles and describes, `probara.id()`, automation keys, `test.each`                |
| [Metadata and links](https://docs.probara.net/en/developers/ci-integrations/jest/metadata/)                 | Title, suite, comment, tags, fields, parameters, ignoring an attempt; links and issues        |
| [Steps and attachments](https://docs.probara.net/en/developers/ci-integrations/jest/steps-and-attachments/) | `probara.step()`, `probara.attach()`, console output, limits                                  |
| [Results and retries](https://docs.probara.net/en/developers/ci-integrations/jest/results-and-retries/)     | Run options, statuses, retries, the results file, assigning failed results                    |
| [Run selection](https://docs.probara.net/en/developers/ci-integrations/jest/run-selection/)                 | `runCasesOnly`: run only the tests of a Probara run                                           |
| [Sharding and projects](https://docs.probara.net/en/developers/ci-integrations/jest/sharding/)              | One run for every shard; Jest `projects`; several Probara projects                            |
| [CI providers](https://docs.probara.net/en/developers/ci-integrations/jest/ci-providers/)                   | GitHub Actions, GitLab CI, Jenkins, CircleCI, Azure Pipelines, Bitbucket Pipelines, Buildkite |
| [Troubleshooting](https://docs.probara.net/en/developers/ci-integrations/jest/troubleshooting/)             | Problems and their solutions, every line the reporter logs, debugging                         |
| [Migrating](https://docs.probara.net/en/developers/ci-integrations/jest/migrating/)                         | From the JUnit import, Qase, Test IT, ReportPortal, Allure and TestRail; upgrading            |

Related: [CI integrations overview](https://docs.probara.net/en/developers/ci-integrations/) ·
[Playwright reporter](https://docs.probara.net/en/developers/ci-integrations/playwright/) ·
[Cypress reporter](https://docs.probara.net/en/developers/ci-integrations/cypress/) ·
[Vitest reporter](https://docs.probara.net/en/developers/ci-integrations/vitest/) ·
[CLI](https://docs.probara.net/en/developers/cli/) · [Jest integration guide](https://docs.probara.net/en/guides/integrations/jest/) ·
[Source on GitHub](https://github.com/cynch-me/probara-sdk/tree/main/packages/jest-reporter)
