# jest-environment-emit

> Environment with unlimited test event handlers

Latest version **1.2.0** (published 2025-06-10) · MIT license · 0 weekly downloads

## Install

```sh
npm install jest-environment-emit
pnpm add jest-environment-emit
yarn add jest-environment-emit
bun add jest-environment-emit
```

## Health

**Score 40/100 (D)** — status: maintenance-mode.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

Negative: stale; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.2.0 |
| Published | 2025-06-10 |
| First published | 2023-11-02 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=16.14.0 |
| Dependencies | 8 |
| Unpacked size | 102.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 5 |
| Author | Yaroslav Serhieiev |
| Maintainers | yaroslavs |
| Keywords | environment, jest, jest-environment, jest-circus |

## Links

- npm: https://www.npmjs.com/package/jest-environment-emit
- Repository: https://github.com/wix-incubator/jest-environment-emit
- Homepage: https://github.com/wix-incubator/jest-environment-emit#readme
- Issues: https://github.com/wix-incubator/jest-environment-emit/issues
- npm.io page: https://npm.io/package/jest-environment-emit

## Dependencies (8)

- [tslib](https://npm.io/package/tslib.md) ^2.5.3
- [bunyan](https://npm.io/package/bunyan.md) ^2.0.5
- [bunyamin](https://npm.io/package/bunyamin.md) ^1.5.2
- [node-ipc](https://npm.io/package/node-ipc.md) 9.2.1
- [strip-ansi](https://npm.io/package/strip-ansi.md) ^6.0.0
- [lodash.merge](https://npm.io/package/lodash.merge.md) ^4.6.2
- [funpermaproxy](https://npm.io/package/funpermaproxy.md) ^1.1.0
- [bunyan-debug-stream](https://npm.io/package/bunyan-debug-stream.md) ^3.1.0

## Alternatives

- [replicas-cli](https://npm.io/package/replicas-cli.md) — 3.0K weekly downloads
- [env-contract](https://npm.io/package/env-contract.md) — 133 weekly downloads
- [@openveo/api](https://npm.io/package/@openveo/api.md) — 61 weekly downloads
- [@ryniaubenpm2/cumque-error-reiciendis](https://npm.io/package/@ryniaubenpm2/cumque-error-reiciendis.md) — 54 weekly downloads
- [ts-global-type-extra](https://npm.io/package/ts-global-type-extra.md) — 11 weekly downloads

## Recent versions

- 1.2.0 (latest) — 2025-06-10
- 1.0.0-alpha.10 (alpha) — 2023-12-01
- 1.0.8 — 2024-05-17
- 1.0.7 — 2024-02-17
- 1.0.6 — 2024-02-10
- 1.0.5 — 2023-12-28
- 1.0.4 — 2023-12-15
- 1.0.3 — 2023-12-08
- 1.0.2 — 2023-12-08
- 1.0.1 — 2023-12-01
- 1.0.0 — 2023-12-01
- 1.0.0-alpha.9 — 2023-12-01
- 1.0.0-alpha.8 — 2023-12-01
- 1.0.0-alpha.7 — 2023-11-26
- 1.0.0-alpha.6 — 2023-11-26
- … 5 more at https://npm.io/package/jest-environment-emit/versions

## README

<div align="center">

![logo](https://github.com/wix-incubator/jest-environment-emit/assets/1962469/02006bb8-e7e4-45e1-9876-9b11316ed912)

## jest-environment-emit

_Environment with unlimited test event handlers_

[![npm version](https://badge.fury.io/js/jest-environment-emit.svg)](https://badge.fury.io/js/jest-environment-emit)

</div>

## Overview

There can be only one test environment per a project config in Jest unlike test reporters, which can be multiple.

This limitation is not convenient, so this package provides a couple of pre-defined test environments and a way to create custom ones:

* `jest-environment-emit` – exports `WithEmitter`, a higher-order function to create custom environment classes
* `jest-environment-emit/node` – exports `TestEnvironment`, a wrapper over `jest-environment-node`
* `jest-environment-emit/jsdom` – exports `TestEnvironment`, a wrapper over `jest-environment-jsdom`

To wrap a custom environment, use `WithEmitter`:

```js
import { WithEmitter } from 'jest-environment-emit';
// ...
export default WithEmitter(MyEnvironment);
```

## Usage

Assuming you have any test environment wrapped with `jest-environment-emit`, you can add as many event listeners as you want:

```js
/** @type {import('jest').Config} */
module.exports = {
  // ...
  testEnvironment: 'jest-environment-emit/node',
  testEnvironmentOptions: {
    eventListeners: [
      './simple-subscription-1.js',
      ['./parametrized-subscription-2.js', { some: 'options' }],
    ]
  },
};
```

The modules specified in `eventListeners` are required and should export a function with the following signature:

```js
/** @type {import('jest-environment-emit').EnvironmentListenerFn} */
const subscription = function (context, options) {
  context.testEvents
    .on('test_environment_setup', async ({ env }) => {
      // use like TestEnvironment#setup, e.g.:
      env.global.__SOME__ = 'value';
    })
    .on('add_hook', ({ event, state }) => {
      // use like TestEnvironment#handleTestEvent in jest-circus
    })
    .on('run_start', async ({ event, state }) => {
      // use like TestEnvironment#handleTestEvent in jest-circus
    })
    .on('test_environment_teardown', async ({ env }) => {
      // use like TestEnvironment#teardown
    })
    .on('*', ({ type }) => {
        // wildcard listener
        if (type === 'test_start') {
            // ...
        }
    });
};

export default subscription; // module.exports = subscription;
```

For exact type definitions, see [src/types.ts](src/types.ts).

## Library API

### Deriving from classes

This higher-order function can also accept one subscriber function and custom class name:

```js
import { WithEmitter } from 'jest-environment-emit';
// ...
export default WithEmitter(MyEnvironment, 'WithMyListeners', (context, options) => {
  context.testEvents.on('*', ({ type }) => {
    // ...
  });
}); // -> class WithMyListeners(MyEnvironment) { ... }
```

The derived classes have a static method `derive` to continue derivation, e.g.:

```js
import { TestEnvironment } from 'jest-environment-emit/node';

export default TestEnvironment.derive((context, options) => {
  context.testEvents.on('*', ({ type }) => {
    // ...
  });
}, 'WithMyListeners'); // -> class MyTestEnvironment(JestEnvironment) { ... }
```

All derived classes have also a protected property `testEvents` to access the event emitter.

```js
import { TestEnvironment } from 'jest-environment-emit/node';

export class MyTestEnvironment extends TestEnvironment {
  constructor(config, context) {
    super(config, context);

    this.testEvents.on('*', ({ type }) => {
      // ...
    });
  }
}
```

### Using custom priorities

By default, all event listeners are appended to the list. If you need to guarantee the order of execution, you can specify a priority:

```js
/** @type {import('jest-environment-emit').EnvironmentListenerFn} */
const subscription = function (context, options) {
  context.testEvents
    .on('test_environment_setup', async ({ env }) => {
      // make sure this listener is executed first
    }, -1)
    .on('test_environment_teardown', async ({ env }) => {
      // make sure this listener is executed last
    }, 1E6)
};
```

Try to avoid using priorities unless you really need them.

## Troubleshooting

Use `JEST_BUNYAMIN_DIR=path/to/dir` to enable debug logging.

In your `globalTeardown` script, you can aggregate all the logs into a single file for convenience:

```js
// globalTeardown.js
import { aggregateLogs } from 'jest-environment-emit/debug';

module.exports = async () => {
  await aggregateLogs();
};
```

The logs, e.g. `jest-bunyamin.log` is a file viewable with [Perfetto](https://ui.perfetto.dev/) or `chrome://tracing`.

> **Support Policy:** This package is officially tested on Jest 29 and 30. Jest 27/28 may work, but are not guaranteed or tested. Use at your own risk for those versions.

---
_Source: https://npm.io/package/jest-environment-emit · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
