@systemfsoftware/stryker-js-cli 4.0.0 → 4.0.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/CHANGELOG.md +12 -0
- package/dist/main.mjs +43 -20
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @systemfsoftware/stryker-js-cli
|
|
2
2
|
|
|
3
|
+
## 4.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- A mutation run that is killed mid-way keeps every completed mutant: the JSONL progress stream is flushed after each result, and incremental mode writes remembered verdicts as they finish so the next run continues instead of starting over.
|
|
8
|
+
|
|
9
|
+
Remembered killed mutants still name the tests that killed them, so a resumed run's report matches a complete run.
|
|
10
|
+
|
|
11
|
+
The progress stream path is progressStreamFile (default reports/mutation-stream.jsonl) and can be set in config or with --progressStreamFile.
|
|
12
|
+
|
|
13
|
+
- Peer Effect requirement advances to 4.0.0-rc.112. No API changes.
|
|
14
|
+
|
|
3
15
|
## 4.0.0
|
|
4
16
|
|
|
5
17
|
### Major Changes
|
package/dist/main.mjs
CHANGED
|
@@ -1053,6 +1053,35 @@ function emitMachineModeOutput(stream, mode, outcome, basePath, pathService) {
|
|
|
1053
1053
|
});
|
|
1054
1054
|
}
|
|
1055
1055
|
//#endregion
|
|
1056
|
+
//#region src/StreamFile.ts
|
|
1057
|
+
const DEFAULT_PROGRESS_STREAM_FILE = "reports/mutation-stream.jsonl";
|
|
1058
|
+
const encodeUtf8 = (line) => new TextEncoder().encode(line);
|
|
1059
|
+
const drainStreamFile = (fileName, framed) => Effect.gen(function* () {
|
|
1060
|
+
const fs = yield* FileSystem.FileSystem;
|
|
1061
|
+
const path = yield* Path.Path;
|
|
1062
|
+
yield* fs.makeDirectory(path.dirname(fileName), { recursive: true }).pipe(Effect.orDie);
|
|
1063
|
+
yield* Effect.scoped(Effect.gen(function* () {
|
|
1064
|
+
const handle = yield* fs.open(fileName, { flag: "w" });
|
|
1065
|
+
yield* Stream.runForEach(framed, (line) => handle.writeAll(encodeUtf8(line)).pipe(Effect.flatMap(() => handle.sync)));
|
|
1066
|
+
})).pipe(Effect.orDie);
|
|
1067
|
+
});
|
|
1068
|
+
const RunEventStreamFileLive = Layer.effect(RunEventStreamPort, Effect.gen(function* () {
|
|
1069
|
+
const stdio = yield* Stdio.Stdio;
|
|
1070
|
+
const fs = yield* FileSystem.FileSystem;
|
|
1071
|
+
const path = yield* Path.Path;
|
|
1072
|
+
const fileNameRef = yield* Ref.make(DEFAULT_PROGRESS_STREAM_FILE);
|
|
1073
|
+
const drainFramed = (framed) => Effect.gen(function* () {
|
|
1074
|
+
const fileName = yield* Ref.get(fileNameRef);
|
|
1075
|
+
yield* drainStreamFile(fileName, framed).pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path.Path, path));
|
|
1076
|
+
});
|
|
1077
|
+
return RunEventStreamPort.of({ createRunEventStream: (resolved) => Effect.gen(function* () {
|
|
1078
|
+
return {
|
|
1079
|
+
...yield* makeRunEventStream(stdio, resolved, drainFramed),
|
|
1080
|
+
setProgressStreamFile: (fileName) => Ref.set(fileNameRef, fileName)
|
|
1081
|
+
};
|
|
1082
|
+
}) });
|
|
1083
|
+
}));
|
|
1084
|
+
//#endregion
|
|
1056
1085
|
//#region src/Survivors.ts
|
|
1057
1086
|
/**
|
|
1058
1087
|
* Survivors — the survivors-admission capability.
|
|
@@ -1562,6 +1591,7 @@ const runOptions = {
|
|
|
1562
1591
|
incremental: Flag.map(optional(Flag.boolean("incremental")), absentWhenFalse).pipe(Flag.withDescription("Enable 'incremental mode'. Stryker will store results in a file and use that file to speed up the next --incremental run")),
|
|
1563
1592
|
allowEmpty: Flag.map(optional(Flag.boolean("allowEmpty")), absentWhenFalse).pipe(Flag.withDescription("Allows stryker to exit without any errors in cases where no tests are found")),
|
|
1564
1593
|
incrementalFile: Flag.string("incrementalFile").pipe(Flag.withDescription("Specify the file to use for incremental mode."), optional),
|
|
1594
|
+
progressStreamFile: Flag.string("progressStreamFile").pipe(Flag.withDescription("Specify the file for the machine-mode progress stream."), optional),
|
|
1565
1595
|
force: Flag.map(optional(Flag.boolean("force")), absentWhenFalse).pipe(Flag.withDescription("Run all mutants, even if --incremental is provided and an incremental file exists. Can be used to force a rebuild of the incremental file.")),
|
|
1566
1596
|
mutate: Flag.string("mutate").pipe(Flag.withAlias("m"), Flag.withDescription("With `mutate` you configure the subset of files or just one specific file to be mutated. These should be your _production code files_, and definitely not your test files. (Whereas with `ignorePatterns` you prevent non-relevant files from being copied to the sandbox directory in the first place)\nThe default will try to guess your production code files based on sane defaults. It reads like this:\n- Include all js-like files inside the `src` or `lib` dir\n- Except files inside `__tests__` directories and file names ending with `test` or `spec`.\nIf the defaults are not sufficient for you, for example in a angular project you might want to **exclude** not only the `*.spec.ts` files but other files too, just like the default already does.\nIt is possible to override the defaults by: - supplying one or more [glob patterns](https://github.com/isaacs/minimatch) to include (e.g. `src/**/*.js`) - or one or more comma separated glob patterns preceded with `!` to exclude (e.g. `!src/**/*.spec.js`) - or both (e.g. `src/**/*.js,!src/**/*.spec.js`).\nNote: Stryker will use [minimatch](https://github.com/isaacs/minimatch) for parsing these patterns, see minimatch for the exact syntax."), Flag.map(splitOnComma), optional),
|
|
1567
1597
|
testFiles: Flag.string("testFiles").pipe(Flag.withAlias("t"), Flag.withDescription("With `testFiles` you can limit which test files are executed during mutation testing. When specified, only tests from these files will be run. This allows you to verify that a module's dedicated unit tests can kill all its mutants independently."), Flag.map(splitOnComma), optional),
|
|
@@ -1657,6 +1687,7 @@ function makeStrykerCommand(requestRef) {
|
|
|
1657
1687
|
setIfPresent(options, "incremental", config.incremental);
|
|
1658
1688
|
setIfPresent(options, "allowEmpty", config.allowEmpty);
|
|
1659
1689
|
setIfPresent(options, "incrementalFile", config.incrementalFile);
|
|
1690
|
+
setIfPresent(options, "progressStreamFile", config.progressStreamFile);
|
|
1660
1691
|
setIfPresent(options, "force", config.force);
|
|
1661
1692
|
setIfPresent(options, "mutate", config.mutate);
|
|
1662
1693
|
setIfPresent(options, "testFiles", config.testFiles);
|
|
@@ -1802,9 +1833,19 @@ const runStrykerCli = (input, createRunEventStream) => Effect.gen(function* () {
|
|
|
1802
1833
|
process.on("SIGINT", onSignal);
|
|
1803
1834
|
process.on("SIGTERM", onSignal);
|
|
1804
1835
|
}), () => Effect.gen(function* () {
|
|
1805
|
-
yield*
|
|
1806
|
-
yield* input.program;
|
|
1836
|
+
const parsed = yield* Effect.result(input.program);
|
|
1807
1837
|
const request = yield* Ref.get(input.requestRef);
|
|
1838
|
+
const fileName = Option.match(request, {
|
|
1839
|
+
onNone: () => DEFAULT_PROGRESS_STREAM_FILE,
|
|
1840
|
+
onSome: (cliRequest) => Match.value(cliRequest).pipe(Match.tag("run", (runRequest) => {
|
|
1841
|
+
const fromCli = runRequest.options["progressStreamFile"];
|
|
1842
|
+
if (typeof fromCli === "string" && fromCli.length > 0) return fromCli;
|
|
1843
|
+
return DEFAULT_PROGRESS_STREAM_FILE;
|
|
1844
|
+
}), Match.orElse(() => DEFAULT_PROGRESS_STREAM_FILE))
|
|
1845
|
+
});
|
|
1846
|
+
if (stream.setProgressStreamFile !== void 0) yield* stream.setProgressStreamFile(fileName);
|
|
1847
|
+
yield* stream.open;
|
|
1848
|
+
if (Result.isFailure(parsed)) return yield* Effect.fail(parsed.failure);
|
|
1808
1849
|
return yield* Option.match(request, {
|
|
1809
1850
|
onNone: () => Effect.void,
|
|
1810
1851
|
onSome: (cliRequest) => dispatch(cliRequest)
|
|
@@ -1822,24 +1863,6 @@ const runStrykerCli = (input, createRunEventStream) => Effect.gen(function* () {
|
|
|
1822
1863
|
}));
|
|
1823
1864
|
});
|
|
1824
1865
|
//#endregion
|
|
1825
|
-
//#region src/StreamFile.ts
|
|
1826
|
-
const STREAM_FILE_DIR = "reports";
|
|
1827
|
-
const STREAM_FILE_NAME = "mutation-stream.jsonl";
|
|
1828
|
-
const encodeUtf8 = (line) => new TextEncoder().encode(line);
|
|
1829
|
-
const drainStreamFile = (framed) => Effect.gen(function* () {
|
|
1830
|
-
const fs = yield* FileSystem.FileSystem;
|
|
1831
|
-
const file = (yield* Path.Path).join(STREAM_FILE_DIR, STREAM_FILE_NAME);
|
|
1832
|
-
yield* fs.makeDirectory(STREAM_FILE_DIR, { recursive: true }).pipe(Effect.orDie);
|
|
1833
|
-
yield* Stream.run(framed.pipe(Stream.map(encodeUtf8)), fs.sink(file, { flag: "w" })).pipe(Effect.orDie);
|
|
1834
|
-
});
|
|
1835
|
-
const RunEventStreamFileLive = Layer.effect(RunEventStreamPort, Effect.gen(function* () {
|
|
1836
|
-
const stdio = yield* Stdio.Stdio;
|
|
1837
|
-
const fs = yield* FileSystem.FileSystem;
|
|
1838
|
-
const path = yield* Path.Path;
|
|
1839
|
-
const drainFramed = (framed) => drainStreamFile(framed).pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path.Path, path));
|
|
1840
|
-
return RunEventStreamPort.of({ createRunEventStream: (resolved) => makeRunEventStream(stdio, resolved, drainFramed) });
|
|
1841
|
-
}));
|
|
1842
|
-
//#endregion
|
|
1843
1866
|
//#region src/main.ts
|
|
1844
1867
|
const EXIT_CODE_RUN_NEVER_REACHED_ITS_FINALIZER = 1;
|
|
1845
1868
|
process.title = "stryker";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemfsoftware/stryker-js-cli",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
"@effect/platform-node-shared": "^4.0.0-rc.112",
|
|
19
19
|
"@noble/hashes": "1.8.0",
|
|
20
20
|
"effect": "^4.0.0-rc.112",
|
|
21
|
-
"@systemfsoftware/effect-cell-types": "^5.0.
|
|
22
|
-
"@systemfsoftware/stryker-js-html-reporter": "^0.1.0",
|
|
21
|
+
"@systemfsoftware/effect-cell-types": "^5.0.1",
|
|
23
22
|
"@systemfsoftware/stryker-js": "^0.1.0",
|
|
23
|
+
"@systemfsoftware/stryker-js-html-reporter": "^0.1.0",
|
|
24
24
|
"@systemfsoftware/stryker-js-platform-node": "^0.1.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
@@ -33,15 +33,15 @@
|
|
|
33
33
|
"tsdown": "^0.22.14",
|
|
34
34
|
"vite-tsconfig-paths": "^6.1.1",
|
|
35
35
|
"vitest": "^4.1.10",
|
|
36
|
-
"@systemfsoftware/
|
|
37
|
-
"@systemfsoftware/effect-
|
|
38
|
-
"@systemfsoftware/
|
|
39
|
-
"@systemfsoftware/effect-schema-vite": "^2.0.0",
|
|
36
|
+
"@systemfsoftware/effect-gherkin-spec": "^2.0.2",
|
|
37
|
+
"@systemfsoftware/effect-schema-law": "^2.0.0",
|
|
38
|
+
"@systemfsoftware/all": "^1.0.1",
|
|
40
39
|
"@systemfsoftware/oxlint-config": "^0.1.0",
|
|
41
|
-
"@systemfsoftware/
|
|
42
|
-
"@systemfsoftware/oxlint-plugin-
|
|
43
|
-
"@systemfsoftware/oxlint-plugin-
|
|
40
|
+
"@systemfsoftware/effect-schema-vite": "^2.0.1",
|
|
41
|
+
"@systemfsoftware/oxlint-plugin-cell-vocabulary": "^1.2.3",
|
|
42
|
+
"@systemfsoftware/oxlint-plugin-test-placement": "^3.2.1",
|
|
44
43
|
"@systemfsoftware/tsconfig": "^1.3.3",
|
|
44
|
+
"@systemfsoftware/oxlint-plugin-effect-entrypoint": "^1.0.6",
|
|
45
45
|
"@systemfsoftware/vitest-config": "^0.1.0"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|