@hughescr/stryker-bun-runner 1.1.3 → 1.2.0
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 +14 -0
- package/dist/coverage/preload-logic.js +1 -34
- package/dist/index.d.ts +33 -0
- package/dist/index.js +7353 -3205
- package/dist/templates/coverage-preload.ts +83 -22
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -96,10 +96,24 @@ bun: {
|
|
|
96
96
|
bunx stryker run
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
## How the sandboxed config works
|
|
100
|
+
|
|
101
|
+
When the plugin initialises it reads your project's `bunfig.toml` (if present) and writes a sanitized copy that is passed to every `bun test` invocation via `--config`. The sanitizer forwards only an explicit allowlist of `[test]` keys; everything else is stripped. The forwarded keys are: `preload`, `root`, `pathIgnorePatterns`, `timeout`, `smol`, `rerunEach`, `retry`, `randomize`, `seed`. The `[install]` table is copied verbatim. Two keys are always forced: `coverage = false` and `onlyFailures = false`. This prevents `coverageThreshold` misses (which cause Bun to exit 1 even when no test actually fails) from being mistaken for mutant kills. If you need additional `[test]` settings forwarded, add their key names to the `SAFE_TEST_KEYS` set in `src/utils/bunfig-sanitizer.ts`.
|
|
102
|
+
|
|
99
103
|
## Known Limitations
|
|
100
104
|
|
|
101
105
|
- **Sequential execution required** - Tests run with `--concurrency=1` to ensure accurate coverage tracking. This is slower than parallel execution but necessary for correct test-to-mutant correlation.
|
|
102
106
|
|
|
107
|
+
**Eager-import and `mock.module()` compatibility**
|
|
108
|
+
|
|
109
|
+
During `dryRun`, the plugin eager-imports every mutated source module at preload time in order to produce deterministic per-test coverage. Each mutated module is imported once, before any test file executes.
|
|
110
|
+
|
|
111
|
+
Because of this, any `mock.module()` call that runs after a module has already been imported has no effect on the already-resolved module binding. In practice, this means that if a test file calls `mock.module('./some-source-file')` at the top level (or inside a `beforeAll`), and that file is among the mutated modules, the test will see the real module rather than the mock.
|
|
112
|
+
|
|
113
|
+
Suggested workarounds: use dependency injection so the real module reference is replaceable at test time; wrap the mocked surface in a test-local helper that the test can control without replacing the module; or use `mock.fn()` on method instances rather than replacing the entire module with `mock.module()`.
|
|
114
|
+
|
|
115
|
+
This limitation applies only to mutated source files — the ones listed under `mutate:` in your Stryker config. Pre-import `mock.module()` of non-mutated modules (for example `node:fs`, third-party libraries, or utility files outside the mutation scope) is unaffected.
|
|
116
|
+
|
|
103
117
|
## Concurrent Tests
|
|
104
118
|
|
|
105
119
|
This plugin automatically patches `describe.concurrent()`, `test.concurrent()`, and `it.concurrent()` to run sequentially during mutation testing. Your tests will work without modification.
|
|
@@ -41,44 +41,11 @@ function writeCoverageToFile(coverageFile, data) {
|
|
|
41
41
|
appendFileSync(coverageFile, JSON.stringify(data) + `
|
|
42
42
|
`, "utf-8");
|
|
43
43
|
}
|
|
44
|
-
function parseWebSocketMessage(data) {
|
|
45
|
-
if (data === "ready") {
|
|
46
|
-
return "ready";
|
|
47
|
-
}
|
|
48
|
-
try {
|
|
49
|
-
const msg = JSON.parse(data);
|
|
50
|
-
if (msg.type === "testStart" && msg.name) {
|
|
51
|
-
return { type: "testStart", name: msg.name };
|
|
52
|
-
}
|
|
53
|
-
} catch {}
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
function createTestCounter() {
|
|
57
|
-
let counter = 0;
|
|
58
|
-
const counterToName = new Map;
|
|
59
|
-
return {
|
|
60
|
-
increment() {
|
|
61
|
-
counter++;
|
|
62
|
-
return `test-${counter}`;
|
|
63
|
-
},
|
|
64
|
-
setName(counterId, name) {
|
|
65
|
-
counterToName.set(counterId, name);
|
|
66
|
-
},
|
|
67
|
-
getName(counterId) {
|
|
68
|
-
return counterToName.get(counterId);
|
|
69
|
-
},
|
|
70
|
-
getCounterToNameMap() {
|
|
71
|
-
return counterToName;
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
44
|
export {
|
|
76
45
|
writeCoverageToFile,
|
|
77
46
|
shouldCollectCoverage,
|
|
78
47
|
setActiveMutant,
|
|
79
|
-
parseWebSocketMessage,
|
|
80
48
|
initializeStrykerNamespace,
|
|
81
49
|
getPreloadConfig,
|
|
82
|
-
formatCoverageData
|
|
83
|
-
createTestCounter
|
|
50
|
+
formatCoverageData
|
|
84
51
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -19,11 +19,27 @@ export declare class BunTestRunner implements TestRunner {
|
|
|
19
19
|
private readonly inspectorTimeout;
|
|
20
20
|
private readonly env?;
|
|
21
21
|
private readonly bunArgs?;
|
|
22
|
+
private readonly mutateGlobs;
|
|
22
23
|
private preloadScriptPath?;
|
|
23
24
|
private coverageFilePath?;
|
|
25
|
+
private sanitizedBunfigPath?;
|
|
26
|
+
private sanitizedBunfigCwd?;
|
|
27
|
+
private tempDir?;
|
|
24
28
|
private cachedTestNames?;
|
|
29
|
+
private baseNameIndex?;
|
|
30
|
+
private cachedTestFiles?;
|
|
31
|
+
private cachedEagerModules?;
|
|
32
|
+
private lastRegistryTmpPath?;
|
|
25
33
|
constructor(logger: Logger, options: StrykerOptions);
|
|
26
34
|
/**
|
|
35
|
+
* Single source of truth for the registry file name.
|
|
36
|
+
* Using getters that read process.cwd() at call time ensures the path
|
|
37
|
+
* resolves to Stryker's sandbox directory — which is set by the time these
|
|
38
|
+
* are invoked — rather than the orchestrator's cwd at module-load time.
|
|
39
|
+
*/
|
|
40
|
+
private get registryPath();
|
|
41
|
+
private get registryTmpPath();
|
|
42
|
+
/**
|
|
27
43
|
* Get test runner capabilities
|
|
28
44
|
*/
|
|
29
45
|
capabilities(): TestRunnerCapabilities;
|
|
@@ -32,6 +48,23 @@ export declare class BunTestRunner implements TestRunner {
|
|
|
32
48
|
*/
|
|
33
49
|
init(): Promise<void>;
|
|
34
50
|
/**
|
|
51
|
+
* Regenerate the sanitized bunfig if the worker's cwd has changed (or if this
|
|
52
|
+
* is the first spawn). Bun resolves relative paths in a bunfig against the
|
|
53
|
+
* bunfig file's location, so keying on cwd ensures preload/root paths land in
|
|
54
|
+
* the right sandbox.
|
|
55
|
+
*/
|
|
56
|
+
private ensureSanitizedBunfig;
|
|
57
|
+
/**
|
|
58
|
+
* Load the shared dryRun registry written by the one worker that ran dryRun.
|
|
59
|
+
* Populates this.cachedTestNames and this.baseNameIndex so that subsequent
|
|
60
|
+
* mutantRun calls on this worker can resolve killedBy names correctly, even
|
|
61
|
+
* for static-coverage mutants where testFilter is empty.
|
|
62
|
+
*
|
|
63
|
+
* Failures are non-fatal — the worker falls back to raw console names (current
|
|
64
|
+
* behaviour before this fix), and a warning is logged so the issue is visible.
|
|
65
|
+
*/
|
|
66
|
+
private loadRegistryFile;
|
|
67
|
+
/**
|
|
35
68
|
* Build test results from inspector data
|
|
36
69
|
*/
|
|
37
70
|
private buildTestsFromInspector;
|