@hughescr/stryker-bun-runner 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -77,6 +77,7 @@ This approach provides reliable test-to-mutant correlation, even with multiple t
77
77
  | `bun.inspectorTimeout` | `number` | `5000` | Timeout for Inspector WebSocket connection in milliseconds |
78
78
  | `bun.env` | `object` | `undefined` | Additional environment variables to pass to bun test |
79
79
  | `bun.bunArgs` | `string[]` | `undefined` | Additional bun test flags (e.g., `['--bail']`) |
80
+ | `bun.testFiles` | `string[]` | `undefined` | Explicit list of test file paths (absolute or relative to cwd). When provided, skips auto-discovery and uses this list verbatim. Relative paths resolve against the bun subprocess's cwd. Useful for restricting mutation testing to a subset of test files. |
80
81
 
81
82
  ### Example with all options
82
83
 
@@ -38,8 +38,8 @@ function formatCoverageData(mutantCoverage, counterToName) {
38
38
  };
39
39
  }
40
40
  function writeCoverageToFile(coverageFile, data) {
41
- appendFileSync(coverageFile, JSON.stringify(data) + `
42
- `, "utf-8");
41
+ appendFileSync(coverageFile, `${JSON.stringify(data)}
42
+ `, "utf8");
43
43
  }
44
44
  export {
45
45
  writeCoverageToFile,
package/dist/index.d.ts CHANGED
@@ -19,6 +19,7 @@ export declare class BunTestRunner implements TestRunner {
19
19
  private readonly inspectorTimeout;
20
20
  private readonly env?;
21
21
  private readonly bunArgs?;
22
+ private readonly testFilesOverride?;
22
23
  private readonly mutateGlobs;
23
24
  private preloadScriptPath?;
24
25
  private coverageFilePath?;
@@ -28,7 +29,9 @@ export declare class BunTestRunner implements TestRunner {
28
29
  private cachedTestNames?;
29
30
  private baseNameIndex?;
30
31
  private cachedTestFiles?;
32
+ private cachedTestFilesCwd?;
31
33
  private cachedEagerModules?;
34
+ private cachedEagerModulesCwd?;
32
35
  private lastRegistryTmpPath?;
33
36
  constructor(logger: Logger, options: StrykerOptions);
34
37
  /**
@@ -44,6 +47,21 @@ export declare class BunTestRunner implements TestRunner {
44
47
  */
45
48
  capabilities(): TestRunnerCapabilities;
46
49
  /**
50
+ * Return the test file list to use for this run.
51
+ * When `bun.testFiles` was provided it is returned verbatim and
52
+ * auto-discovery is skipped entirely. Otherwise the result is cached after
53
+ * the first real discovery call so that subsequent callers (dryRun, mutantRun)
54
+ * do not re-glob the filesystem.
55
+ */
56
+ private getOrDiscoverTestFiles;
57
+ /**
58
+ * Test-file cache hit for a given cwd.
59
+ * Returns the cached list synchronously when available, or undefined to
60
+ * signal that async re-discovery is needed (cwd changed or first call).
61
+ * Used by dryRun() to avoid introducing a microtask yield on the hot path.
62
+ */
63
+ private testFilesCacheHit;
64
+ /**
47
65
  * Initialize the test runner
48
66
  */
49
67
  init(): Promise<void>;
@@ -73,10 +91,62 @@ export declare class BunTestRunner implements TestRunner {
73
91
  */
74
92
  dryRun(): Promise<DryRunResult>;
75
93
  /**
94
+ * Build the in-memory test name cache and base-name index, then atomically
95
+ * persist them to a well-known file so other worker processes can lazy-load
96
+ * them when handling static-coverage mutants (testFilter is empty for those).
97
+ *
98
+ * Writing to a .tmp path then renaming is atomic on POSIX: readers always see
99
+ * either the previous complete file or the new one — never a partial write.
100
+ */
101
+ private buildAndPersistTestRegistry;
102
+ /**
76
103
  * Run tests with an active mutant
77
104
  */
78
105
  mutantRun(options: MutantRunOptions): Promise<MutantRunResult>;
79
106
  /**
107
+ * Build the MutantRunResult for a killed mutant (non-zero exit code).
108
+ * Handles runtime error detection and killedBy resolution.
109
+ */
110
+ private buildMutantKilledResult;
111
+ /**
112
+ * Check if the process failed due to a runtime error (no tests ran).
113
+ * Returns a MutantRunResult if this is a runtime error, or null to continue.
114
+ */
115
+ private checkRuntimeError;
116
+ /**
117
+ * Check for dry run process failures (timeout or non-zero exit).
118
+ * Returns a DryRunResult to short-circuit if the process failed, or null to proceed.
119
+ */
120
+ private checkDryRunProcessResult;
121
+ /**
122
+ * Collect coverage from the coverage file and remap counter-based IDs to
123
+ * full test names using the inspector's execution order.
124
+ */
125
+ private collectAndRemapCoverage;
126
+ /**
127
+ * Build local index structures from testFilter for killedBy resolution.
128
+ *
129
+ * testFilter carries the full registry IDs Stryker wants us to run, including
130
+ * any " [N]" dedup suffixes. Building the index here means all workers behave
131
+ * identically on the first shot, eliminating incremental drift caused by workers
132
+ * that never ran dryRun falling through to raw names.
133
+ */
134
+ private buildLocalTestFilterIndex;
135
+ /**
136
+ * Resolve raw failed test names from console output against the test registry.
137
+ *
138
+ * Console-parser output lacks the [N] dedup suffix that dryRun appends when
139
+ * multiple tests share the same base name (e.g. it.each with %s).
140
+ *
141
+ * Fallback chain — stops at the FIRST successful resolution for each name:
142
+ * 1. Exact match in localRegistry (built from testFilter)
143
+ * 2. Base-name match in localBaseIndex (built from testFilter)
144
+ * 3. Exact match in this.cachedTestNames (instance registry from dryRun)
145
+ * 4. Base-name match in this.baseNameIndex (instance registry from dryRun)
146
+ * 5. Raw name as-is with a warn log — last resort if nothing resolves.
147
+ */
148
+ private resolveKilledBy;
149
+ /**
80
150
  * Cleanup resources
81
151
  */
82
152
  dispose(): Promise<void>;
@@ -91,8 +161,14 @@ export interface BunTestRunnerOptions {
91
161
  */
92
162
  bunPath?: string;
93
163
  /**
94
- * Timeout per test in milliseconds
164
+ * Child-process timeout in milliseconds — the maximum wall-clock time that the
165
+ * entire `bun test` subprocess is allowed to run before it is killed.
95
166
  * @default 10000
167
+ *
168
+ * Note: this is distinct from Bun's per-test timeout configured via
169
+ * `[test].timeout` in `bunfig.toml`. The two are independent: `bunfig.toml`
170
+ * controls when Bun itself declares a single test timed out; this option
171
+ * controls when the Stryker runner forcibly kills the whole child process.
96
172
  */
97
173
  timeout?: number;
98
174
  /**
@@ -109,6 +185,25 @@ export interface BunTestRunnerOptions {
109
185
  * @example ['--bail', '--only']
110
186
  */
111
187
  bunArgs?: string[];
188
+ /**
189
+ * Explicit list of test file paths (must be non-empty when provided).
190
+ * When provided, BunTestRunner skips auto-discovery (which globs
191
+ * `**\/*.test.ts` from the current working directory) and uses exactly this
192
+ * list. Useful for restricting mutation testing to a subset, or for callers
193
+ * that run outside Stryker's sandboxed cwd and need to point at a specific
194
+ * file set. Relative paths resolve against the bun subprocess's cwd.
195
+ *
196
+ * IMPORTANT: In a Stryker mutation-testing run, each worker's cwd is set to
197
+ * a sandbox directory (`.stryker-tmp/sandbox-XYZ/`) containing sandbox copies
198
+ * of the project files. Relative paths are resolved against that sandbox cwd
199
+ * and therefore point at the mutated copies. Absolute paths bypass the sandbox
200
+ * and always point at the ORIGINAL (unmutated) files — mutations will be
201
+ * silently ignored. Always prefer relative paths in Stryker context.
202
+ *
203
+ * An empty array (`[]`) is invalid — use `undefined` or omit the option to
204
+ * fall back to auto-discovery.
205
+ */
206
+ testFiles?: string[];
112
207
  }
113
208
  /**
114
209
  * Extended Stryker options with Bun-specific configuration
@@ -168,6 +263,14 @@ export declare const strykerValidationSchema: {
168
263
  type: string;
169
264
  };
170
265
  };
266
+ testFiles: {
267
+ type: string;
268
+ description: string;
269
+ minItems: number;
270
+ items: {
271
+ type: string;
272
+ };
273
+ };
171
274
  };
172
275
  additionalProperties: boolean;
173
276
  };