@cfxlabsinc/b2b-services
    Preparing search index...

    Module @cfxlabsinc/nx-bun-test

    @cfxlabsinc/nx-bun-test

    Infers a test target for every package, running bun test.

    Replaces the test target @nx/vitest used to contribute. Nx's targetDefaults can only augment a target that already exists, so without an inference plugin every package would need to declare "test": {} by hand.

    tools/test/bun.sh test ./<projectRoot>/ --pass-with-no-tests --timeout 600000 [--preload ./<projectRoot>/<preload>]
    
    • tools/test/bun.sh runs bun as the .bun-version release. On CI, PATH bun already is that release and the script just execs it. Locally PATH often holds a canary, whose bun test differs from CI's (module mocks, bare-specifier onResolve, --isolate=modules), so the script runs bunx bun@<version> and puts it first on PATH for any bun a test spawns. It compares bun --revision, because a canary reports the same --version.
    • ./<projectRoot>/, not <projectRoot>/: bun reads a bare argument as a substring filter, which also matched copies of a package under tmp/.

    plus lcov coverage into coverage/<projectRoot> whenever BUN_COVERAGE holds bun's coverage flags — pr.yml's test step sets it, and the coverage configuration sets it to --coverage --coverage-reporter=lcov. BUN_COVERAGE is a target input, so a cached run without coverage is never replayed for one with it.

    • --pass-with-no-tests — the target is inferred for every package, the same way the vitest one was; a package with no tests is not a failure.
    • No --parallel / --isolate by default. bun runs one package's files sequentially in a single process, which is what the surfpool and Temporal suites need — they previously spelled it pool: "forks" + fileParallelism: false in their vite configs.
    • test:parallel opts a package in. A project whose project.json tags it gets --parallel=4, run under bun tools/test/with-postgres.ts, which passes on an inherited TEST_DATABASE_URL or boots one Postgres for the run. --parallel implies --isolate, so the preload runs in every file, and without one shared server each file would boot a container of its own.
    inputs:  default
    ^production
    {workspaceRoot}/bunfig.toml
    {workspaceRoot}/tools/test/**/*
    {workspaceRoot}/.bun-version
    env: BUN_COVERAGE
    outputs: {workspaceRoot}/coverage/{projectRoot}
    • default, not production — production drops *.test.ts, which is the one thing this target exists to run. ^production on the dependency side is right, though: an upstream package's own tests can't change this one's result.
    • The two {workspaceRoot} entries. The command runs with cwd = workspace root, so the root bunfig.toml is the only one bun reads, and it decides both what gets collected (pathIgnorePatterns) and what runs before every file ([test].preload → tools/test/). Neither is reachable from default — that's {projectRoot}/**/* plus sharedGlobals, and sharedGlobals is only tsconfig.base.json. Without them, dropping the global timeout or changing an ignore pattern leaves every test cache warm and wrong.
    • outputs is always declared because only a coverage run writes it and Nx configurations carry executor options alone — outputs is target-level and can't be narrowed per configuration. A plain test run captures nothing.

    A project nested inside another (tools/ci and tools/visual-snapshots inside tools) runs its own tests, so the outer one's command passes --path-ignore-patterns for each. The flag replaces bunfig's pathIgnorePatterns rather than adding to them, so **/e2e/** is restated.

    Not covered: the root package.json / bun.lock. A dependency bump doesn't invalidate any test cache — that's a workspace-wide gap (build has it too) and belongs in sharedGlobals, not here.

    A package opts in by having the file; there is no per-package project.json wiring.

    File Used by
    test/preload.ts surfpool / Temporal packages — the module body replaces vitest's globalSetup
    test/setup.ts packages/ui — happy-dom's GlobalRegistrator must run before anything touches document

    A preload's module body executes once per bun test invocation, and a top-level afterAll fires after the final test file — the same once-per-package-with-teardown contract globalSetup provided.

    The command passes --timeout 600000. tools/test/preload.ts calls setDefaultTimeout with the same number for a bare bun test. That call can lapse partway through a package's files, so the flag is the one that holds. BUN_TEST_JUNIT_DIR adds a JUnit report at $BUN_TEST_JUNIT_DIR/{projectName}.xml.

    NxBunTestPluginOptions
    createNodes