Bun
This guide covers Bun 1.2.23 or newer. You need Node.js 22.12 or newer to run test-inventory and an existing JavaScript or TypeScript test suite. The scanner reads your source without executing your tests or starting a browser. These are minimum supported versions; CI comparisons list tested versions.
Choose another framework · Use an AI client
Install
npm install --save-dev test-inventoryScan your suite
Run from the folder containing your project's package.json:
npx test-inventory --framework bun --pretty --output inventory.jsonTo select files explicitly, use quoted globs. This example matches the quote-gateway fixture used below; adjust the globs to your suite's layout:
npx test-inventory "src/**/*.test.ts" "src/**/*.spec.ts" --framework bun --output inventory.jsonThe command replaces inventory.json once the new output is complete. It does not change your test files.
Check the result
Print the counts and diagnostics from the saved file:
node -e "const i = require('./inventory.json'); console.log(i.summary); console.log(i.diagnostics)"For matching tests, summary.fileCount and summary.testCount should be greater than zero. Review diagnostics even when the command exits with 0: errors can mean tests are missing. If the result is empty or unexpected, use troubleshooting.
The inventory describes source declarations, not execution results. Conditional skips are not proof that a run skipped the test. Loops and tables are one record by default; supported cases can be expanded with --expand-cases. Expected-to-fail tests execute and check for failure; they are not disabled tests.
Tests created by unreadable helpers can be missing without a diagnostic. A dependency hash does not prove complete coverage of runtime dependencies. Read the shared limits before using scans to make CI decisions.
Find skipped tests
npx test-inventory --framework bun --state skip --fields fullName,state,condition,reason --prettyThis uses the same file selection as the first scan. If you supplied globs, --root or --framework-version, repeat those options here.
This selects source declarations marked skip; it is not a report of a test run. See query recipes for other inventory queries.
Example
quote-gateway tests a quote gateway with Bun's bun test, using Bun's own chains, as test.skipIf(condition), and a bunfig.toml that runs its routing specs at once.
[test]
root = "src"
retry = 1
concurrentTestGlob = "**/routing/*.spec.ts"npx test-inventory "src/**/*.test.ts" "src/**/*.spec.ts" --framework bun --output inventory.jsonWithout the globs and --framework, the scan finds the same files from Bun's patterns under [test] root, and Bun from the test script. skipIf is a condition, and [test] retry applies to every test:
{
"fullName": "spread > streams quotes from the venue",
"state": "skip",
"isConditional": true,
"condition": "!process.env.VENUE_URL",
"retries": 1
}Bun parameterized tests
quote-gateway tests the same spread calculation with two rows of data:
// src/quotes/spread.test.ts
test.each([
{ mic: 'XNAS', bid: 99.95, ask: 100.05 },
{ mic: 'XLON', bid: 49.9, ask: 50.1 },
])('quotes the $mic spread', ({ bid, ask }) => {
expect(spreadBps({ bid, ask })).toBeGreaterThan(0);
});First scan the declarations:
npx test-inventory "src/**/*.test.ts" "src/**/*.spec.ts" --framework bun --prettyThe table is one record with two cases. This is an excerpt:
{
"fullName": "spread > quotes the $mic spread",
"caseCount": 2,
"caseIndex": null
}To list each resolvable case separately, add --expand-cases to the same scan:
npx test-inventory "src/**/*.test.ts" "src/**/*.spec.ts" --framework bun --expand-cases --prettyThe table becomes two records with their substituted titles and zero-based indexes. These are record excerpts:
{
"fullName": "spread > quotes the XNAS spread",
"caseCount": 1,
"caseIndex": 0
}{
"fullName": "spread > quotes the XLON spread",
"caseCount": 1,
"caseIndex": 1
}Expansion follows the detected Bun version's title rules. If your project does not record its Bun version, pass --framework-version with the version you use to both commands. Unresolved data stays one record with a cases-not-expanded warning. See Bun's table syntax for the supported title formats. The scanner reads the table without running Bun or executing either test case.
Configuration and limits
The scan reads the root bunfig.toml [test] table. Without it, files have no config. Explicit globs count as files given to bun test. Supported settings include root, pathIgnorePatterns, concurrentTestGlob and, from Bun 1.3, retry. Invalid pattern settings are reported.
[test].preload files enter dependency hashes but are not executed. A focused test can make Bun omit other tests from its run report; the inventory keeps all declarations and their isOnly flags. Run the scanner with Node.js, even when the scanned tests use Bun.
See Bun file selection for exact defaults and version differences.
Supported syntax
Bun 1.2.23 and newer, which runs tests the way 1.3 and 1.4 do; see framework version.
Where test comes from
| Form | Example |
|---|---|
| Globals | test, it, describe, xtest, xit, xdescribe and the hooks, which bun test sets in its test files |
| Imports | import { describe, test } from 'bun:test', a namespace or default import, or require('bun:test'); imports from @jest/globals and vitest too, which Bun rewrites to bun:test |
| Kept in a variable | const later = test.skip: only what both branches of a choice share applies, also of one written in place, as (process.env.CI ? test.skip : test)(...) |
| Local helpers file | import { it } from './helpers' or require('./helpers'), followed through local imports, and helper functions that declare tests, read at each call |
Calls
| Call | Read as |
|---|---|
test(title, fn, options), test(title, options, fn) | A test. Options are a number, the timeout, or { timeout, retry, repeats }. A retry above 0 with any repeats, 0 too, is an invalid-chain error from Bun 1.3, which refuses them together. |
.skip, .todo, .failing, .only, .concurrent, .serial | A skipped, todo or expectedToFail test, isOnly, or isParallel. A chain may hold them in any order, but only one of skip, todo and failing, one only, and one of concurrent and serial; another is an invalid-chain error: Bun fails the file. skip wins over todo, and todo over failing. |
.if(condition), .skipIf, .todoIf, .failingIf, .concurrentIf, .serialIf | A state under a condition: if skips when its condition is false, the others set theirs when it is true. A condition that holds counts as its mode in the chain, so test.todoIf(true).failing is an invalid-chain error as test.todo.failing is; one the scan can't work out counts as not holding. A describe can't be failing. |
.each(table) | One record with caseCount, as for Jest; with expandCases, each case titled as Bun titles it: %s a string, %d and %f a number, %i an integer, %j and %o JSON, %# the index, %% a %, and $key a value of an object case, quoted before Bun 1.3. A value of another type leaves its placeholder as written, and once the values are used up, the rest stays as written. %p, and $key of an object, keep the cases as one record. A table that isn't an array is an invalid-chain error: Bun fails the file. |
test(title) without a function | A test-without-body error: Bun fails the file. test.skip(title) and test.todo(title) are allowed; test.todo with a function is todo too. |
beforeAll, afterAll, beforeEach, afterEach | Hooks. |
A refusal inside a describe fails that describe, whose tests are notLoaded with stateSource: "suite"; tests outside it still run.
A .only makes Bun run only the focused tests of its file, and from 1.3 with --only, none of the files without one; from 1.3, with CI=true, as in GitHub Actions, it fails its file instead. The other tests of the file are listed as written, with isOnly on the focused ones.
The shared syntax rules also apply.
Next
- Shared limits: imports, generated tests, conditions and dependency coverage.
- Key concepts: counts, states, IDs and hashes.
- Output reference and diagnostics: interpret every field and warning.
- CLI, library and MCP: use the same inventory through each interface.
- Compare with Bun: differences from runner collection and execution reports.