A custom Jest reporter that generates Flakiness Reports from your Jest test runs. The reporter converts Jest test results into the standardized Flakiness JSON format, capturing test outcomes, retries, system utilization, and environment information.
- Requirements
- Installation
- Quick Start
- Recommended Jest Config
- Uploading Reports
- Viewing Reports
- Features
- Configuration Options
- Environment Variables
- Example Configuration
- Node.js 20.17.0 or higher (22.9.0 or higher on Node 22)
- Jest 27 or higher, using the jest-circus runner (Jest's default since 27). The legacy
jest-jasmine2runner is not supported. - Node.js project with a git repository (for commit information)
- Valid Flakiness.io access token (for uploads)
npm install -D @flakiness/jestAdd the reporter to your Jest config:
// jest.config.mjs
export default {
testLocationInResults: true,
reporters: [
'default',
['@flakiness/jest', { flakinessProject: 'my-org/my-project' }],
],
};Note
Include 'default' (or another built-in reporter) alongside the flakiness reporter to retain Jest's standard terminal output — Jest only uses the reporters listed in the reporters array.
Run your tests. The report will be automatically generated in the ./flakiness-report folder:
npx jestView the interactive report:
npx flakiness show ./flakiness-reportTwo Jest flags are strongly recommended to get the most out of this reporter:
// jest.config.mjs
export default {
testLocationInResults: true,
reporters: ['default', ['@flakiness/jest', {}]],
};testLocationInResults: true— populatesassertion.locationso the report can pin each test to its exact file and line in your source.jest.retryTimes(n, { logErrorsBeforeRetry: true })— when retries are enabled, this flag preserves the error from each prior attempt. Without it, Jest drops those errors and the retry attempts in the report carry the correct count but emptyerrors[]arrays.
Reports are automatically uploaded to Flakiness.io after test completion. Authentication is resolved in the following order, and the first available method wins:
-
Access token: Provide a token via the
tokenoption or theFLAKINESS_ACCESS_TOKENenvironment variable. -
GitHub OIDC: When running in GitHub Actions with no access token, the reporter can authenticate using GitHub's OIDC token. This requires three conditions:
- The
flakinessProjectoption must be set to your Flakiness.io project identifier (org/project). - The Flakiness.io project must be bound to the GitHub repository that runs the GitHub Actions workflow.
- The workflow must grant the
id-token: writepermission.
- The
-
GitLab OIDC: When running in GitLab CI/CD with no access token, the reporter can authenticate using a GitLab ID token. GitLab mints ID tokens when the job starts, so the job must declare one named
FLAKINESS_ID_TOKENwhose audience is your project identifier:test: id_tokens: FLAKINESS_ID_TOKEN: aud: my-org/my-project # must match the `flakinessProject` option script: - npx jest
The
flakinessProjectoption must be set, and the Flakiness.io project must be bound to the GitLab project running the pipeline.
If no method is available the upload is skipped, and if an upload fails the report is still available locally in the output folder. Either way the test run is unaffected.
After test execution:
npx flakiness show ./flakiness-reportSee features.md for this reporter's status against the Flakiness Report spec.
When testLocationInResults: true is set in your Jest config, the reporter records the exact file, line, and column for each test. This enables precise navigation from the Flakiness.io dashboard back to your source code.
When retries are enabled via jest.retryTimes(n), the reporter emits one RunAttempt per invocation — the correct attempt count is always preserved. To also capture the error from each prior attempt (not just the final one), pass { logErrorsBeforeRetry: true }:
jest.retryTimes(3, { logErrorsBeforeRetry: true });Without this option, Jest discards prior-attempt errors and the synthesized retry attempts carry no error details.
The reporter extracts trailing @word tokens from test titles into tags:
describe('api tests @api', () => {
test('login @smoke @regression', () => { /* ... */ });
});The test above is tagged with api, smoke, and regression. Rules:
- Tags must be trailing —
test('ping @alice in slack', ...)does not extractalice. @embedded inside a word (alice@example.com) is never a tag.
Jest allows tests with identical names in the same describe block. Flakiness.io, however, considers two tests duplicates when they share the same suite hierarchy, title, and environment, because each test's history is keyed off its full name.
When the reporter detects duplicate full names, it warns and handles them according to the duplicates option.
For each Jest project (configured via projects: [...]), the reporter creates a unique environment. The environment name comes from the project's displayName; if missing, it defaults to "jest". If two projects share a displayName, subsequent environments are suffixed (2), (3), and so on, so every environment is distinctly labeled.
The test environment (node, jsdom, or a custom environment) is recorded under metadata.testEnvironment.
Environment variables prefixed with FK_ENV_ are automatically included in the environment metadata. The prefix is stripped and the key is converted to lowercase.
Example:
export FK_ENV_DEPLOYMENT=staging
export FK_ENV_REGION=us-east-1Results in environment metadata:
{
"metadata": {
"deployment": "staging",
"region": "us-east-1"
}
}Flakiness.io creates a dedicated history for tests executed in each unique environment — tests run with FK_ENV_DEPLOYMENT=staging get a separate timeline from tests run with FK_ENV_DEPLOYMENT=production.
The reporter automatically detects CI environments and includes:
- CI run URLs (GitHub Actions, Azure DevOps, Jenkins, GitLab CI)
- Git commit information
- System metadata (OS name, version, arch)
- CPU and RAM utilization sampled during the run
Optional human-readable report title. Typically used to name a CI run, matrix shard, or other execution group. Defaults to the FLAKINESS_TITLE environment variable, or empty otherwise.
reporters: [
['@flakiness/jest', { title: 'smoke tests run' }]
]The Flakiness.io project identifier in org/project format. Required for CI OIDC authentication. When set, and when the Flakiness.io project is bound to the repository running the pipeline, the reporter authenticates uploads via a GitHub Actions or GitLab CI/CD OIDC token with no access token required. See Uploading Reports for the per-provider requirements.
reporters: [
['@flakiness/jest', { flakinessProject: 'my-org/my-project' }]
]Custom Flakiness.io endpoint URL for uploading reports. Defaults to the FLAKINESS_ENDPOINT environment variable, or https://flakiness.io if not set.
reporters: [
['@flakiness/jest', { endpoint: 'https://custom.flakiness.io' }]
]Access token for authenticating with Flakiness.io when uploading reports. Defaults to the FLAKINESS_ACCESS_TOKEN environment variable. If no token is provided, the reporter falls back to CI OIDC on GitHub Actions and GitLab CI/CD.
reporters: [
['@flakiness/jest', { token: 'your-access-token' }]
]Directory path where the Flakiness report will be written. Defaults to the FLAKINESS_OUTPUT_DIR environment variable, or flakiness-report in the current working directory.
reporters: [
['@flakiness/jest', { outputFolder: './test-results/flakiness' }]
]Controls how the reporter handles tests with duplicate full names. Defaults to 'fail'.
'fail'(default): Duplicates are collapsed into a single failing test with a descriptive error and adupeannotation. The first duplicate absorbs the error; the remaining ones have their attempts stripped. This is the recommended mode — it surfaces the problem so you can fix it by renaming your tests.'rename': Duplicates are automatically renamed by appending a suffix (e.g.,– dupe #2,– dupe #3) to their titles. Each renamed test receives adupeannotation on all its attempts. The first test keeps its original title; only subsequent duplicates are renamed.
Warning
The 'rename' mode is not recommended for regular use. Rename ordering depends on the order Jest reports duplicates, which may shift between runs — so the same duplicate can end up with different suffixes and broken history.
reporters: [
['@flakiness/jest', { duplicates: 'rename' }]
]When true, the report is written locally but not uploaded to Flakiness.io. Can also be controlled via the FLAKINESS_DISABLE_UPLOAD environment variable.
reporters: [
['@flakiness/jest', { disableUpload: true }]
]FLAKINESS_TITLE: Human-readable report title (equivalent totitleoption)FLAKINESS_ACCESS_TOKEN: Access token for Flakiness.io uploads (equivalent totokenoption)FLAKINESS_ENDPOINT: Custom Flakiness.io endpoint URL (equivalent toendpointoption)FLAKINESS_OUTPUT_DIR: Output directory for reports (equivalent tooutputFolderoption)FLAKINESS_DISABLE_UPLOAD: When set, disables report uploads (equivalent todisableUploadoption)FLAKINESS_ID_TOKEN: GitLab CI/CD ID token used for OIDC authentication. Set by GitLab for jobs that declare it underid_tokens:(see Uploading Reports)FK_ENV_*: EachFK_ENV_<KEY>env var is added toenvironment.metadataas{ <key>: <value> }(prefix stripped, key lowercased)
A complete example with all options:
// jest.config.mjs
export default {
testLocationInResults: true,
reporters: [
'default',
['@flakiness/jest', {
title: 'My Test Run',
flakinessProject: 'my-org/my-project',
endpoint: process.env.FLAKINESS_ENDPOINT,
token: process.env.FLAKINESS_ACCESS_TOKEN,
outputFolder: './flakiness-report',
duplicates: 'fail',
disableUpload: false,
}],
],
};