@systemfsoftware/stryker-js-vitest-runner 2.1.0 → 3.0.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/CHANGELOG.md +12 -0
- package/dist/index.mjs +314 -387
- package/package.json +4 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @systemfsoftware/stryker-js-vitest-runner
|
|
2
2
|
|
|
3
|
+
## 3.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- The dry-run decision moved to a plain kernel (dryRunCell removed); the mutant-run decision splits into branded MutantKilled|MutantSurvived|MutantTimeout|MutantDryError variants
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies:
|
|
12
|
+
- @systemfsoftware/effect-cell-types@6.0.0
|
|
13
|
+
- @systemfsoftware/stryker-js@1.0.0
|
|
14
|
+
|
|
3
15
|
## 2.1.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/index.mjs
CHANGED
|
@@ -7,81 +7,61 @@ import { Cell, Workflow } from "@systemfsoftware/effect-cell-types";
|
|
|
7
7
|
import { Module } from "@systemfsoftware/stryker-js/Module";
|
|
8
8
|
import { INSTRUMENTER_CONSTANTS, errorToString, normalizeFileName } from "@systemfsoftware/stryker-js/Mutant";
|
|
9
9
|
import { TestRunner, TestRunnerFailed, testFilesProvided } from "@systemfsoftware/stryker-js/TestRunner";
|
|
10
|
+
import * as Context from "effect/Context";
|
|
10
11
|
import * as FileSystem from "effect/FileSystem";
|
|
11
|
-
import
|
|
12
|
+
import * as Match from "effect/Match";
|
|
12
13
|
import * as Option from "effect/Option";
|
|
13
14
|
import * as Path from "effect/Path";
|
|
14
15
|
import * as Ref from "effect/Ref";
|
|
15
16
|
import * as Result from "effect/Result";
|
|
16
17
|
import { Effect } from "effect";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
exports: S.optional(S.Record(S.String, ExportEntry))
|
|
54
|
-
}), [S.Record(S.String, S.Unknown)]);
|
|
55
|
-
/**
|
|
56
|
-
* The dynamically imported project-local `vitest/node` module. The runtime
|
|
57
|
-
* check only asserts object-likeness: the module namespace is whatever the
|
|
58
|
-
* resolved package exports, and the consumers tolerate a missing
|
|
59
|
-
* `createVitest` via their own fallbacks.
|
|
60
|
-
*/
|
|
61
|
-
const VitestNodeModuleSchema = S.declare((input) => input !== null && typeof input === "object" && !Array.isArray(input), { description: "The project-local vitest/node module" });
|
|
62
|
-
/** The `package.json` document of a resolved vitest package. */
|
|
63
|
-
const VitestPackageSchema = S.Struct({ version: S.String });
|
|
64
|
-
//#endregion
|
|
65
|
-
//#region src/VitestDryRun.workflow.ts
|
|
66
|
-
/**
|
|
67
|
-
* VitestDryRun workflow — pure result-mapping for the dry-run phase.
|
|
68
|
-
*
|
|
69
|
-
* Every function here is pure: it maps raw vitest task payloads to
|
|
70
|
-
* Stryker run results without touching the filesystem or spawning
|
|
71
|
-
* processes. Impure orchestration lives in `Runner.ts`.
|
|
72
|
-
*/
|
|
18
|
+
//#region src/interpret-vitest-run.workflow.ts
|
|
19
|
+
var VitestMutantRunCommand = class extends S.TaggedClass()("VitestMutantRunCommand", {
|
|
20
|
+
rawTests: S.Array(S.Unknown),
|
|
21
|
+
projectRoot: S.String,
|
|
22
|
+
hasExternalError: S.Boolean,
|
|
23
|
+
externalErrorText: S.String,
|
|
24
|
+
hitCount: S.optional(S.Finite),
|
|
25
|
+
hitLimit: S.optional(S.Finite),
|
|
26
|
+
reportAllKillers: S.Boolean
|
|
27
|
+
}) {};
|
|
28
|
+
const VitestMutantRunTypeId = Symbol.for("@systemfsoftware/stryker-js-vitest-runner/VitestMutantRun");
|
|
29
|
+
var MutantKilled = class extends S.TaggedClass()("Killed", {
|
|
30
|
+
testsJson: S.String,
|
|
31
|
+
killerIds: S.optional(S.Array(S.String)),
|
|
32
|
+
failureMessage: S.optional(S.String)
|
|
33
|
+
}) {
|
|
34
|
+
[VitestMutantRunTypeId] = VitestMutantRunTypeId;
|
|
35
|
+
};
|
|
36
|
+
var MutantSurvived = class extends S.TaggedClass()("Survived", { testsJson: S.String }) {
|
|
37
|
+
[VitestMutantRunTypeId] = VitestMutantRunTypeId;
|
|
38
|
+
};
|
|
39
|
+
var MutantTimeout = class extends S.TaggedClass()("Timeout", {
|
|
40
|
+
testsJson: S.String,
|
|
41
|
+
reason: S.optional(S.String)
|
|
42
|
+
}) {
|
|
43
|
+
[VitestMutantRunTypeId] = VitestMutantRunTypeId;
|
|
44
|
+
};
|
|
45
|
+
var MutantDryError = class extends S.TaggedClass()("Error", {
|
|
46
|
+
testsJson: S.String,
|
|
47
|
+
errorMessage: S.optional(S.String)
|
|
48
|
+
}) {
|
|
49
|
+
[VitestMutantRunTypeId] = VitestMutantRunTypeId;
|
|
50
|
+
};
|
|
51
|
+
var VitestMutantRunError = class extends S.TaggedError()("VitestMutantRunError", { message: S.String }) {
|
|
52
|
+
[VitestMutantRunTypeId] = VitestMutantRunTypeId;
|
|
53
|
+
};
|
|
73
54
|
var VitestDryRunCommand$1 = class extends S.TaggedClass()("VitestDryRunCommand", {
|
|
74
55
|
rawTests: S.Array(S.Unknown),
|
|
75
56
|
projectRoot: S.String,
|
|
76
57
|
hasExternalError: S.Boolean,
|
|
77
58
|
externalErrorText: S.String
|
|
78
59
|
}) {};
|
|
79
|
-
var VitestDryRunOutput
|
|
60
|
+
var VitestDryRunOutput = class extends S.TaggedClass()("VitestDryRunOutput", {
|
|
80
61
|
status: S.Literals(["Complete", "Error"]),
|
|
81
62
|
testsJson: S.String,
|
|
82
63
|
errorMessage: S.optional(S.String)
|
|
83
64
|
}) {};
|
|
84
|
-
S.TaggedError()("VitestDryRunError", { message: S.String });
|
|
85
65
|
const recordOption$1 = (value) => S.decodeUnknownOption(S.Record(S.String, S.Unknown))(value);
|
|
86
66
|
const getStringField$1 = (record, key) => Option.fromNullishOr(record[key]).pipe(Option.filter((v) => typeof v === "string"));
|
|
87
67
|
const getNumberField$1 = (record, key) => Option.fromNullishOr(record[key]).pipe(Option.filter((v) => typeof v === "number"));
|
|
@@ -130,12 +110,6 @@ const toRawTestIdRaw$1 = (test) => {
|
|
|
130
110
|
onSome: (file) => Option.getOrElse(Option.fromNullishOr(getFilepath$1(file)), () => "unknown.js")
|
|
131
111
|
})}#${collectTestNameRaw$1(test)}`;
|
|
132
112
|
};
|
|
133
|
-
/**
|
|
134
|
-
* A test id is `<file>#<test name>`, and the file is reported relative to the
|
|
135
|
-
* project root so an id is stable across machines and sandbox directories.
|
|
136
|
-
* Vitest reports an absolute path, so the root prefix is stripped here rather
|
|
137
|
-
* than resolved — a decision body has no path service and needs none.
|
|
138
|
-
*/
|
|
139
113
|
const normalizeTestIdRaw$1 = (id, projectRoot) => {
|
|
140
114
|
const hash = id.indexOf("#");
|
|
141
115
|
if (hash === -1) return id;
|
|
@@ -220,65 +194,146 @@ const convertTestRaw$1 = (test, projectRoot) => {
|
|
|
220
194
|
status
|
|
221
195
|
})));
|
|
222
196
|
};
|
|
223
|
-
const decideVitestDryRun$1 = (command) => {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}))), Match.orElse(() => Result.succeed(VitestDryRunOutput$1.make({
|
|
237
|
-
status: "Complete",
|
|
238
|
-
testsJson: JSON.stringify(tests),
|
|
239
|
-
errorMessage: void 0
|
|
240
|
-
}))));
|
|
197
|
+
const decideVitestDryRun$1 = (command) => Match.value(command.rawTests.map((t) => convertTestRaw$1(t, command.projectRoot))).pipe(Match.when((tests) => tests.some((t) => t.status === "failed") === false && command.hasExternalError === true, (tests) => Result.succeed(VitestDryRunOutput.make({
|
|
198
|
+
status: "Error",
|
|
199
|
+
testsJson: JSON.stringify(tests),
|
|
200
|
+
errorMessage: `An error occurred outside of a test run: ${command.externalErrorText}`
|
|
201
|
+
}))), Match.orElse((tests) => Result.succeed(VitestDryRunOutput.make({
|
|
202
|
+
status: "Complete",
|
|
203
|
+
testsJson: JSON.stringify(tests),
|
|
204
|
+
errorMessage: void 0
|
|
205
|
+
}))));
|
|
206
|
+
const hitLimitReason = (hitCount, hitLimit) => {
|
|
207
|
+
if (hitCount === void 0 || hitLimit === void 0) return Option.none();
|
|
208
|
+
if (hitCount > hitLimit) return Option.some(`Hit limit reached (${hitCount}/${hitLimit})`);
|
|
209
|
+
return Option.none();
|
|
241
210
|
};
|
|
242
|
-
const
|
|
211
|
+
const decideVitestMutantRun = (command) => Match.value(hitLimitReason(command.hitCount, command.hitLimit)).pipe(Match.when(Option.isSome, (hit) => Result.succeed(MutantTimeout.make({
|
|
212
|
+
testsJson: "[]",
|
|
213
|
+
reason: hit.value
|
|
214
|
+
}))), Match.when(Option.isNone, () => {
|
|
215
|
+
const dryOut = decideVitestDryRun$1(VitestDryRunCommand$1.make({
|
|
216
|
+
rawTests: command.rawTests,
|
|
217
|
+
projectRoot: command.projectRoot,
|
|
218
|
+
hasExternalError: command.hasExternalError,
|
|
219
|
+
externalErrorText: command.externalErrorText
|
|
220
|
+
}));
|
|
221
|
+
return Match.value(Result.isFailure(dryOut)).pipe(Match.when(true, () => Result.fail(new VitestMutantRunError({ message: "dry run mapping failed" }))), Match.when(false, () => {
|
|
222
|
+
const dry = Result.getOrElse(dryOut, () => VitestDryRunOutput.make({
|
|
223
|
+
status: "Complete",
|
|
224
|
+
testsJson: "[]",
|
|
225
|
+
errorMessage: void 0
|
|
226
|
+
}));
|
|
227
|
+
return Match.value(dry.status === "Error").pipe(Match.when(true, () => Result.succeed(MutantDryError.make({
|
|
228
|
+
testsJson: "[]",
|
|
229
|
+
errorMessage: dry.errorMessage
|
|
230
|
+
}))), Match.when(false, () => {
|
|
231
|
+
const testsOption = Option.liftThrowable((input) => JSON.parse(input))(dry.testsJson).pipe(Option.filter((v) => Array.isArray(v)));
|
|
232
|
+
const killed = Option.getOrElse(testsOption, () => []).filter((t) => t.status === "failed");
|
|
233
|
+
return Match.value(killed.length > 0).pipe(Match.when(true, () => Match.value(command.reportAllKillers).pipe(Match.when(true, () => {
|
|
234
|
+
const firstKiller = Option.fromNullishOr(killed[0]);
|
|
235
|
+
const failureMessage = Option.match(firstKiller, {
|
|
236
|
+
onNone: () => void 0,
|
|
237
|
+
onSome: (k) => k.failureMessage
|
|
238
|
+
});
|
|
239
|
+
return Result.succeed(MutantKilled.make({
|
|
240
|
+
testsJson: dry.testsJson,
|
|
241
|
+
killerIds: killed.map((t) => t.id),
|
|
242
|
+
failureMessage
|
|
243
|
+
}));
|
|
244
|
+
}), Match.when(false, () => {
|
|
245
|
+
const first = Option.fromNullishOr(killed[0]);
|
|
246
|
+
const failureMessage = Option.match(first, {
|
|
247
|
+
onNone: () => void 0,
|
|
248
|
+
onSome: (k) => k.failureMessage
|
|
249
|
+
});
|
|
250
|
+
return Match.value(Option.isSome(first)).pipe(Match.when(true, () => Result.succeed(MutantKilled.make({
|
|
251
|
+
testsJson: dry.testsJson,
|
|
252
|
+
killerIds: Option.match(first, {
|
|
253
|
+
onNone: () => void 0,
|
|
254
|
+
onSome: (k) => [k.id]
|
|
255
|
+
}),
|
|
256
|
+
failureMessage
|
|
257
|
+
}))), Match.when(false, () => Result.succeed(MutantKilled.make({
|
|
258
|
+
testsJson: dry.testsJson,
|
|
259
|
+
killerIds: Option.getOrUndefined(Option.match(first, {
|
|
260
|
+
onNone: () => Option.none(),
|
|
261
|
+
onSome: (k) => Option.some([k.id])
|
|
262
|
+
})),
|
|
263
|
+
failureMessage
|
|
264
|
+
}))), Match.exhaustive);
|
|
265
|
+
}), Match.exhaustive)), Match.when(false, () => Result.succeed(MutantSurvived.make({ testsJson: dry.testsJson }))), Match.exhaustive);
|
|
266
|
+
}), Match.exhaustive);
|
|
267
|
+
}), Match.exhaustive);
|
|
268
|
+
}), Match.exhaustive);
|
|
269
|
+
const interpretVitestRun = Workflow.make(VitestMutantRunCommand, decideVitestMutantRun);
|
|
243
270
|
//#endregion
|
|
244
|
-
//#region src/
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
reason: S.optional(S.String)
|
|
269
|
-
}) {};
|
|
270
|
-
var VitestMutantRunError = class extends S.TaggedError()("VitestMutantRunError", { message: S.String }) {};
|
|
271
|
+
//#region src/Runner.schema.ts
|
|
272
|
+
const VitestRunnerOptionsSchema = S.Struct({
|
|
273
|
+
dir: S.optional(S.String),
|
|
274
|
+
related: S.optional(S.Boolean).pipe(S.withDecodingDefault(Effect.succeed(true))),
|
|
275
|
+
configFile: S.optional(S.String)
|
|
276
|
+
});
|
|
277
|
+
const VitestSectionSchema = S.optional(VitestRunnerOptionsSchema).pipe(S.withDecodingDefault(Effect.succeed({ related: true })));
|
|
278
|
+
const HitCountMetaSchema = S.Struct({ hitCount: S.optional(S.Finite) });
|
|
279
|
+
const MutantCoverageMetaSchema = S.Struct({ mutantCoverage: S.optional(S.Struct({
|
|
280
|
+
static: S.Record(S.String, S.Finite),
|
|
281
|
+
perTest: S.Record(S.String, S.Record(S.String, S.Finite))
|
|
282
|
+
})) });
|
|
283
|
+
const MutantCoverageShapeSchema = S.Struct({
|
|
284
|
+
static: S.Record(S.String, S.Finite),
|
|
285
|
+
perTest: S.Record(S.String, S.Record(S.String, S.Finite))
|
|
286
|
+
});
|
|
287
|
+
var CoverageDecodeFailed = class extends S.TaggedError()("CoverageDecodeFailed", { cause: S.Unknown }) {};
|
|
288
|
+
const ExportEntry = S.Union([S.String, S.Record(S.String, S.Unknown)]);
|
|
289
|
+
const PackageManifest = S.StructWithRest(S.Struct({
|
|
290
|
+
name: S.optional(S.String),
|
|
291
|
+
exports: S.optional(S.Record(S.String, ExportEntry))
|
|
292
|
+
}), [S.Record(S.String, S.Unknown)]);
|
|
293
|
+
const VitestNodeModuleSchema = S.declare((input) => input !== null && typeof input === "object" && !Array.isArray(input), { description: "The project-local vitest/node module" });
|
|
294
|
+
const VitestPackageSchema = S.Struct({ version: S.String });
|
|
271
295
|
var VitestDryRunCommand = class extends S.TaggedClass()("VitestDryRunCommand", {
|
|
272
296
|
rawTests: S.Array(S.Unknown),
|
|
273
297
|
projectRoot: S.String,
|
|
274
298
|
hasExternalError: S.Boolean,
|
|
275
299
|
externalErrorText: S.String
|
|
276
300
|
}) {};
|
|
277
|
-
var
|
|
278
|
-
|
|
301
|
+
var DryRunComplete = class extends S.TaggedClass()("Complete", { testsJson: S.String }) {};
|
|
302
|
+
var DryRunExternalError = class extends S.TaggedClass()("Error", {
|
|
279
303
|
testsJson: S.String,
|
|
280
|
-
errorMessage: S.
|
|
304
|
+
errorMessage: S.String
|
|
281
305
|
}) {};
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region src/Runner.ts
|
|
308
|
+
var VitestHarness = class extends Context.Service()("VitestHarness") {};
|
|
309
|
+
function fromTestId(id) {
|
|
310
|
+
const [file, ...name] = id.split("#");
|
|
311
|
+
return {
|
|
312
|
+
file,
|
|
313
|
+
test: name.join("#")
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function normalizeTestId(id, projectRoot, pathService) {
|
|
317
|
+
const { file, test } = fromTestId(id);
|
|
318
|
+
return `${normalizeFileName(pathService.relative(projectRoot, file))}#${test}`;
|
|
319
|
+
}
|
|
320
|
+
function normalizeCoverage(rawCoverage, projectRoot, pathService) {
|
|
321
|
+
return {
|
|
322
|
+
perTest: Object.fromEntries(Object.entries(rawCoverage.perTest).map(([rawTestId, coverageData]) => [normalizeTestId(rawTestId, projectRoot, pathService), coverageData])),
|
|
323
|
+
static: rawCoverage.static
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function collectTestsFromSuite(suite) {
|
|
327
|
+
return suite.tasks.flatMap((task) => {
|
|
328
|
+
if (task.type === "suite") return collectTestsFromSuite(task);
|
|
329
|
+
return task;
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
function isErrorCodeError(error) {
|
|
333
|
+
if (error instanceof Error && "code" in error) return typeof Reflect.get(error, "code") === "string";
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
const VITEST_ERROR_CODES = Object.freeze({ FILES_NOT_FOUND: "VITEST_FILES_NOT_FOUND" });
|
|
282
337
|
const recordOption = (value) => S.decodeUnknownOption(S.Record(S.String, S.Unknown))(value);
|
|
283
338
|
const getStringField = (record, key) => Option.fromNullishOr(record[key]).pipe(Option.filter((v) => typeof v === "string"));
|
|
284
339
|
const getNumberField = (record, key) => Option.fromNullishOr(record[key]).pipe(Option.filter((v) => typeof v === "number"));
|
|
@@ -327,12 +382,6 @@ const toRawTestIdRaw = (test) => {
|
|
|
327
382
|
onSome: (file) => Option.getOrElse(Option.fromNullishOr(getFilepath(file)), () => "unknown.js")
|
|
328
383
|
})}#${collectTestNameRaw(test)}`;
|
|
329
384
|
};
|
|
330
|
-
/**
|
|
331
|
-
* A test id is `<file>#<test name>`, and the file is reported relative to the
|
|
332
|
-
* project root so an id is stable across machines and sandbox directories.
|
|
333
|
-
* Vitest reports an absolute path, so the root prefix is stripped here rather
|
|
334
|
-
* than resolved — a decision body has no path service and needs none.
|
|
335
|
-
*/
|
|
336
385
|
const normalizeTestIdRaw = (id, projectRoot) => {
|
|
337
386
|
const hash = id.indexOf("#");
|
|
338
387
|
if (hash === -1) return id;
|
|
@@ -417,134 +466,14 @@ const convertTestRaw = (test, projectRoot) => {
|
|
|
417
466
|
status
|
|
418
467
|
})));
|
|
419
468
|
};
|
|
420
|
-
const decideVitestDryRun = (command) =>
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
status: "Complete",
|
|
426
|
-
testsJson: JSON.stringify(tests),
|
|
427
|
-
errorMessage: void 0
|
|
428
|
-
}))));
|
|
429
|
-
/**
|
|
430
|
-
* The hit-limit cutoff: `Some` iff both numbers are present AND the count
|
|
431
|
-
* strictly exceeds the limit. The boundary is `>` and not `>=` on purpose —
|
|
432
|
-
* `hitCount === hitLimit` is the last permitted hit, not one too many.
|
|
433
|
-
*/
|
|
434
|
-
const hitLimitReason = (hitCount, hitLimit) => {
|
|
435
|
-
if (hitCount === void 0 || hitLimit === void 0) return Option.none();
|
|
436
|
-
if (hitCount > hitLimit) return Option.some(`Hit limit reached (${hitCount}/${hitLimit})`);
|
|
437
|
-
return Option.none();
|
|
438
|
-
};
|
|
439
|
-
const decideVitestMutantRun = (command) => Match.value(hitLimitReason(command.hitCount, command.hitLimit)).pipe(Match.when(Option.isSome, (hit) => Result.succeed(VitestMutantRunOutput.make({
|
|
440
|
-
status: "Timeout",
|
|
441
|
-
testsJson: "[]",
|
|
442
|
-
errorMessage: void 0,
|
|
443
|
-
killerIds: void 0,
|
|
444
|
-
failureMessage: void 0,
|
|
445
|
-
reason: hit.value
|
|
446
|
-
}))), Match.when(Option.isNone, () => {
|
|
447
|
-
const dryOut = decideVitestDryRun(VitestDryRunCommand.make({
|
|
448
|
-
rawTests: command.rawTests,
|
|
449
|
-
projectRoot: command.projectRoot,
|
|
450
|
-
hasExternalError: command.hasExternalError,
|
|
451
|
-
externalErrorText: command.externalErrorText
|
|
452
|
-
}));
|
|
453
|
-
return Match.value(Result.isFailure(dryOut)).pipe(Match.when(true, () => Result.fail(new VitestMutantRunError({ message: "dry run mapping failed" }))), Match.when(false, () => {
|
|
454
|
-
const dry = Result.getOrElse(dryOut, () => VitestDryRunOutput.make({
|
|
455
|
-
status: "Complete",
|
|
456
|
-
testsJson: "[]",
|
|
457
|
-
errorMessage: void 0
|
|
458
|
-
}));
|
|
459
|
-
return Match.value(dry.status === "Error").pipe(Match.when(true, () => Result.succeed(VitestMutantRunOutput.make({
|
|
460
|
-
status: "Error",
|
|
461
|
-
testsJson: "[]",
|
|
462
|
-
errorMessage: dry.errorMessage,
|
|
463
|
-
killerIds: void 0,
|
|
464
|
-
failureMessage: void 0
|
|
465
|
-
}))), Match.when(false, () => {
|
|
466
|
-
const testsOption = Option.liftThrowable((input) => JSON.parse(input))(dry.testsJson).pipe(Option.filter((v) => Array.isArray(v)));
|
|
467
|
-
const killed = Option.getOrElse(testsOption, () => []).filter((t) => t.status === "failed");
|
|
468
|
-
return Match.value(killed.length > 0).pipe(Match.when(true, () => Match.value(command.reportAllKillers).pipe(Match.when(true, () => {
|
|
469
|
-
const firstKiller = Option.fromNullishOr(killed[0]);
|
|
470
|
-
const failureMessage = Option.match(firstKiller, {
|
|
471
|
-
onNone: () => void 0,
|
|
472
|
-
onSome: (k) => k.failureMessage
|
|
473
|
-
});
|
|
474
|
-
return Result.succeed(VitestMutantRunOutput.make({
|
|
475
|
-
status: "Killed",
|
|
476
|
-
testsJson: dry.testsJson,
|
|
477
|
-
errorMessage: void 0,
|
|
478
|
-
killerIds: killed.map((t) => t.id),
|
|
479
|
-
failureMessage
|
|
480
|
-
}));
|
|
481
|
-
}), Match.when(false, () => {
|
|
482
|
-
const first = Option.fromNullishOr(killed[0]);
|
|
483
|
-
const failureMessage = Option.match(first, {
|
|
484
|
-
onNone: () => void 0,
|
|
485
|
-
onSome: (k) => k.failureMessage
|
|
486
|
-
});
|
|
487
|
-
return Match.value(Option.isSome(first)).pipe(Match.when(true, () => Result.succeed(VitestMutantRunOutput.make({
|
|
488
|
-
status: "Killed",
|
|
489
|
-
testsJson: dry.testsJson,
|
|
490
|
-
errorMessage: void 0,
|
|
491
|
-
killerIds: Option.match(first, {
|
|
492
|
-
onNone: () => void 0,
|
|
493
|
-
onSome: (k) => [k.id]
|
|
494
|
-
}),
|
|
495
|
-
failureMessage
|
|
496
|
-
}))), Match.when(false, () => Result.succeed(VitestMutantRunOutput.make({
|
|
497
|
-
status: "Killed",
|
|
498
|
-
testsJson: dry.testsJson,
|
|
499
|
-
errorMessage: void 0,
|
|
500
|
-
killerIds: Option.getOrUndefined(Option.match(first, {
|
|
501
|
-
onNone: () => Option.none(),
|
|
502
|
-
onSome: (k) => Option.some([k.id])
|
|
503
|
-
})),
|
|
504
|
-
failureMessage
|
|
505
|
-
}))), Match.exhaustive);
|
|
506
|
-
}), Match.exhaustive)), Match.when(false, () => Result.succeed(VitestMutantRunOutput.make({
|
|
507
|
-
status: "Survived",
|
|
508
|
-
testsJson: dry.testsJson,
|
|
509
|
-
errorMessage: void 0,
|
|
510
|
-
killerIds: void 0,
|
|
511
|
-
failureMessage: void 0
|
|
512
|
-
}))), Match.exhaustive);
|
|
513
|
-
}), Match.exhaustive);
|
|
514
|
-
}), Match.exhaustive);
|
|
515
|
-
}), Match.exhaustive);
|
|
516
|
-
const vitestMutantRunWorkflow = Workflow.make(VitestMutantRunCommand, decideVitestMutantRun);
|
|
517
|
-
//#endregion
|
|
518
|
-
//#region src/Runner.ts
|
|
519
|
-
function fromTestId(id) {
|
|
520
|
-
const [file, ...name] = id.split("#");
|
|
521
|
-
return {
|
|
522
|
-
file,
|
|
523
|
-
test: name.join("#")
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
function normalizeTestId(id, projectRoot, pathService) {
|
|
527
|
-
const { file, test } = fromTestId(id);
|
|
528
|
-
return `${normalizeFileName(pathService.relative(projectRoot, file))}#${test}`;
|
|
529
|
-
}
|
|
530
|
-
function normalizeCoverage(rawCoverage, projectRoot, pathService) {
|
|
531
|
-
return {
|
|
532
|
-
perTest: Object.fromEntries(Object.entries(rawCoverage.perTest).map(([rawTestId, coverageData]) => [normalizeTestId(rawTestId, projectRoot, pathService), coverageData])),
|
|
533
|
-
static: rawCoverage.static
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
function collectTestsFromSuite(suite) {
|
|
537
|
-
return suite.tasks.flatMap((task) => {
|
|
538
|
-
if (task.type === "suite") return collectTestsFromSuite(task);
|
|
539
|
-
return task;
|
|
469
|
+
const decideVitestDryRun = (command) => {
|
|
470
|
+
const tests = command.rawTests.map((t) => convertTestRaw(t, command.projectRoot));
|
|
471
|
+
if (tests.some((t) => t.status === "failed") === false && command.hasExternalError) return DryRunExternalError.make({
|
|
472
|
+
testsJson: JSON.stringify(tests),
|
|
473
|
+
errorMessage: `An error occurred outside of a test run: ${command.externalErrorText}`
|
|
540
474
|
});
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
if (error instanceof Error && "code" in error) return typeof Reflect.get(error, "code") === "string";
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
/** @see https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/node/errors.ts */
|
|
547
|
-
const VITEST_ERROR_CODES = Object.freeze({ FILES_NOT_FOUND: "VITEST_FILES_NOT_FOUND" });
|
|
475
|
+
return DryRunComplete.make({ testsJson: JSON.stringify(tests) });
|
|
476
|
+
};
|
|
548
477
|
const SOURCE_CONDITION = "@systemfsoftware/source";
|
|
549
478
|
const sourceTargetOf = (entry) => {
|
|
550
479
|
if (typeof entry === "string") return (() => {
|
|
@@ -592,12 +521,6 @@ const readSandboxSelfAliases = (projectRoot) => Effect$1.gen(function* () {
|
|
|
592
521
|
onSome: (manifest) => sandboxSelfAliases(manifest, projectRoot, pathService)
|
|
593
522
|
});
|
|
594
523
|
});
|
|
595
|
-
/**
|
|
596
|
-
* Vite records a package specifier as a bare dep. Vitest related-mode then
|
|
597
|
-
* joins that specifier onto the project root, misses the file, and reports
|
|
598
|
-
* zero tests. Returning the sandbox source path from `resolveId` makes the
|
|
599
|
-
* dep a real filesystem path related-mode can walk.
|
|
600
|
-
*/
|
|
601
524
|
const sandboxSelfPlugin = (aliases) => ({
|
|
602
525
|
name: "stryker-sandbox-self-exports",
|
|
603
526
|
enforce: "pre",
|
|
@@ -924,169 +847,173 @@ const makeVitestRunnerLayer = (input) => Layer.effect(TestRunner, Effect$1.gen(f
|
|
|
924
847
|
})()
|
|
925
848
|
};
|
|
926
849
|
});
|
|
927
|
-
const
|
|
928
|
-
(
|
|
929
|
-
|
|
850
|
+
const harnessImpl = {
|
|
851
|
+
setMode: (mode) => Effect$1.gen(function* () {
|
|
852
|
+
(yield* requireCtx).provide("mode", mode);
|
|
853
|
+
}),
|
|
854
|
+
provide: (key, value) => Effect$1.gen(function* () {
|
|
855
|
+
const ctx = yield* requireCtx;
|
|
856
|
+
if (key === "hitLimit") {
|
|
857
|
+
if (typeof value === "number" || value === void 0) ctx.provide("hitLimit", value);
|
|
858
|
+
else ctx.provide("hitLimit", void 0);
|
|
859
|
+
} else if (key === "mutantActivation") {
|
|
860
|
+
if (value === "runtime" || value === "static") ctx.provide("mutantActivation", value);
|
|
861
|
+
} else if (typeof value === "string") ctx.provide("activeMutant", value);
|
|
862
|
+
})
|
|
863
|
+
};
|
|
864
|
+
const mutantRunCell = Cell.layer({
|
|
865
|
+
read: (command) => Effect$1.gen(function* () {
|
|
866
|
+
const harness = yield* VitestHarness;
|
|
867
|
+
yield* harness.setMode("mutant");
|
|
868
|
+
yield* harness.provide("hitLimit", command.hitLimit);
|
|
869
|
+
yield* harness.provide("mutantActivation", command.mutantActivation);
|
|
870
|
+
yield* harness.provide("activeMutant", command.activeMutant.id);
|
|
871
|
+
const { rawTests, hasExternalError, externalErrorText } = yield* collectRaw({
|
|
872
|
+
testIds: (() => {
|
|
873
|
+
if (command.testFilter !== void 0) return [...command.testFilter];
|
|
874
|
+
})(),
|
|
875
|
+
relatedFiles: [command.sandboxFileName]
|
|
876
|
+
});
|
|
877
|
+
const hitCount = yield* readHitCount.pipe(Effect$1.mapError((cause) => new TestRunnerFailed({
|
|
878
|
+
runnerName: "vitest",
|
|
879
|
+
phase: "mutantRun",
|
|
880
|
+
cause: errorToString(cause)
|
|
881
|
+
})), Effect$1.option, Effect$1.map(Option.getOrUndefined));
|
|
882
|
+
const reportAllKillers = (() => {
|
|
883
|
+
if (typeof input.options.disableBail === "boolean") return input.options.disableBail;
|
|
884
|
+
return false;
|
|
885
|
+
})();
|
|
886
|
+
if (hitCount === void 0) return {
|
|
887
|
+
rawTests,
|
|
888
|
+
projectRoot: input.sandboxDirectory,
|
|
889
|
+
hasExternalError,
|
|
890
|
+
externalErrorText,
|
|
891
|
+
hitLimit: command.hitLimit,
|
|
892
|
+
reportAllKillers
|
|
893
|
+
};
|
|
894
|
+
return {
|
|
895
|
+
rawTests,
|
|
896
|
+
projectRoot: input.sandboxDirectory,
|
|
897
|
+
hasExternalError,
|
|
898
|
+
externalErrorText,
|
|
899
|
+
hitCount,
|
|
900
|
+
hitLimit: command.hitLimit,
|
|
901
|
+
reportAllKillers
|
|
902
|
+
};
|
|
903
|
+
}),
|
|
904
|
+
decode: (raw) => {
|
|
905
|
+
const base = {
|
|
906
|
+
rawTests: raw.rawTests,
|
|
907
|
+
projectRoot: raw.projectRoot,
|
|
908
|
+
hasExternalError: raw.hasExternalError,
|
|
909
|
+
externalErrorText: raw.externalErrorText,
|
|
910
|
+
reportAllKillers: raw.reportAllKillers
|
|
911
|
+
};
|
|
912
|
+
if (raw.hitCount !== void 0) {
|
|
913
|
+
if (raw.hitLimit !== void 0) return Result.succeed(new VitestMutantRunCommand({
|
|
914
|
+
...base,
|
|
915
|
+
hitCount: raw.hitCount,
|
|
916
|
+
hitLimit: raw.hitLimit
|
|
917
|
+
}));
|
|
918
|
+
return Result.succeed(new VitestMutantRunCommand({
|
|
919
|
+
...base,
|
|
920
|
+
hitCount: raw.hitCount
|
|
921
|
+
}));
|
|
922
|
+
}
|
|
923
|
+
if (raw.hitLimit !== void 0) return Result.succeed(new VitestMutantRunCommand({
|
|
924
|
+
...base,
|
|
925
|
+
hitLimit: raw.hitLimit
|
|
926
|
+
}));
|
|
927
|
+
return Result.succeed(new VitestMutantRunCommand(base));
|
|
928
|
+
},
|
|
929
|
+
decide: interpretVitestRun,
|
|
930
|
+
encode: (outcome) => Result.match(outcome, {
|
|
931
|
+
onFailure: (e) => ({
|
|
932
|
+
status: "error",
|
|
933
|
+
errorMessage: e.message
|
|
934
|
+
}),
|
|
935
|
+
onSuccess: (out) => {
|
|
936
|
+
const nrOfTests = () => {
|
|
937
|
+
try {
|
|
938
|
+
const raw = JSON.parse(out.testsJson);
|
|
939
|
+
if (Array.isArray(raw)) return raw.filter(isIdRecord).length;
|
|
940
|
+
return 0;
|
|
941
|
+
} catch {
|
|
942
|
+
return 0;
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
return Match.value(out).pipe(Match.tag("Error", (error) => ({
|
|
946
|
+
status: "error",
|
|
947
|
+
errorMessage: error.errorMessage ?? "unknown"
|
|
948
|
+
})), Match.tag("Timeout", (timeout) => (() => {
|
|
949
|
+
if (timeout.reason === void 0) return { status: "timeout" };
|
|
950
|
+
return {
|
|
951
|
+
status: "timeout",
|
|
952
|
+
reason: timeout.reason
|
|
953
|
+
};
|
|
954
|
+
})()), Match.tag("Killed", (killed) => ({
|
|
955
|
+
status: "killed",
|
|
956
|
+
failureMessage: killed.failureMessage ?? "",
|
|
957
|
+
killedBy: (() => {
|
|
958
|
+
if (killed.killerIds !== void 0) return [...killed.killerIds];
|
|
959
|
+
return [];
|
|
960
|
+
})(),
|
|
961
|
+
nrOfTests: nrOfTests()
|
|
962
|
+
})), Match.tag("Survived", () => ({
|
|
963
|
+
status: "survived",
|
|
964
|
+
nrOfTests: nrOfTests()
|
|
965
|
+
})), Match.exhaustive);
|
|
966
|
+
}
|
|
967
|
+
}),
|
|
968
|
+
write: (output, _raw) => Effect$1.succeed(output)
|
|
969
|
+
});
|
|
970
|
+
const dryRun = (options) => Effect$1.gen(function* () {
|
|
971
|
+
yield* (yield* VitestHarness).setMode("dry-run");
|
|
972
|
+
const hasTestFiles = testFilesProvided(options);
|
|
930
973
|
const filter = (() => {
|
|
931
974
|
if (hasTestFiles) return {
|
|
932
|
-
testFiles: [...
|
|
975
|
+
testFiles: [...options.testFiles ?? []],
|
|
933
976
|
relatedFiles: (() => {
|
|
934
|
-
if (
|
|
977
|
+
if (options.files !== void 0) return [...options.files];
|
|
935
978
|
})()
|
|
936
979
|
};
|
|
937
980
|
return { relatedFiles: (() => {
|
|
938
|
-
if (
|
|
981
|
+
if (options.files !== void 0) return [...options.files];
|
|
939
982
|
})() };
|
|
940
983
|
})();
|
|
941
984
|
const { rawTests, hasExternalError, externalErrorText } = yield* collectRaw(filter);
|
|
942
|
-
|
|
985
|
+
const decision = decideVitestDryRun(new VitestDryRunCommand({
|
|
943
986
|
rawTests,
|
|
944
987
|
projectRoot: input.sandboxDirectory,
|
|
945
988
|
hasExternalError,
|
|
946
989
|
externalErrorText
|
|
947
|
-
};
|
|
948
|
-
|
|
949
|
-
rawTests: raw.rawTests,
|
|
950
|
-
projectRoot: raw.projectRoot,
|
|
951
|
-
hasExternalError: raw.hasExternalError,
|
|
952
|
-
externalErrorText: raw.externalErrorText
|
|
953
|
-
}))), Cell.decide(vitestDryRunWorkflow), Cell.encode((outcome) => Result.match(outcome, {
|
|
954
|
-
onFailure: (e) => ({
|
|
990
|
+
}));
|
|
991
|
+
const result = Match.value(decision).pipe(Match.tag("Error", (error) => ({
|
|
955
992
|
status: "error",
|
|
956
|
-
errorMessage:
|
|
957
|
-
}),
|
|
958
|
-
|
|
959
|
-
const raw = JSON.parse(out.testsJson);
|
|
993
|
+
errorMessage: error.errorMessage
|
|
994
|
+
})), Match.tag("Complete", (complete) => {
|
|
995
|
+
const raw = JSON.parse(complete.testsJson);
|
|
960
996
|
let tests;
|
|
961
997
|
if (Array.isArray(raw)) tests = raw.filter(isTestResultLike);
|
|
962
998
|
else tests = [];
|
|
963
|
-
if (out.status === "Error") return {
|
|
964
|
-
status: "error",
|
|
965
|
-
errorMessage: out.errorMessage ?? "unknown"
|
|
966
|
-
};
|
|
967
999
|
return {
|
|
968
1000
|
status: "complete",
|
|
969
1001
|
tests
|
|
970
1002
|
};
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
if (output.status === "complete") {
|
|
1003
|
+
}), Match.exhaustive);
|
|
1004
|
+
if (result.status === "complete") {
|
|
974
1005
|
const mutantCoverage = yield* readMutantCoverage.pipe(Effect$1.mapError((cause) => new TestRunnerFailed({
|
|
975
1006
|
runnerName: "vitest",
|
|
976
1007
|
phase: "dryRun",
|
|
977
1008
|
cause: errorToString(cause)
|
|
978
1009
|
})));
|
|
979
1010
|
if (mutantCoverage !== void 0) return {
|
|
980
|
-
...
|
|
1011
|
+
...result,
|
|
981
1012
|
mutantCoverage
|
|
982
1013
|
};
|
|
983
1014
|
}
|
|
984
|
-
return
|
|
985
|
-
})))
|
|
986
|
-
const mutantRunDescription = pipe(Cell.read((command) => Effect$1.gen(function* () {
|
|
987
|
-
const ctx = yield* requireCtx;
|
|
988
|
-
ctx.provide("mode", "mutant");
|
|
989
|
-
ctx.provide("hitLimit", command.hitLimit);
|
|
990
|
-
ctx.provide("mutantActivation", command.mutantActivation);
|
|
991
|
-
ctx.provide("activeMutant", command.activeMutant.id);
|
|
992
|
-
const { rawTests, hasExternalError, externalErrorText } = yield* collectRaw({
|
|
993
|
-
testIds: (() => {
|
|
994
|
-
if (command.testFilter !== void 0) return [...command.testFilter];
|
|
995
|
-
})(),
|
|
996
|
-
relatedFiles: [command.sandboxFileName]
|
|
997
|
-
});
|
|
998
|
-
const hitCount = yield* readHitCount.pipe(Effect$1.mapError((cause) => new TestRunnerFailed({
|
|
999
|
-
runnerName: "vitest",
|
|
1000
|
-
phase: "mutantRun",
|
|
1001
|
-
cause: errorToString(cause)
|
|
1002
|
-
})), Effect$1.option, Effect$1.map(Option.getOrUndefined));
|
|
1003
|
-
const reportAllKillers = (() => {
|
|
1004
|
-
if (typeof input.options.disableBail === "boolean") return input.options.disableBail;
|
|
1005
|
-
return false;
|
|
1006
|
-
})();
|
|
1007
|
-
if (hitCount === void 0) return {
|
|
1008
|
-
rawTests,
|
|
1009
|
-
projectRoot: input.sandboxDirectory,
|
|
1010
|
-
hasExternalError,
|
|
1011
|
-
externalErrorText,
|
|
1012
|
-
hitLimit: command.hitLimit,
|
|
1013
|
-
reportAllKillers
|
|
1014
|
-
};
|
|
1015
|
-
return {
|
|
1016
|
-
rawTests,
|
|
1017
|
-
projectRoot: input.sandboxDirectory,
|
|
1018
|
-
hasExternalError,
|
|
1019
|
-
externalErrorText,
|
|
1020
|
-
hitCount,
|
|
1021
|
-
hitLimit: command.hitLimit,
|
|
1022
|
-
reportAllKillers
|
|
1023
|
-
};
|
|
1024
|
-
})), Cell.decode((raw) => {
|
|
1025
|
-
const base = {
|
|
1026
|
-
rawTests: raw.rawTests,
|
|
1027
|
-
projectRoot: raw.projectRoot,
|
|
1028
|
-
hasExternalError: raw.hasExternalError,
|
|
1029
|
-
externalErrorText: raw.externalErrorText,
|
|
1030
|
-
reportAllKillers: raw.reportAllKillers
|
|
1031
|
-
};
|
|
1032
|
-
if (raw.hitCount !== void 0) {
|
|
1033
|
-
if (raw.hitLimit !== void 0) return Result.succeed(new VitestMutantRunCommand({
|
|
1034
|
-
...base,
|
|
1035
|
-
hitCount: raw.hitCount,
|
|
1036
|
-
hitLimit: raw.hitLimit
|
|
1037
|
-
}));
|
|
1038
|
-
return Result.succeed(new VitestMutantRunCommand({
|
|
1039
|
-
...base,
|
|
1040
|
-
hitCount: raw.hitCount
|
|
1041
|
-
}));
|
|
1042
|
-
}
|
|
1043
|
-
if (raw.hitLimit !== void 0) return Result.succeed(new VitestMutantRunCommand({
|
|
1044
|
-
...base,
|
|
1045
|
-
hitLimit: raw.hitLimit
|
|
1046
|
-
}));
|
|
1047
|
-
return Result.succeed(new VitestMutantRunCommand(base));
|
|
1048
|
-
}), Cell.decide(vitestMutantRunWorkflow), Cell.encode((outcome) => Result.match(outcome, {
|
|
1049
|
-
onFailure: (e) => ({
|
|
1050
|
-
status: "error",
|
|
1051
|
-
errorMessage: e.message
|
|
1052
|
-
}),
|
|
1053
|
-
onSuccess: (out) => {
|
|
1054
|
-
let parsed;
|
|
1055
|
-
try {
|
|
1056
|
-
const raw = JSON.parse(out.testsJson);
|
|
1057
|
-
if (Array.isArray(raw)) parsed = raw.filter(isIdRecord);
|
|
1058
|
-
else parsed = [];
|
|
1059
|
-
} catch {
|
|
1060
|
-
parsed = [];
|
|
1061
|
-
}
|
|
1062
|
-
const nrOfTests = parsed.length;
|
|
1063
|
-
if (out.status === "Error") return {
|
|
1064
|
-
status: "error",
|
|
1065
|
-
errorMessage: out.errorMessage ?? "unknown"
|
|
1066
|
-
};
|
|
1067
|
-
if (out.status === "Timeout") {
|
|
1068
|
-
if (out.reason === void 0) return { status: "timeout" };
|
|
1069
|
-
return {
|
|
1070
|
-
status: "timeout",
|
|
1071
|
-
reason: out.reason
|
|
1072
|
-
};
|
|
1073
|
-
}
|
|
1074
|
-
if (out.status === "Killed") return {
|
|
1075
|
-
status: "killed",
|
|
1076
|
-
failureMessage: out.failureMessage ?? "",
|
|
1077
|
-
killedBy: (() => {
|
|
1078
|
-
if (out.killerIds !== void 0) return [...out.killerIds];
|
|
1079
|
-
return [];
|
|
1080
|
-
})(),
|
|
1081
|
-
nrOfTests
|
|
1082
|
-
};
|
|
1083
|
-
return {
|
|
1084
|
-
status: "survived",
|
|
1085
|
-
nrOfTests
|
|
1086
|
-
};
|
|
1087
|
-
}
|
|
1088
|
-
})), Cell.write((output) => Effect$1.succeed(output)));
|
|
1089
|
-
const dryRun = (options) => Cell.apply(dryRunDescription, options).pipe(Effect$1.mapError((cause) => (() => {
|
|
1015
|
+
return result;
|
|
1016
|
+
}).pipe(Effect$1.provideService(VitestHarness, harnessImpl), Effect$1.mapError((cause) => (() => {
|
|
1090
1017
|
if (cause instanceof TestRunnerFailed) return cause;
|
|
1091
1018
|
return new TestRunnerFailed({
|
|
1092
1019
|
runnerName: "vitest",
|
|
@@ -1094,7 +1021,7 @@ const makeVitestRunnerLayer = (input) => Layer.effect(TestRunner, Effect$1.gen(f
|
|
|
1094
1021
|
cause: errorToString(cause)
|
|
1095
1022
|
});
|
|
1096
1023
|
})()));
|
|
1097
|
-
const mutantRun = (options) => Cell.
|
|
1024
|
+
const mutantRun = (options) => Cell.run(mutantRunCell, options).pipe(Effect$1.provideService(VitestHarness, harnessImpl), Effect$1.mapError((cause) => (() => {
|
|
1098
1025
|
if (cause instanceof TestRunnerFailed) return cause;
|
|
1099
1026
|
return new TestRunnerFailed({
|
|
1100
1027
|
runnerName: "vitest",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemfsoftware/stryker-js-vitest-runner",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"coverageAnalysis": "perTest"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@systemfsoftware/
|
|
35
|
-
"@systemfsoftware/
|
|
34
|
+
"@systemfsoftware/stryker-js": "^1.0.0",
|
|
35
|
+
"@systemfsoftware/effect-cell-types": "^6.0.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"effect": "^4.0.0-rc.112",
|
|
@@ -50,10 +50,9 @@
|
|
|
50
50
|
"tsdown": "^0.22.14",
|
|
51
51
|
"typescript": "^7",
|
|
52
52
|
"vitest": "^4",
|
|
53
|
-
"@systemfsoftware/all": "^1.1.
|
|
53
|
+
"@systemfsoftware/all": "^1.1.2",
|
|
54
54
|
"@systemfsoftware/effect-gherkin-spec": "^4.0.0",
|
|
55
55
|
"@systemfsoftware/oxlint-config": "^0.1.0",
|
|
56
|
-
"@systemfsoftware/stryker-js-platform-node": "^0.2.0",
|
|
57
56
|
"@systemfsoftware/tsconfig": "^1.3.3",
|
|
58
57
|
"@systemfsoftware/vitest-config": "^0.1.0"
|
|
59
58
|
},
|