{"id":18285908,"url":"https://github.com/exodusmovement/test","last_synced_at":"2025-04-05T08:30:35.531Z","repository":{"id":252973527,"uuid":"825783273","full_name":"ExodusMovement/test","owner":"ExodusMovement","description":"A runner for node:test, jest, and tape test suites on top of node:test (and any runtime)","archived":false,"fork":false,"pushed_at":"2025-02-19T07:30:46.000Z","size":1242,"stargazers_count":4,"open_issues_count":4,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-21T00:33:10.841Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://npmjs.com/@exodus/test","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ExodusMovement.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-08T13:41:54.000Z","updated_at":"2025-02-19T07:30:50.000Z","dependencies_parsed_at":"2024-08-13T19:28:10.989Z","dependency_job_id":"8d31645b-0aff-4ddb-ba34-71e9944efb90","html_url":"https://github.com/ExodusMovement/test","commit_stats":null,"previous_names":["exodusmovement/test"],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Ftest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Ftest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Ftest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ExodusMovement%2Ftest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ExodusMovement","download_url":"https://codeload.github.com/ExodusMovement/test/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247311266,"owners_count":20918331,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T13:18:09.881Z","updated_at":"2025-04-05T08:30:35.513Z","avatar_url":"https://github.com/ExodusMovement.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @exodus/test\n\nA runner for `node:test`, `jest`, and `tape` test suites on top of `node:test` (and any runtime)\n\n## Features\n\n- Native ESM, including in Jest tests\n- Esbuild on the fly for babelified ESM interop (enable via `--esbuild`)\n- TypeScript support in both transform (through [tsx](https://tsx.is/), enable via `--esbuild`)\n  and typestrip (via `--typescript`) modes\n- Runs on [node:test](https://nodejs.org/api/test.html), and (experimental) on bun, deno, d8, JSC and\n  [Hermes](https://hermesengine.dev)\n- Testsuite-agnostic -- can run any file as long as it sets exit code based on test results\n- Built-in [Jest](https://jestjs.io) compatibility (with `--jest`), including `jest.*` global\n  - Up to ~10x faster depending on the original setup\n  - Actual `expect` module, also `jest-extended` and `jest-when` just work on top\n  - Snapshots, including snapshot matchers\n  - Function and timer mocks\n  - [test.concurrent]()\n  - Module mocks (on top of Node.js runtime only), including for ESM modules\n  - Loads Jest configuration\n  - It works on Hermes too!\n- Built-in network record/replay for offline tests, mocking `fetch` and `WebSocket` sessions\n- `--drop-network` support for guaranteed offline testing\n- Native code coverage via v8 (Node.js or [c8](https://github.com/bcoe/c8)), with istanbul reporters\n- GitHub reporter (auto-enabled by default)\n- JSDOM env support\n- Hanging tests error by default (unlike `jest`)\n- Babel support, picks up your Babel config (enable via `--babel`)\n- Unlike `bun:test`, it runs test files in isolated contexts \\\n  Bun leaks globals / side effects between test files ([ref](https://github.com/oven-sh/bun/issues/6024)),\n  and has incompatible `test()` lifecycle / order\n- Also features a tape API for drop-in replacement\n\n## Reporter samples\n\n#### CLI (but uses colors when output supports them, e.g. in terminal):\n\n```console\n# tests/jest/expect.mock.test.js\n✔ PASS drinkAll \u003e drinks something lemon-flavoured (1.300417ms)\n✔ PASS drinkAll \u003e does not drink something octopus-flavoured (0.191791ms)\n✔ PASS drinkAll (1.842959ms)\n✔ PASS drinkEach \u003e drinkEach drinks each drink (0.360625ms)\n✔ PASS drinkEach (0.463416ms)\n✔ PASS toHaveBeenCalledWith \u003e registration applies correctly to orange La Croix (0.53325ms)\n✔ PASS toHaveBeenCalledWith (0.564166ms)\n✔ PASS toHaveBeenLastCalledWith \u003e applying to all flavors does mango last (0.380375ms)\n✔ PASS toHaveBeenLastCalledWith (0.473417ms)\n# tests/jest/fn.invocationCallOrder.test.js\n✔ PASS mock.invocationCallOrder (4.221042ms)\n```\n\n#### GitHub Actions collapses test results per-file, like this:\n\n\u003cdetails\u003e\n \u003csummary\u003e✅ \u003cstrong\u003etests/jest/lifecycle.test.js\u003c/strong\u003e\u003c/summary\u003e\n \u003cpre\u003e\n  ✔ PASS A \u003e B \u003e C (3.26166ms)\n  ✔ PASS A \u003e B \u003e D (1.699463ms)\n  ✔ PASS A \u003e B (6.72719ms)\n  ✔ PASS A \u003e E \u003e F (1.117997ms)\n  ✔ PASS A \u003e E \u003e G \u003e H (1.330904ms)\n  ✔ PASS A \u003e E \u003e G (1.94971ms)\n  ✔ PASS A \u003e E (3.821825ms)\n  ✔ PASS A \u003e I (0.533096ms)\n  ✔ PASS A (13.887889ms)\n  ✔ PASS J (0.373187ms)\n  ✔ PASS K \u003e L (0.659852ms)\n  ✔ PASS K (1.143195ms)\n \u003c/pre\u003e\n\u003c/details\u003e\u003cdetails\u003e\n \u003csummary\u003e✅ \u003cstrong\u003etests/jest/timers.async.test.js\u003c/strong\u003e\u003c/summary\u003e\n \u003cpre\u003e\n  ✔ PASS advanceTimersByTime() does not let microtasks to pass (5.326604ms)\n  ✔ PASS advanceTimersByTime() does not let microtasks to pass even with await (1.336064ms)\n  ✔ PASS advanceTimersByTimeAsync() lets microtasks to pass (6.99526ms)\n  ✔ PASS advanceTimersByTimeAsync() lets microtasks to pass, chained (10.131664ms)\n  ✔ PASS advanceTimersByTimeAsync() lets microtasks to pass, longer chained (8.635472ms)\n  ✔ PASS advanceTimersByTimeAsync() lets microtasks to pass, async chain (56.937983ms)\n \u003c/pre\u003e\n\u003c/details\u003e\n\nSee live output in [CI](https://github.com/ExodusMovement/test/actions/workflows/checks.yaml)\n\n## Library\n\n### List of exports\n\n- `@exodus/test/node` -- `node:test` API, working under non-Node.js platforms\n\n- `@exodus/test/jest` -- `jest` implementation\n\n- `@exodus/test/tape` -- `tape` mock (can also be helpful when moving from `tap`)\n\n## Binary\n\nJust use `\"test\": \"exodus-test\"`\n\n### Options\n\n- `--jest` -- register jest test helpers as global variables, also load `jest.config.*` configuration options\n\n- `--esbuild` -- use esbuild loader, also enables Typescript support\n\n- `--babel` -- use babel loader (slower than `--esbuild`, makes sense if you have a special config)\n\n- `--coverage` -- enable coverage, prints coverage output (varies by coverage engine)\n\n- `--coverage-engine c8` -- use c8 coverage engine (default), also generates `./coverage/` dirs\n\n- `--coverage-engine node` -- use Node.js builtint coverage engine\n\n- `--watch` -- operate in watch mode and re-run tests on file changes\n\n- `--only` -- only run the tests marked with `test.only`\n\n- `--passWithNoTests` -- do not error when no test files were found\n\n- `--write-snapshots` -- write snapshots instead of verifying them (has `--test-update-snapshots` alias)\n\n- `--test-force-exit` -- force exit after tests are done (useful in integration tests where it could be unfeasible to resolve all open handles)\n\n## Jest compatibility\n\nThe `--jest` mode is mostly compatible with Jest. There are some noteworthy differences though.\nThis tool does not hoist mocks, so it is important that a mock is defined before the module that uses it is imported.\nIn ESM, this can be achieved with dynamic imports:\n\n```js\njest.mock('./hogwarts.js', () =\u003e {\n  return {\n    __esModule: true,\n    default: jest.fn(),\n  }\n})\n\nconst { default: getEntryQualification } = await import('./hogwarts.js')\nconst { qualifiesForHogwarts } = await import('./wizard.js') // module importing ./hogwarts.js\n\ntest('qualifies for Hogwarts', () =\u003e {\n  // doSomething is a mock function\n  getEntryQualification.mockReturnValue(['lumos'])\n\n  expect(qualifiesForHogwarts('potter')).toBe(false)\n  getEntryQualification.mockReturnValue([])\n  expect(qualifiesForHogwarts('potter')).toBe(true)\n})\n```\n\nNote that all modules that transitively import `hogwarts.js` will have to be imported after the mock is defined.\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexodusmovement%2Ftest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexodusmovement%2Ftest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexodusmovement%2Ftest/lists"}