@systemfsoftware/stryker-js 13.1.0 → 15.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 +62 -0
- package/README.md +30 -0
- package/dist/Run.schema-B1HZugu9.d.mts +24 -0
- package/dist/Run.schema-DuaneDGd.mjs +57 -0
- package/dist/RunEnvironment.service-B1bsWOQ9.d.mts +2927 -0
- package/dist/config.d.mts +4 -4
- package/dist/config.mjs +1 -1
- package/dist/events.d.mts +2 -2
- package/dist/events.mjs +2 -2
- package/dist/{index-Ptvmn934.d.mts → index-Cf9G6kA8.d.mts} +1683 -3073
- package/dist/index.d.mts +622 -105
- package/dist/index.mjs +1104 -26
- package/dist/main.mjs +53956 -34882
- package/dist/{merge-config-BVdwN_LJ.d.mts → merge-config-BdQdK3PM.d.mts} +4 -4
- package/dist/merge-config-zsGl1aWc.mjs +1473 -0
- package/dist/promises.d.mts +3 -3
- package/dist/promises.mjs +1 -1
- package/dist/run-stages-aBT_QAfO.mjs +20687 -0
- package/package.json +17 -17
- package/dist/Run.schema-BwLLAYqu.d.mts +0 -325
- package/dist/Run.schema-Cv2_Kup0.mjs +0 -272
- package/dist/RunEnvironment.service-rkMZ8nm1.d.mts +0 -530
- package/dist/dist-CQ7r4AaH.mjs +0 -8142
- package/dist/merge-config-DZHwEkGY.mjs +0 -63
- package/dist/run-stages.cell-rdoY0cVH.mjs +0 -8857
|
@@ -0,0 +1,1473 @@
|
|
|
1
|
+
import * as S from "effect/Schema";
|
|
2
|
+
import * as Option$1 from "effect/Option";
|
|
3
|
+
import * as Order from "effect/Order";
|
|
4
|
+
import * as SchemaGetter$1 from "effect/SchemaGetter";
|
|
5
|
+
import * as SchemaTransformation$1 from "effect/SchemaTransformation";
|
|
6
|
+
import * as Context from "effect/Context";
|
|
7
|
+
import { Effect, Schema, SchemaGetter, SchemaIssue, SchemaTransformation } from "effect";
|
|
8
|
+
import * as Effect$1 from "effect/Effect";
|
|
9
|
+
import * as Boolean$1 from "effect/Boolean";
|
|
10
|
+
import * as Rpc from "effect/rpc/Rpc";
|
|
11
|
+
import * as RpcGroup from "effect/rpc/RpcGroup";
|
|
12
|
+
import * as RpcMiddleware from "effect/rpc/RpcMiddleware";
|
|
13
|
+
import * as Match$1 from "effect/Match";
|
|
14
|
+
import { dual } from "effect/Function";
|
|
15
|
+
import * as Record$1 from "effect/Record";
|
|
16
|
+
import * as Predicate$1 from "effect/Predicate";
|
|
17
|
+
//#region ../stryker-js-plugin-interface/dist/rolldown-runtime-D7D4PA-g.mjs
|
|
18
|
+
var __defProp = Object.defineProperty;
|
|
19
|
+
var __exportAll = (all, no_symbols) => {
|
|
20
|
+
let target = {};
|
|
21
|
+
for (var name in all) __defProp(target, name, {
|
|
22
|
+
get: all[name],
|
|
23
|
+
enumerable: true
|
|
24
|
+
});
|
|
25
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
26
|
+
return target;
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region ../stryker-js-plugin-interface/dist/index.mjs
|
|
30
|
+
/** A 1-based line: the first line of a file is line 1. */
|
|
31
|
+
const Line = S.Int.check(S.isGreaterThanOrEqualTo(1));
|
|
32
|
+
/** A 1-based column: the first character of a line is column 1. */
|
|
33
|
+
const Column = S.Int.check(S.isGreaterThanOrEqualTo(1));
|
|
34
|
+
const Position$1 = S.Struct({
|
|
35
|
+
line: Line,
|
|
36
|
+
column: Column
|
|
37
|
+
});
|
|
38
|
+
const positionOrder = Order.combine(Order.mapInput(Order.Number, (position) => position.line), Order.mapInput(Order.Number, (position) => position.column));
|
|
39
|
+
const inOrder = (order) => (ends) => ({
|
|
40
|
+
start: Order.min(order)(ends.start, ends.end),
|
|
41
|
+
end: Order.max(order)(ends.start, ends.end)
|
|
42
|
+
});
|
|
43
|
+
const notReversed = (order) => (ends) => Order.isLessThanOrEqualTo(order)(ends.start, ends.end);
|
|
44
|
+
const PositionEndsSchema = S.Struct({
|
|
45
|
+
start: Position$1,
|
|
46
|
+
end: Position$1
|
|
47
|
+
});
|
|
48
|
+
const OrderedEnds = S.declare((value) => S.is(PositionEndsSchema)(value) && notReversed(positionOrder)(value), {
|
|
49
|
+
expected: "a location whose end is not before its start",
|
|
50
|
+
toCodecArbitrary: () => S.link()(PositionEndsSchema, {
|
|
51
|
+
decode: SchemaGetter$1.transform(inOrder(positionOrder)),
|
|
52
|
+
encode: SchemaGetter$1.transform((ends) => ends)
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
const Location$1 = PositionEndsSchema.pipe(S.decodeTo(OrderedEnds, SchemaTransformation$1.passthrough()));
|
|
56
|
+
const OpenEndsSchema = S.Struct({
|
|
57
|
+
start: Position$1,
|
|
58
|
+
end: S.optional(Position$1)
|
|
59
|
+
});
|
|
60
|
+
const closedEnds = (ends) => Option$1.map(Option$1.fromUndefinedOr(ends.end), (end) => ({
|
|
61
|
+
start: ends.start,
|
|
62
|
+
end
|
|
63
|
+
}));
|
|
64
|
+
const OrderedOpenEnds = S.declare((value) => S.is(OpenEndsSchema)(value) && Option$1.match(closedEnds(value), {
|
|
65
|
+
onNone: () => true,
|
|
66
|
+
onSome: notReversed(positionOrder)
|
|
67
|
+
}), {
|
|
68
|
+
expected: "a location whose end, when present, is not before its start",
|
|
69
|
+
toCodecArbitrary: () => S.link()(OpenEndsSchema, {
|
|
70
|
+
decode: SchemaGetter$1.transform((ends) => Option$1.getOrElse(Option$1.map(closedEnds(ends), inOrder(positionOrder)), () => ends)),
|
|
71
|
+
encode: SchemaGetter$1.transform((ends) => ends)
|
|
72
|
+
})
|
|
73
|
+
});
|
|
74
|
+
const OpenEndLocation$1 = OpenEndsSchema.pipe(S.decodeTo(OrderedOpenEnds, SchemaTransformation$1.passthrough()));
|
|
75
|
+
S.is(Line), S.is(Column), S.is(Location$1);
|
|
76
|
+
const MutantStatusSchema = S.Literals([
|
|
77
|
+
"Killed",
|
|
78
|
+
"Survived",
|
|
79
|
+
"NoCoverage",
|
|
80
|
+
"CompileError",
|
|
81
|
+
"RuntimeError",
|
|
82
|
+
"Timeout",
|
|
83
|
+
"Ignored",
|
|
84
|
+
"Pending"
|
|
85
|
+
]);
|
|
86
|
+
const SurvivorStatusSchema = S.Literals(["Survived", "NoCoverage"]);
|
|
87
|
+
const RememberedStatusSchema = S.Literals([
|
|
88
|
+
"Survived",
|
|
89
|
+
"Killed",
|
|
90
|
+
"Timeout",
|
|
91
|
+
"NoCoverage",
|
|
92
|
+
"Ignored"
|
|
93
|
+
]);
|
|
94
|
+
const EphemeralStatusSchema = S.Literals([
|
|
95
|
+
"CompileError",
|
|
96
|
+
"RuntimeError",
|
|
97
|
+
"Pending"
|
|
98
|
+
]);
|
|
99
|
+
const ActionableStatusSchema = S.Literals([
|
|
100
|
+
"Survived",
|
|
101
|
+
"NoCoverage",
|
|
102
|
+
"Timeout",
|
|
103
|
+
"RuntimeError"
|
|
104
|
+
]);
|
|
105
|
+
const MutantId = S.String.check(S.isPattern(/^[0-9a-f]{16}$/u, { expected: "a 16-character lowercase hexadecimal mutant id" })).pipe(S.brand("MutantId"));
|
|
106
|
+
const MutatorNameGrammar = S.String.check(S.isPattern(/^(?:[a-z][a-z0-9]*(?:-[a-z0-9]+)*\/)?[A-Z][A-Za-z0-9]*$/u, { expected: "a PascalCase mutator name, optionally prefixed by a lowercase kebab-case namespace and a slash" }));
|
|
107
|
+
const MutatorName = MutatorNameGrammar.pipe(S.brand("MutatorName"));
|
|
108
|
+
const CanonicalFileName = S.String.pipe(S.decodeTo(S.String.pipe(S.check(S.isPattern(/^[^\\]+$/u)), S.brand("CanonicalFileName")), {
|
|
109
|
+
decode: SchemaGetter$1.transform((fileName) => fileName.replace(/\\/g, "/")),
|
|
110
|
+
encode: SchemaGetter$1.transform((canonical) => canonical)
|
|
111
|
+
}));
|
|
112
|
+
/**
|
|
113
|
+
* A mutant's file location in the mutation-testing-report-schema contract:
|
|
114
|
+
* 1-based line and 1-based column, the same base the JSON report and the
|
|
115
|
+
* machine stream emit. Every producer on the instrument path (node spans,
|
|
116
|
+
* embedded-region shifts) targets this base; no downstream layer converts.
|
|
117
|
+
*/
|
|
118
|
+
const Mutant = S.TaggedStruct("Mutant", {
|
|
119
|
+
id: MutantId,
|
|
120
|
+
fileName: CanonicalFileName,
|
|
121
|
+
mutatorName: MutatorName,
|
|
122
|
+
replacement: S.String,
|
|
123
|
+
location: Location$1,
|
|
124
|
+
status: S.optional(MutantStatusSchema),
|
|
125
|
+
statusReason: S.optional(S.String),
|
|
126
|
+
coveredBy: S.String.pipe(S.Array, S.optional),
|
|
127
|
+
static: S.optional(S.Boolean),
|
|
128
|
+
testsCompleted: S.optional(S.Finite),
|
|
129
|
+
description: S.optional(S.String)
|
|
130
|
+
}).check(S.makeFilter((mutant) => mutant.statusReason === void 0 || mutant.status !== void 0, { message: "a mutant carries a status reason only together with a status" }));
|
|
131
|
+
const MutantFromUnknown = S.Unknown.pipe(S.decodeTo(Mutant));
|
|
132
|
+
const RunOptionsFields = {
|
|
133
|
+
timeout: S.Finite.pipe(S.check(S.isGreaterThanOrEqualTo(0))),
|
|
134
|
+
disableBail: S.Boolean
|
|
135
|
+
};
|
|
136
|
+
const MutantActivationSchema = S.Literals(["runtime", "static"]);
|
|
137
|
+
const HitCount = S.Int.pipe(S.check(S.isGreaterThanOrEqualTo(0)));
|
|
138
|
+
const MutantRunOptionsSchema = S.Struct({
|
|
139
|
+
...RunOptionsFields,
|
|
140
|
+
activeMutant: Mutant,
|
|
141
|
+
sandboxFileName: S.String,
|
|
142
|
+
mutantActivation: MutantActivationSchema,
|
|
143
|
+
reloadEnvironment: S.Boolean,
|
|
144
|
+
testFilter: S.String.pipe(S.Array, S.optionalKey),
|
|
145
|
+
priorKillerTestIds: S.String.pipe(S.Array, S.optionalKey),
|
|
146
|
+
hitLimit: S.optionalKey(HitCount)
|
|
147
|
+
});
|
|
148
|
+
const asMutantIdKeyed = (counts) => Object.fromEntries(Object.entries(counts).filter(([key]) => S.is(MutantId)(key)));
|
|
149
|
+
const asStringKeyed = (counts) => Object.fromEntries(Object.entries(counts));
|
|
150
|
+
const MutantIdKeyedHitCounts = S.Record(S.String, HitCount).pipe(S.check(S.makeFilter((counts) => {
|
|
151
|
+
const unknownKey = Object.keys(counts).find((key) => !S.is(MutantId)(key));
|
|
152
|
+
return unknownKey === void 0 ? void 0 : {
|
|
153
|
+
path: [unknownKey],
|
|
154
|
+
issue: `hit counts must be keyed by mutant ids, got '${unknownKey}'`
|
|
155
|
+
};
|
|
156
|
+
}, { arbitraryConstraint: { patterns: [{
|
|
157
|
+
source: "^[0-9a-f]{16}$",
|
|
158
|
+
flags: ""
|
|
159
|
+
}] } })), S.decodeTo(S.Record(MutantId, HitCount), {
|
|
160
|
+
decode: SchemaGetter$1.transform(asMutantIdKeyed),
|
|
161
|
+
encode: SchemaGetter$1.transform(asStringKeyed)
|
|
162
|
+
}));
|
|
163
|
+
const MutantCoverageSchema = S.Struct({
|
|
164
|
+
perTest: S.Record(S.String, MutantIdKeyedHitCounts),
|
|
165
|
+
static: MutantIdKeyedHitCounts
|
|
166
|
+
});
|
|
167
|
+
SurvivorStatusSchema.literals, RememberedStatusSchema.literals, EphemeralStatusSchema.literals, ActionableStatusSchema.literals;
|
|
168
|
+
const CheckerMutantWire = S.Struct({
|
|
169
|
+
id: MutantId,
|
|
170
|
+
fileName: CanonicalFileName,
|
|
171
|
+
mutatorName: MutatorName,
|
|
172
|
+
replacement: S.String,
|
|
173
|
+
location: Location$1
|
|
174
|
+
});
|
|
175
|
+
const CheckResultSchema = S.Union([S.Struct({ status: S.Literal("passed") }), S.Struct({
|
|
176
|
+
status: S.Literal("compileError"),
|
|
177
|
+
reason: S.String
|
|
178
|
+
})]).pipe(S.toTaggedUnion("status"));
|
|
179
|
+
const CheckStatus = S.Literals(CheckResultSchema.discriminants);
|
|
180
|
+
var CheckerFailed = class extends S.TaggedError()("CheckerFailed", {
|
|
181
|
+
cause: S.String,
|
|
182
|
+
checkerName: S.String,
|
|
183
|
+
mutantIds: S.Array(MutantId)
|
|
184
|
+
}) {
|
|
185
|
+
get message() {
|
|
186
|
+
const mutants = this.mutantIds.length === 0 ? "" : ` for mutants ${this.mutantIds.join(", ")}`;
|
|
187
|
+
return `Checker "${this.checkerName}" failed${mutants}: ${this.cause}`;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
var Checker = class extends Context.Service()("@systemfsoftware/stryker-js-plugin-interface/Checker.service/Checker") {};
|
|
191
|
+
var Checker_exports = /* @__PURE__ */ __exportAll({
|
|
192
|
+
CheckResultSchema: () => CheckResultSchema,
|
|
193
|
+
CheckStatus: () => CheckStatus,
|
|
194
|
+
Checker: () => Checker,
|
|
195
|
+
CheckerFailed: () => CheckerFailed,
|
|
196
|
+
CheckerMutantWire: () => CheckerMutantWire
|
|
197
|
+
});
|
|
198
|
+
S.TaggedError()("EvaluatorFailed", { cause: S.Unknown });
|
|
199
|
+
Context.Service()("@systemfsoftware/stryker-js-plugin-interface/Evaluator.service/Evaluator");
|
|
200
|
+
const RULE_IDS = [
|
|
201
|
+
"arid-logging",
|
|
202
|
+
"arid-telemetry",
|
|
203
|
+
"arid-time",
|
|
204
|
+
"arid-config-default",
|
|
205
|
+
"arid-memoization",
|
|
206
|
+
"redundant-relational",
|
|
207
|
+
"equivalent-to-original",
|
|
208
|
+
"duplicate-at-site",
|
|
209
|
+
"ignore-static",
|
|
210
|
+
"directive",
|
|
211
|
+
"excluded-mutator",
|
|
212
|
+
"ignorer"
|
|
213
|
+
];
|
|
214
|
+
const IgnoreRuleId = S.Literals(RULE_IDS);
|
|
215
|
+
const SEPARATOR = ": ";
|
|
216
|
+
const asLiteralPattern = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
217
|
+
const REASON_SOURCE = `^(?:${RULE_IDS.map(asLiteralPattern).join("|")})${SEPARATOR}[\\s\\S]*$`;
|
|
218
|
+
const IgnoreStatusReasonText = S.String.check(S.isPattern(new RegExp(REASON_SOURCE, "u"), { arbitraryConstraint: { patterns: [{
|
|
219
|
+
source: REASON_SOURCE,
|
|
220
|
+
flags: "u"
|
|
221
|
+
}] } }));
|
|
222
|
+
const ReasonPartsSchema = S.Struct({
|
|
223
|
+
ruleId: IgnoreRuleId,
|
|
224
|
+
detail: S.String
|
|
225
|
+
});
|
|
226
|
+
const reasonPartsOf = (text) => Option$1.map(Option$1.fromNullishOr(RULE_IDS.find((ruleId) => text.startsWith(`${ruleId}${SEPARATOR}`))), (ruleId) => ({
|
|
227
|
+
ruleId,
|
|
228
|
+
detail: text.slice(ruleId.length + 2)
|
|
229
|
+
}));
|
|
230
|
+
const malformedReason = (text) => new SchemaIssue.InvalidValue({ message: `expected "<rule-id>${SEPARATOR}<detail>"` }, text);
|
|
231
|
+
const partsOf$1 = SchemaGetter.transformEffect((text) => Effect$1.fromOption(reasonPartsOf(text), () => malformedReason(text)));
|
|
232
|
+
const textOf$1 = SchemaGetter.transform((parts) => `${parts.ruleId}${SEPARATOR}${parts.detail}`);
|
|
233
|
+
const IgnoreStatusReason = IgnoreStatusReasonText.pipe(S.decodeTo(ReasonPartsSchema, SchemaTransformation.makeTransformation({
|
|
234
|
+
decode: partsOf$1,
|
|
235
|
+
encode: textOf$1
|
|
236
|
+
})));
|
|
237
|
+
const Id = S.String.check(S.isPattern(/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u, { expected: "a lowercase kebab-case catalog entry id" })).pipe(S.brand("MutatorCatalogId"));
|
|
238
|
+
const Tier = S.Literals(["default", "optIn"]);
|
|
239
|
+
const Definition = S.NonEmptyString;
|
|
240
|
+
/**
|
|
241
|
+
* `after` lists the replacement texts in the order the mutator emits them, and
|
|
242
|
+
* is empty when the entry must not fire on `before`.
|
|
243
|
+
*/
|
|
244
|
+
const Example = S.Struct({
|
|
245
|
+
before: S.String,
|
|
246
|
+
after: S.Array(S.String)
|
|
247
|
+
});
|
|
248
|
+
const EntryShape = S.Struct({
|
|
249
|
+
id: Id,
|
|
250
|
+
name: MutatorName,
|
|
251
|
+
tier: Tier,
|
|
252
|
+
definition: Definition,
|
|
253
|
+
examples: S.Array(Example)
|
|
254
|
+
});
|
|
255
|
+
const carriesExamples = S.makeFilter((entry) => entry.examples.length === 0 ? `mutator catalog entry "${entry.id}" carries no examples` : void 0);
|
|
256
|
+
const carriesASnippet = S.makeFilter((entry) => {
|
|
257
|
+
return entry.examples.find((example) => example.before.length === 0) === void 0 ? void 0 : `mutator catalog entry "${entry.id}" carries an example with an empty before`;
|
|
258
|
+
});
|
|
259
|
+
const Entry = EntryShape.check(carriesExamples, carriesASnippet);
|
|
260
|
+
const Provider = S.String.check(S.isPattern(/^(?:stryker|[a-z][a-z0-9]*(?:-[a-z0-9]+)*)$/u, { expected: "the stock provider \"stryker\" or a lowercase kebab-case plugin namespace" })).pipe(S.brand("MutatorProvider"));
|
|
261
|
+
const CatalogShape = S.Struct({
|
|
262
|
+
provider: Provider,
|
|
263
|
+
entries: S.NonEmptyArray(Entry)
|
|
264
|
+
});
|
|
265
|
+
const duplicatedValue = (values) => values.find((value, index) => values.indexOf(value) !== index);
|
|
266
|
+
const namespaceOf = (name) => {
|
|
267
|
+
const slash = name.indexOf("/");
|
|
268
|
+
return slash === -1 ? void 0 : name.slice(0, slash);
|
|
269
|
+
};
|
|
270
|
+
const entryIdsAreUnique = S.makeFilter((catalog) => {
|
|
271
|
+
const duplicated = duplicatedValue(catalog.entries.map((entry) => entry.id));
|
|
272
|
+
return duplicated === void 0 ? void 0 : `mutator catalog entries share the id "${duplicated}"`;
|
|
273
|
+
});
|
|
274
|
+
const entryNamesAreUnique = S.makeFilter((catalog) => {
|
|
275
|
+
const duplicated = duplicatedValue(catalog.entries.map((entry) => entry.name));
|
|
276
|
+
return duplicated === void 0 ? void 0 : `mutator catalog entries share the mutator name "${duplicated}"`;
|
|
277
|
+
});
|
|
278
|
+
const ownedByProvider = (provider, name) => {
|
|
279
|
+
const namespace = namespaceOf(name);
|
|
280
|
+
return provider === "stryker" ? namespace === void 0 : namespace === provider;
|
|
281
|
+
};
|
|
282
|
+
const providerOwnsEveryName = S.makeFilter((catalog) => {
|
|
283
|
+
const unowned = catalog.entries.find((entry) => !ownedByProvider(catalog.provider, entry.name));
|
|
284
|
+
return unowned === void 0 ? void 0 : `provider "${catalog.provider}" does not own the mutator name "${unowned.name}"`;
|
|
285
|
+
});
|
|
286
|
+
const Catalog = CatalogShape.check(entryIdsAreUnique, entryNamesAreUnique, providerOwnsEveryName);
|
|
287
|
+
var Mutant_exports = /* @__PURE__ */ __exportAll({
|
|
288
|
+
ActionableStatusSchema: () => ActionableStatusSchema,
|
|
289
|
+
CanonicalFileName: () => CanonicalFileName,
|
|
290
|
+
Column: () => Column,
|
|
291
|
+
EphemeralStatusSchema: () => EphemeralStatusSchema,
|
|
292
|
+
HitCount: () => HitCount,
|
|
293
|
+
IgnoreRuleId: () => IgnoreRuleId,
|
|
294
|
+
IgnoreStatusReason: () => IgnoreStatusReason,
|
|
295
|
+
IgnoreStatusReasonText: () => IgnoreStatusReasonText,
|
|
296
|
+
Line: () => Line,
|
|
297
|
+
Location: () => Location$1,
|
|
298
|
+
Mutant: () => Mutant,
|
|
299
|
+
MutantActivationSchema: () => MutantActivationSchema,
|
|
300
|
+
MutantCoverageSchema: () => MutantCoverageSchema,
|
|
301
|
+
MutantFromUnknown: () => MutantFromUnknown,
|
|
302
|
+
MutantId: () => MutantId,
|
|
303
|
+
MutantRunOptionsSchema: () => MutantRunOptionsSchema,
|
|
304
|
+
MutantStatusSchema: () => MutantStatusSchema,
|
|
305
|
+
MutatorName: () => MutatorName,
|
|
306
|
+
OpenEndLocation: () => OpenEndLocation$1,
|
|
307
|
+
Position: () => Position$1,
|
|
308
|
+
RememberedStatusSchema: () => RememberedStatusSchema,
|
|
309
|
+
RunOptionsFields: () => RunOptionsFields,
|
|
310
|
+
SurvivorStatusSchema: () => SurvivorStatusSchema,
|
|
311
|
+
duplicatedValue: () => duplicatedValue,
|
|
312
|
+
inOrder: () => inOrder,
|
|
313
|
+
notReversed: () => notReversed
|
|
314
|
+
});
|
|
315
|
+
var MutatorCatalog_exports = /* @__PURE__ */ __exportAll({
|
|
316
|
+
Catalog: () => Catalog,
|
|
317
|
+
Definition: () => Definition,
|
|
318
|
+
Entry: () => Entry,
|
|
319
|
+
Example: () => Example,
|
|
320
|
+
Id: () => Id,
|
|
321
|
+
Name: () => MutatorName,
|
|
322
|
+
Provider: () => Provider,
|
|
323
|
+
Tier: () => Tier
|
|
324
|
+
});
|
|
325
|
+
const isMutator = (value) => typeof value === "function";
|
|
326
|
+
const implementsNothing = () => [];
|
|
327
|
+
const mutatorArbitrary = Schema.link()(Schema.Null, {
|
|
328
|
+
decode: SchemaGetter.transform(() => implementsNothing),
|
|
329
|
+
encode: SchemaGetter.transform(() => null)
|
|
330
|
+
});
|
|
331
|
+
const Implementation = Schema.declare(isMutator, { toCodecArbitrary: () => mutatorArbitrary });
|
|
332
|
+
const ProviderEntry = Schema.Struct({
|
|
333
|
+
id: Id,
|
|
334
|
+
name: MutatorName,
|
|
335
|
+
tier: Tier,
|
|
336
|
+
definition: Definition,
|
|
337
|
+
examples: Schema.NonEmptyArray(Example),
|
|
338
|
+
implementation: Implementation
|
|
339
|
+
});
|
|
340
|
+
const Contribution = Schema.Struct({
|
|
341
|
+
namespace: Provider,
|
|
342
|
+
entries: Schema.NonEmptyArray(ProviderEntry)
|
|
343
|
+
});
|
|
344
|
+
var MutatorProvider_exports = /* @__PURE__ */ __exportAll({
|
|
345
|
+
Contribution: () => Contribution,
|
|
346
|
+
Implementation: () => Implementation,
|
|
347
|
+
ProviderEntry: () => ProviderEntry
|
|
348
|
+
});
|
|
349
|
+
const statusBuckets = {
|
|
350
|
+
Detected: ["Killed", "Timeout"],
|
|
351
|
+
Undetected: ["Survived", "NoCoverage"],
|
|
352
|
+
Invalid: ["CompileError", "RuntimeError"],
|
|
353
|
+
Untested: ["Ignored", "Pending"]
|
|
354
|
+
};
|
|
355
|
+
const DetectedStatus = S.Literals(statusBuckets.Detected);
|
|
356
|
+
const UndetectedStatus = S.Literals(statusBuckets.Undetected);
|
|
357
|
+
const InvalidStatus = S.Literals(statusBuckets.Invalid);
|
|
358
|
+
const UntestedStatus = S.Literals(statusBuckets.Untested);
|
|
359
|
+
const NonNegativeInt = S.Int.pipe(S.check(S.isGreaterThanOrEqualTo(0)));
|
|
360
|
+
const NonNegativeFinite = S.Finite.pipe(S.check(S.isGreaterThanOrEqualTo(0)));
|
|
361
|
+
const Percentage = S.Finite.pipe(S.check(S.isBetween({
|
|
362
|
+
minimum: 0,
|
|
363
|
+
maximum: 100
|
|
364
|
+
})));
|
|
365
|
+
const MutationScore = S.TaggedUnion({
|
|
366
|
+
Scored: { percentage: Percentage },
|
|
367
|
+
Unscored: {}
|
|
368
|
+
});
|
|
369
|
+
const StaticClassSummarySchema = S.Struct({
|
|
370
|
+
count: NonNegativeInt,
|
|
371
|
+
costMs: NonNegativeFinite
|
|
372
|
+
});
|
|
373
|
+
const scorePercentageOf = (counts) => counts.counted > 0 ? Option$1.some(counts.detected / counts.counted * 100) : Option$1.none();
|
|
374
|
+
var Metrics = class extends S.Class("Metrics")({
|
|
375
|
+
pending: NonNegativeInt,
|
|
376
|
+
killed: NonNegativeInt,
|
|
377
|
+
timeout: NonNegativeInt,
|
|
378
|
+
survived: NonNegativeInt,
|
|
379
|
+
noCoverage: NonNegativeInt,
|
|
380
|
+
runtimeErrors: NonNegativeInt,
|
|
381
|
+
compileErrors: NonNegativeInt,
|
|
382
|
+
ignored: NonNegativeInt
|
|
383
|
+
}) {
|
|
384
|
+
get totalDetected() {
|
|
385
|
+
return this.timeout + this.killed;
|
|
386
|
+
}
|
|
387
|
+
get totalUndetected() {
|
|
388
|
+
return this.survived + this.noCoverage;
|
|
389
|
+
}
|
|
390
|
+
get totalCovered() {
|
|
391
|
+
return this.totalDetected + this.survived;
|
|
392
|
+
}
|
|
393
|
+
get totalValid() {
|
|
394
|
+
return this.totalUndetected + this.totalDetected;
|
|
395
|
+
}
|
|
396
|
+
get totalInvalid() {
|
|
397
|
+
return this.runtimeErrors + this.compileErrors;
|
|
398
|
+
}
|
|
399
|
+
get totalMutants() {
|
|
400
|
+
return this.totalValid + this.totalInvalid + this.ignored + this.pending;
|
|
401
|
+
}
|
|
402
|
+
get mutationScore() {
|
|
403
|
+
return Option$1.match(scorePercentageOf({
|
|
404
|
+
detected: this.totalDetected,
|
|
405
|
+
counted: this.totalValid
|
|
406
|
+
}), {
|
|
407
|
+
onNone: () => MutationScore.cases.Unscored.make({}),
|
|
408
|
+
onSome: (percentage) => MutationScore.cases.Scored.make({ percentage })
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
get mutationScoreBasedOnCoveredCode() {
|
|
412
|
+
return Option$1.match(scorePercentageOf({
|
|
413
|
+
detected: this.totalDetected,
|
|
414
|
+
counted: this.totalCovered
|
|
415
|
+
}), {
|
|
416
|
+
onNone: () => MutationScore.cases.Unscored.make({}),
|
|
417
|
+
onSome: (percentage) => MutationScore.cases.Scored.make({ percentage })
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
const MetricsSchema = Metrics;
|
|
422
|
+
const MetricsResultSchema = S.Struct({
|
|
423
|
+
name: S.String,
|
|
424
|
+
metrics: Metrics,
|
|
425
|
+
childResults: S.Array(S.suspend(() => MetricsResultSchema))
|
|
426
|
+
}).annotate({ identifier: "MetricsResult" });
|
|
427
|
+
const StrykerCoverageAnalysis = S.Literal("perTest");
|
|
428
|
+
const StrykerFileLogLevel = S.Literal("off");
|
|
429
|
+
const StrykerLogLevel = S.Literal("info");
|
|
430
|
+
const StrykerTempDirName = S.Literal(".stryker-tmp");
|
|
431
|
+
/**
|
|
432
|
+
* The Stryker option set, declared as ONE Effect Schema.
|
|
433
|
+
*
|
|
434
|
+
* Replaces the vendored `schema/stryker-core.json` codegen chain
|
|
435
|
+
* (`tasks/generate-stryker-core.mjs` → `src-generated/stryker-core.ts`): every
|
|
436
|
+
* option name, type, optionality and default is preserved, and
|
|
437
|
+
* the JSON Schema document is **derived** from
|
|
438
|
+
* `StrykerOptionsSchema` (no file read).
|
|
439
|
+
*
|
|
440
|
+
* Layering mirrors the original document:
|
|
441
|
+
* - objects without `additionalProperties: false` there (the option set
|
|
442
|
+
* itself, `commandRunner`, `clearTextReporter`, `warnings`) are open here —
|
|
443
|
+
* `S.StructWithRest` with a `Record<string, unknown>` index keeps arbitrary
|
|
444
|
+
* plugin-proposed keys and makes the decoded type carry
|
|
445
|
+
* `[k: string]: unknown`;
|
|
446
|
+
* - objects with `additionalProperties: false` (`htmlReporter`, `jsonReporter`,
|
|
447
|
+
* `thresholds`, `mutator`) are closed here.
|
|
448
|
+
*
|
|
449
|
+
* `dashboard` and `eventReporter` are absent: the reporters they configured were
|
|
450
|
+
* removed, and the removed-option check rejects both names. Declaring them here
|
|
451
|
+
* with defaults meant the default option set carried two options the very next
|
|
452
|
+
* validation step refused - invisible only while the defaults were filled by a
|
|
453
|
+
* separate engine that happened not to inject them.
|
|
454
|
+
*/
|
|
455
|
+
/** Open object: fixed fields plus an index signature accepting arbitrary plugin keys. */
|
|
456
|
+
const openStruct = (fields) => S.StructWithRest(S.Struct(fields), [S.Record(S.String, S.Unknown)]);
|
|
457
|
+
/**
|
|
458
|
+
* Field that decodes to a value but defaults when the key is absent.
|
|
459
|
+
*
|
|
460
|
+
* The default is typed by the schema's ENCODED side, which is what
|
|
461
|
+
* `withDecodingDefaultKey` consumes: a whole-object option can therefore default
|
|
462
|
+
* to `{}` exactly when every field inside it carries its own default, and
|
|
463
|
+
* the compiler decides that rather than the author asserting it.
|
|
464
|
+
*
|
|
465
|
+
* The annotation is applied to the schema BEFORE the default transform wraps it.
|
|
466
|
+
* Annotating the wrapper instead leaves `default` off the derived JSON Schema
|
|
467
|
+
* document, so a consumer filling defaults from that document (ajv
|
|
468
|
+
* `useDefaults`) silently injects nothing.
|
|
469
|
+
*/
|
|
470
|
+
const defaulted = (schema, defaultValue) => {
|
|
471
|
+
const annotated = schema.annotate({ default: defaultValue });
|
|
472
|
+
return S.withDecodingDefaultKey(Effect.succeed(defaultValue))(annotated);
|
|
473
|
+
};
|
|
474
|
+
const LogLevel = S.Literals([
|
|
475
|
+
"off",
|
|
476
|
+
"fatal",
|
|
477
|
+
"error",
|
|
478
|
+
"warn",
|
|
479
|
+
"info",
|
|
480
|
+
"debug",
|
|
481
|
+
"trace"
|
|
482
|
+
]);
|
|
483
|
+
const CoverageAnalysisMode = S.Literals([
|
|
484
|
+
"off",
|
|
485
|
+
"all",
|
|
486
|
+
"perTest"
|
|
487
|
+
]);
|
|
488
|
+
const ReportType = S.Literals(["full", "mutationScore"]);
|
|
489
|
+
const PackageManager = S.Literals([
|
|
490
|
+
"npm",
|
|
491
|
+
"yarn",
|
|
492
|
+
"pnpm"
|
|
493
|
+
]);
|
|
494
|
+
const MutantSetPolicy = S.Literals(["default", "full"]);
|
|
495
|
+
const CommandRunnerOptionsSchema = openStruct({ command: defaulted(S.String, "npm test") });
|
|
496
|
+
const ClearTextReporterOptions = openStruct({
|
|
497
|
+
allowColor: defaulted(S.Boolean, true),
|
|
498
|
+
allowEmojis: defaulted(S.Boolean, false),
|
|
499
|
+
logTests: defaulted(S.Boolean, true),
|
|
500
|
+
maxTestsToLog: defaulted(NonNegativeInt, 3),
|
|
501
|
+
reportTests: defaulted(S.Boolean, true),
|
|
502
|
+
reportMutants: defaulted(S.Boolean, true),
|
|
503
|
+
reportScoreTable: defaulted(S.Boolean, true),
|
|
504
|
+
skipFull: defaulted(S.Boolean, false)
|
|
505
|
+
});
|
|
506
|
+
const HtmlReporterOptions = S.Struct({ fileName: defaulted(S.String, "reports/mutation/mutation.html") });
|
|
507
|
+
const JsonReporterOptions = S.Struct({ fileName: defaulted(S.String, "reports/mutation/mutation.json") });
|
|
508
|
+
const MutationScoreThresholdsValuesSchema = S.Struct({
|
|
509
|
+
high: defaulted(Percentage, 80),
|
|
510
|
+
low: defaulted(Percentage, 60),
|
|
511
|
+
break: defaulted(S.NullOr(Percentage), null)
|
|
512
|
+
});
|
|
513
|
+
const OrderedThresholdsValuesSchema = S.Struct({
|
|
514
|
+
high: Percentage,
|
|
515
|
+
low: Percentage,
|
|
516
|
+
break: S.NullOr(Percentage)
|
|
517
|
+
});
|
|
518
|
+
const isOrderedThresholds = (value) => S.is(OrderedThresholdsValuesSchema)(value) && value.low <= value.high;
|
|
519
|
+
const OrderedThresholds = S.declare(isOrderedThresholds, {
|
|
520
|
+
message: "a mutation score threshold pair has low at or below high",
|
|
521
|
+
toCodecArbitrary: () => S.link()(OrderedThresholdsValuesSchema, {
|
|
522
|
+
decode: SchemaGetter.transform(({ break: breaking, high, low }) => ({
|
|
523
|
+
break: breaking,
|
|
524
|
+
high: Math.max(high, low),
|
|
525
|
+
low: Math.min(high, low)
|
|
526
|
+
})),
|
|
527
|
+
encode: SchemaGetter.transform((thresholds) => thresholds)
|
|
528
|
+
})
|
|
529
|
+
});
|
|
530
|
+
const MutationScoreThresholdsSchema = MutationScoreThresholdsValuesSchema.pipe(S.decodeTo(OrderedThresholds, SchemaTransformation.passthrough()));
|
|
531
|
+
const MutatorDescriptor = S.Struct({
|
|
532
|
+
excludedMutations: defaulted(S.Array(MutatorNameGrammar), []),
|
|
533
|
+
optInMutations: defaulted(S.Array(MutatorNameGrammar), []),
|
|
534
|
+
mutantSetPolicy: defaulted(MutantSetPolicy, "default")
|
|
535
|
+
});
|
|
536
|
+
const SurfacingOptions = S.Struct({
|
|
537
|
+
perLine: defaulted(NonNegativeInt, 1),
|
|
538
|
+
perFile: defaulted(NonNegativeInt, 7)
|
|
539
|
+
});
|
|
540
|
+
const WarningOptions = openStruct({
|
|
541
|
+
unknownOptions: defaulted(S.Boolean, true),
|
|
542
|
+
preprocessorErrors: defaulted(S.Boolean, true),
|
|
543
|
+
unserializableOptions: defaulted(S.Boolean, true),
|
|
544
|
+
slow: defaulted(S.Boolean, true)
|
|
545
|
+
});
|
|
546
|
+
const ConcurrencyCount = S.Int.pipe(S.check(S.isGreaterThanOrEqualTo(1)));
|
|
547
|
+
const ConcurrencyPercent = S.String.pipe(S.check(S.isPattern(/^(100|[1-9]?[0-9])%$/u)));
|
|
548
|
+
const pluginSpecifierArbitrary = S.link()(S.Literals([
|
|
549
|
+
"file:///project/node_modules/@systemfsoftware/stryker-js-angular/index.mjs",
|
|
550
|
+
"file:///home/user/project/plugins/custom-plugin.mjs",
|
|
551
|
+
"effect",
|
|
552
|
+
"@systemfsoftware/stryker-js-angular",
|
|
553
|
+
"@systemfsoftware/stryker-js-svelte",
|
|
554
|
+
"my-plugin",
|
|
555
|
+
"@scope/my-plugin/sub/entry",
|
|
556
|
+
"my-plugin/sub"
|
|
557
|
+
]), {
|
|
558
|
+
decode: SchemaGetter.transform((sample) => sample),
|
|
559
|
+
encode: SchemaGetter.transform((sample) => sample)
|
|
560
|
+
});
|
|
561
|
+
const PluginFileUrl = S.declare((value) => typeof value === "string" && /^(?:file:\/\/\/\S+|(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(?:\/(?!\.\.?\/)[^/\s]+)*)$/.test(value), { toCodecArbitrary: () => pluginSpecifierArbitrary });
|
|
562
|
+
const TestRunnerCustomConfigSchema = S.Struct({
|
|
563
|
+
plugin: PluginFileUrl,
|
|
564
|
+
nodeArgs: S.String.pipe(S.Array, S.optionalKey),
|
|
565
|
+
options: S.optionalKey(S.Record(S.String, S.Unknown))
|
|
566
|
+
});
|
|
567
|
+
const TestRunnerConfigSchema = S.Union([S.String, TestRunnerCustomConfigSchema]);
|
|
568
|
+
const AnyNonStringTestRunner = S.declare((value) => typeof value !== "string", { message: "expected a custom test runner config" });
|
|
569
|
+
const isCustomTestRunner = S.is(AnyNonStringTestRunner);
|
|
570
|
+
const CheckerCustomConfigSchema = S.Struct({
|
|
571
|
+
plugin: PluginFileUrl,
|
|
572
|
+
nodeArgs: S.String.pipe(S.Array, S.optionalKey),
|
|
573
|
+
options: S.optionalKey(S.Record(S.String, S.Unknown))
|
|
574
|
+
});
|
|
575
|
+
const CheckerEntryConfigSchema = CheckerCustomConfigSchema;
|
|
576
|
+
const StrykerOptionsSchema = S.StructWithRest(S.Struct({
|
|
577
|
+
allowConsoleColors: defaulted(S.Boolean, true),
|
|
578
|
+
buildCommand: S.optionalKey(S.String),
|
|
579
|
+
checkers: defaulted(S.Array(CheckerEntryConfigSchema), []),
|
|
580
|
+
checkerNodeArgs: defaulted(S.Array(S.String), []),
|
|
581
|
+
concurrency: S.optionalKey(S.Union([ConcurrencyCount, ConcurrencyPercent])),
|
|
582
|
+
commandRunner: defaulted(CommandRunnerOptionsSchema, { command: "npm test" }),
|
|
583
|
+
coverageAnalysis: defaulted(CoverageAnalysisMode, StrykerCoverageAnalysis.literal),
|
|
584
|
+
clearTextReporter: defaulted(ClearTextReporterOptions, {
|
|
585
|
+
allowColor: true,
|
|
586
|
+
allowEmojis: false,
|
|
587
|
+
logTests: true,
|
|
588
|
+
maxTestsToLog: 3,
|
|
589
|
+
reportTests: true,
|
|
590
|
+
reportMutants: true,
|
|
591
|
+
reportScoreTable: true,
|
|
592
|
+
skipFull: false
|
|
593
|
+
}),
|
|
594
|
+
dryRunOnly: defaulted(S.Boolean, false),
|
|
595
|
+
ignorePatterns: defaulted(S.Array(S.String), []),
|
|
596
|
+
ignoreStatic: defaulted(S.Boolean, false),
|
|
597
|
+
incremental: defaulted(S.Boolean, false),
|
|
598
|
+
incrementalFile: defaulted(S.String, "reports/stryker-incremental.json"),
|
|
599
|
+
incrementalSources: defaulted(S.Array(S.String), []),
|
|
600
|
+
progressStreamFile: defaulted(S.String, "reports/mutation-stream.jsonl"),
|
|
601
|
+
since: S.optionalKey(S.String),
|
|
602
|
+
force: defaulted(S.Boolean, false),
|
|
603
|
+
fileLogLevel: defaulted(LogLevel, StrykerFileLogLevel.literal),
|
|
604
|
+
inPlace: defaulted(S.Boolean, false),
|
|
605
|
+
logLevel: defaulted(LogLevel, StrykerLogLevel.literal),
|
|
606
|
+
maxConcurrentTestRunners: defaulted(S.Int.pipe(S.check(S.isGreaterThanOrEqualTo(1))), Number.MAX_SAFE_INTEGER),
|
|
607
|
+
maxTestRunnerReuse: defaulted(NonNegativeInt, 0),
|
|
608
|
+
mutate: defaulted(S.Array(S.String), ["{src,lib}/**/!(*.+(s|S)pec|*.+(t|T)est).+(cjs|mjs|js|ts|mts|cts|jsx|tsx|html|vue|svelte)", "!{src,lib}/**/__tests__/**/*.+(cjs|mjs|js|ts|mts|cts|jsx|tsx|html|vue|svelte)"]),
|
|
609
|
+
mutator: defaulted(MutatorDescriptor, {
|
|
610
|
+
excludedMutations: [],
|
|
611
|
+
optInMutations: [],
|
|
612
|
+
mutantSetPolicy: "default"
|
|
613
|
+
}),
|
|
614
|
+
surfacing: defaulted(SurfacingOptions, {
|
|
615
|
+
perLine: 1,
|
|
616
|
+
perFile: 7
|
|
617
|
+
}),
|
|
618
|
+
packageManager: S.optionalKey(PackageManager),
|
|
619
|
+
plugins: defaulted(S.Array(PluginFileUrl), []),
|
|
620
|
+
appendPlugins: defaulted(S.Array(PluginFileUrl), []),
|
|
621
|
+
reporters: defaulted(S.Array(S.String), [
|
|
622
|
+
"clear-text",
|
|
623
|
+
"progress",
|
|
624
|
+
"html"
|
|
625
|
+
]),
|
|
626
|
+
htmlReporter: defaulted(HtmlReporterOptions, { fileName: "reports/mutation/mutation.html" }),
|
|
627
|
+
jsonReporter: defaulted(JsonReporterOptions, { fileName: "reports/mutation/mutation.json" }),
|
|
628
|
+
disableTypeChecks: defaulted(S.Union([S.Boolean, S.String]), true),
|
|
629
|
+
symlinkNodeModules: defaulted(S.Boolean, true),
|
|
630
|
+
tempDirName: defaulted(S.String, StrykerTempDirName.literal),
|
|
631
|
+
cleanTempDir: defaulted(S.Literals([
|
|
632
|
+
"always",
|
|
633
|
+
false,
|
|
634
|
+
true
|
|
635
|
+
]), true),
|
|
636
|
+
testRunner: defaulted(TestRunnerConfigSchema, "vm"),
|
|
637
|
+
testRunnerNodeArgs: defaulted(S.Array(S.String), []),
|
|
638
|
+
thresholds: defaulted(MutationScoreThresholdsSchema, {
|
|
639
|
+
high: 80,
|
|
640
|
+
low: 60,
|
|
641
|
+
break: null
|
|
642
|
+
}),
|
|
643
|
+
timeoutFactor: defaulted(NonNegativeFinite, 1.5),
|
|
644
|
+
timeoutMS: defaulted(NonNegativeInt, 5e3),
|
|
645
|
+
dryRunTimeoutMinutes: defaulted(NonNegativeFinite, 5),
|
|
646
|
+
tsconfigFile: defaulted(S.String, "tsconfig.json"),
|
|
647
|
+
warnings: defaulted(S.Union([S.Boolean, WarningOptions]), true),
|
|
648
|
+
disableBail: defaulted(S.Boolean, false),
|
|
649
|
+
allowEmpty: defaulted(S.Boolean, false),
|
|
650
|
+
ignorers: defaulted(S.Array(PluginFileUrl), []),
|
|
651
|
+
testFiles: defaulted(S.Array(S.String), [])
|
|
652
|
+
}), [S.Record(S.String, S.Unknown)]);
|
|
653
|
+
var Options_exports = /* @__PURE__ */ __exportAll({
|
|
654
|
+
CheckerCustomConfigSchema: () => CheckerCustomConfigSchema,
|
|
655
|
+
CheckerEntryConfigSchema: () => CheckerEntryConfigSchema,
|
|
656
|
+
CommandRunnerOptionsSchema: () => CommandRunnerOptionsSchema,
|
|
657
|
+
CoverageAnalysisMode: () => CoverageAnalysisMode,
|
|
658
|
+
LogLevel: () => LogLevel,
|
|
659
|
+
MutantSetPolicy: () => MutantSetPolicy,
|
|
660
|
+
MutationScoreThresholdsSchema: () => MutationScoreThresholdsSchema,
|
|
661
|
+
PackageManager: () => PackageManager,
|
|
662
|
+
PluginFileUrl: () => PluginFileUrl,
|
|
663
|
+
ReportType: () => ReportType,
|
|
664
|
+
StrykerCoverageAnalysis: () => StrykerCoverageAnalysis,
|
|
665
|
+
StrykerFileLogLevel: () => StrykerFileLogLevel,
|
|
666
|
+
StrykerLogLevel: () => StrykerLogLevel,
|
|
667
|
+
StrykerOptionsSchema: () => StrykerOptionsSchema,
|
|
668
|
+
StrykerTempDirName: () => StrykerTempDirName,
|
|
669
|
+
TestRunnerConfigSchema: () => TestRunnerConfigSchema,
|
|
670
|
+
TestRunnerCustomConfigSchema: () => TestRunnerCustomConfigSchema,
|
|
671
|
+
isCustomTestRunner: () => isCustomTestRunner
|
|
672
|
+
});
|
|
673
|
+
const ExitCode = S.Int.pipe(S.check(S.isBetween({
|
|
674
|
+
minimum: 0,
|
|
675
|
+
maximum: 255
|
|
676
|
+
})));
|
|
677
|
+
const ExitClass = S.Literals([
|
|
678
|
+
"VerdictFail",
|
|
679
|
+
"ConfigError",
|
|
680
|
+
"RuntimeError",
|
|
681
|
+
"InternalError"
|
|
682
|
+
]);
|
|
683
|
+
const BASELINE_EXIT_CODES = {
|
|
684
|
+
VerdictFail: 1,
|
|
685
|
+
ConfigError: 2,
|
|
686
|
+
RuntimeError: 3,
|
|
687
|
+
InternalError: 4
|
|
688
|
+
};
|
|
689
|
+
const CLASS_BY_BASELINE_CODE = {
|
|
690
|
+
1: "VerdictFail",
|
|
691
|
+
2: "ConfigError",
|
|
692
|
+
3: "RuntimeError",
|
|
693
|
+
4: "InternalError"
|
|
694
|
+
};
|
|
695
|
+
const codeOfClass = (exitClass) => BASELINE_EXIT_CODES[exitClass];
|
|
696
|
+
const classOfCode = (code) => CLASS_BY_BASELINE_CODE[code];
|
|
697
|
+
const BaselineExitCode = S.Literals([
|
|
698
|
+
1,
|
|
699
|
+
2,
|
|
700
|
+
3,
|
|
701
|
+
4
|
|
702
|
+
]);
|
|
703
|
+
const ExitCodeFromClass = S.decodeTo(BaselineExitCode, SchemaTransformation.transform({
|
|
704
|
+
decode: codeOfClass,
|
|
705
|
+
encode: classOfCode
|
|
706
|
+
}))(ExitClass);
|
|
707
|
+
const Position = S.StructWithRest(S.Struct({
|
|
708
|
+
"line": S.Finite.annotate({ "examples": [4] }).check(S.isInt().annotate({ "expected": "an integer" })).check(S.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" })),
|
|
709
|
+
"column": S.Finite.annotate({ "examples": [3] }).check(S.isInt().annotate({ "expected": "an integer" })).check(S.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }))
|
|
710
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
711
|
+
"title": "Position",
|
|
712
|
+
"description": "Position of a mutation. Both line and column start at one.",
|
|
713
|
+
"identifier": "position"
|
|
714
|
+
});
|
|
715
|
+
const Thresholds = S.StructWithRest(S.Struct({
|
|
716
|
+
"high": S.Finite.annotate({
|
|
717
|
+
"description": "Higher bound threshold.",
|
|
718
|
+
"examples": [80]
|
|
719
|
+
}).check(S.isInt().annotate({ "expected": "an integer" })).check(S.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })).check(S.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })),
|
|
720
|
+
"low": S.Finite.annotate({
|
|
721
|
+
"description": "Lower bound threshold.",
|
|
722
|
+
"examples": [60]
|
|
723
|
+
}).check(S.isInt().annotate({ "expected": "an integer" })).check(S.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })).check(S.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })),
|
|
724
|
+
"break": S.optionalKey(S.Union([S.Finite.check(S.isFinite().annotate({ "expected": "a finite number" })).check(S.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })).check(S.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })), S.Null]).annotate({ "description": "The mutation score below which the run breaks. Null disables the break." }))
|
|
725
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
726
|
+
"title": "Thresholds",
|
|
727
|
+
"description": "Thresholds for the status of the reported application.",
|
|
728
|
+
"identifier": "thresholds"
|
|
729
|
+
});
|
|
730
|
+
const PerformanceStatistics = S.StructWithRest(S.Struct({
|
|
731
|
+
"setup": S.Finite.annotate({ "description": "Time it took to run the setup phase in milliseconds." }).check(S.isFinite().annotate({ "expected": "a finite number" })),
|
|
732
|
+
"initialRun": S.Finite.annotate({ "description": "Time it took to run the initial test phase (dry-run) in milliseconds." }).check(S.isFinite().annotate({ "expected": "a finite number" })),
|
|
733
|
+
"mutation": S.Finite.annotate({ "description": "Time it took to run the mutation test phase in milliseconds." }).check(S.isFinite().annotate({ "expected": "a finite number" }))
|
|
734
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
735
|
+
"title": "PerformanceStatistics",
|
|
736
|
+
"description": "The performance statistics per phase. Total time should be roughly equal to the sum of all these.",
|
|
737
|
+
"identifier": "performanceStatistics"
|
|
738
|
+
});
|
|
739
|
+
const BrandingInformation = S.StructWithRest(S.Struct({
|
|
740
|
+
"homepageUrl": S.String.annotate({
|
|
741
|
+
"description": "URL to the homepage of the framework.",
|
|
742
|
+
"format": "uri"
|
|
743
|
+
}),
|
|
744
|
+
"imageUrl": S.optionalKey(S.String.annotate({ "description": "URL to an image for the framework, can be a data URL." }))
|
|
745
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
746
|
+
"title": "BrandingInformation",
|
|
747
|
+
"description": "Extra branding information about the framework used.",
|
|
748
|
+
"identifier": "brandingInformation"
|
|
749
|
+
});
|
|
750
|
+
const Dependencies = S.Record(S.String, S.String).annotate({
|
|
751
|
+
"title": "Dependencies",
|
|
752
|
+
"description": "Dependencies used by the framework. Key-value pair of dependencies and their versions.",
|
|
753
|
+
"identifier": "dependencies"
|
|
754
|
+
});
|
|
755
|
+
const OSInformation = S.StructWithRest(S.Struct({
|
|
756
|
+
"description": S.optionalKey(S.String.annotate({
|
|
757
|
+
"description": "Human-readable description of the OS",
|
|
758
|
+
"examples": [
|
|
759
|
+
"Windows 10 Pro",
|
|
760
|
+
"Debian Buster",
|
|
761
|
+
"Ubuntu 20.04.1 LTS"
|
|
762
|
+
]
|
|
763
|
+
})),
|
|
764
|
+
"platform": S.String.annotate({
|
|
765
|
+
"description": "Platform identifier",
|
|
766
|
+
"examples": ["linux", "win32"]
|
|
767
|
+
}),
|
|
768
|
+
"version": S.optionalKey(S.String.annotate({
|
|
769
|
+
"description": "Version of the OS or distribution",
|
|
770
|
+
"examples": ["10.0.19041"]
|
|
771
|
+
}))
|
|
772
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
773
|
+
"title": "OSInformation",
|
|
774
|
+
"identifier": "oSInformation"
|
|
775
|
+
});
|
|
776
|
+
const CpuInformation = S.StructWithRest(S.Struct({
|
|
777
|
+
"baseClock": S.optionalKey(S.Finite.annotate({ "description": "Clock speed in MHz" }).check(S.isFinite().annotate({ "expected": "a finite number" }))),
|
|
778
|
+
"logicalCores": S.Finite.check(S.isFinite().annotate({ "expected": "a finite number" })),
|
|
779
|
+
"model": S.optionalKey(S.String.annotate({ "examples": ["Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz"] }))
|
|
780
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
781
|
+
"title": "CpuInformation",
|
|
782
|
+
"identifier": "cpuInformation"
|
|
783
|
+
});
|
|
784
|
+
const RamInformation = S.StructWithRest(S.Struct({ "total": S.Finite.annotate({ "description": "The total RAM of the system that performed mutation testing in MB." }).check(S.isFinite().annotate({ "expected": "a finite number" })) }), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
785
|
+
"title": "RamInformation",
|
|
786
|
+
"identifier": "ramInformation"
|
|
787
|
+
});
|
|
788
|
+
const Location = S.StructWithRest(S.Struct({
|
|
789
|
+
"start": Position,
|
|
790
|
+
"end": Position
|
|
791
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
792
|
+
"title": "Location",
|
|
793
|
+
"description": "A location with start and end. Start is inclusive, end is exclusive.",
|
|
794
|
+
"identifier": "location"
|
|
795
|
+
});
|
|
796
|
+
const OpenEndLocation = S.StructWithRest(S.Struct({
|
|
797
|
+
"start": Position,
|
|
798
|
+
"end": S.optionalKey(Position)
|
|
799
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
800
|
+
"title": "OpenEndLocation",
|
|
801
|
+
"description": "A location where \"end\" is not required. Start is inclusive, end is exclusive.",
|
|
802
|
+
"identifier": "openEndLocation"
|
|
803
|
+
});
|
|
804
|
+
const FrameworkInformation = S.StructWithRest(S.Struct({
|
|
805
|
+
"name": S.String.annotate({
|
|
806
|
+
"description": "Name of the framework used.",
|
|
807
|
+
"examples": [
|
|
808
|
+
"Stryker",
|
|
809
|
+
"Stryker4s",
|
|
810
|
+
"Stryker.NET",
|
|
811
|
+
"Infection PHP",
|
|
812
|
+
"Pitest"
|
|
813
|
+
]
|
|
814
|
+
}),
|
|
815
|
+
"version": S.optionalKey(S.String.annotate({ "description": "Version of the framework." })),
|
|
816
|
+
"branding": S.optionalKey(BrandingInformation),
|
|
817
|
+
"dependencies": S.optionalKey(Dependencies)
|
|
818
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
819
|
+
"title": "FrameworkInformation",
|
|
820
|
+
"description": "Extra information about the framework used",
|
|
821
|
+
"identifier": "frameworkInformation"
|
|
822
|
+
});
|
|
823
|
+
const SystemInformation = S.StructWithRest(S.Struct({
|
|
824
|
+
"ci": S.Boolean.annotate({ "description": "Did mutation testing run in a Continuous Integration environment (pipeline)? Note that there is no way of knowing this for sure. It's done on a best-effort basis." }),
|
|
825
|
+
"os": S.optionalKey(OSInformation),
|
|
826
|
+
"cpu": S.optionalKey(CpuInformation),
|
|
827
|
+
"ram": S.optionalKey(RamInformation)
|
|
828
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
829
|
+
"title": "SystemInformation",
|
|
830
|
+
"description": "Information about the system that performed mutation testing.",
|
|
831
|
+
"identifier": "systemInformation"
|
|
832
|
+
});
|
|
833
|
+
const MutantResult = S.StructWithRest(S.Struct({
|
|
834
|
+
"coveredBy": S.optionalKey(S.Array(S.String).annotate({ "description": "The test ids that covered this mutant. If a mutation testing framework doesn't measure this information, it can simply be left out." })),
|
|
835
|
+
"description": S.optionalKey(S.String.annotate({
|
|
836
|
+
"description": "Description of the applied mutation.",
|
|
837
|
+
"examples": ["removed call to java/io/Writer::write"]
|
|
838
|
+
})),
|
|
839
|
+
"duration": S.optionalKey(S.Finite.annotate({ "description": "The net time it took to test this mutant in milliseconds. This is the time measurement without overhead from the mutation testing framework." }).check(S.isFinite().annotate({ "expected": "a finite number" }))),
|
|
840
|
+
"id": S.String.annotate({
|
|
841
|
+
"description": "Unique id, can be used to correlate this mutant across reports.",
|
|
842
|
+
"examples": ["321321"]
|
|
843
|
+
}),
|
|
844
|
+
"killedBy": S.optionalKey(S.Array(S.String).annotate({ "description": "The test ids that killed this mutant. It is a best practice to \"bail\" on first failing test, in which case you can fill this array with that one test." })),
|
|
845
|
+
"location": Location,
|
|
846
|
+
"mutatorName": S.String.annotate({
|
|
847
|
+
"description": "Category of the mutation.",
|
|
848
|
+
"examples": [
|
|
849
|
+
"ConditionalExpression",
|
|
850
|
+
"EqualityOperator",
|
|
851
|
+
"LogicalOperator"
|
|
852
|
+
]
|
|
853
|
+
}),
|
|
854
|
+
"replacement": S.optionalKey(S.String.annotate({
|
|
855
|
+
"description": "Actual mutation that has been applied.",
|
|
856
|
+
"examples": [
|
|
857
|
+
"-",
|
|
858
|
+
"+",
|
|
859
|
+
"&&",
|
|
860
|
+
"||"
|
|
861
|
+
]
|
|
862
|
+
})),
|
|
863
|
+
"static": S.optionalKey(S.Boolean.annotate({ "description": "A static mutant means that it was loaded once at during initialization, this makes it slow or even impossible to test, depending on the mutation testing framework." })),
|
|
864
|
+
"status": MutantStatusSchema.annotate({
|
|
865
|
+
"title": "MutantStatus",
|
|
866
|
+
"description": "Result of the mutation."
|
|
867
|
+
}),
|
|
868
|
+
"statusReason": S.optionalKey(S.String.annotate({ "description": "The reason that this mutant has this status. In the case of a killed mutant, this should be filled with the failure message(s) of the failing tests. In case of an error mutant, this should be filled with the error message." })),
|
|
869
|
+
"testsCompleted": S.optionalKey(S.Finite.annotate({ "description": "The number of tests actually completed in order to test this mutant. Can differ from \"coveredBy\" because of bailing a mutant test run after first failing test." }).check(S.isFinite().annotate({ "expected": "a finite number" })))
|
|
870
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
871
|
+
"title": "MutantResult",
|
|
872
|
+
"description": "Single mutation.",
|
|
873
|
+
"identifier": "mutantResult"
|
|
874
|
+
});
|
|
875
|
+
const TestDefinition = S.StructWithRest(S.Struct({
|
|
876
|
+
"id": S.String.annotate({ "description": "Unique id of the test, used to correlate what test killed a mutant." }),
|
|
877
|
+
"name": S.String.annotate({ "description": "Name of the test, used to display the test." }),
|
|
878
|
+
"location": S.optionalKey(OpenEndLocation)
|
|
879
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
880
|
+
"title": "TestDefinition",
|
|
881
|
+
"description": "A test in your test file.",
|
|
882
|
+
"identifier": "testDefinition"
|
|
883
|
+
});
|
|
884
|
+
const FileResult = S.StructWithRest(S.Struct({
|
|
885
|
+
"language": S.String.annotate({
|
|
886
|
+
"description": "Programming language that is used. Used for code highlighting, see https://prismjs.com/#examples.",
|
|
887
|
+
"examples": [
|
|
888
|
+
"javascript",
|
|
889
|
+
"typescript",
|
|
890
|
+
"cs",
|
|
891
|
+
"scala",
|
|
892
|
+
"java"
|
|
893
|
+
]
|
|
894
|
+
}),
|
|
895
|
+
"mutants": S.Array(MutantResult).check(S.isUnique().annotate({ "expected": "an array with unique items" })),
|
|
896
|
+
"source": S.String.annotate({
|
|
897
|
+
"description": "Full source code of the original file (without mutants), this is used to display exactly what was changed for each mutant.",
|
|
898
|
+
"examples": ["using System; using....."]
|
|
899
|
+
})
|
|
900
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
901
|
+
"title": "FileResult",
|
|
902
|
+
"description": "Mutated file, with the relative path of the file as the key.",
|
|
903
|
+
"identifier": "fileResult"
|
|
904
|
+
});
|
|
905
|
+
const TestFile = S.StructWithRest(S.Struct({
|
|
906
|
+
"source": S.optionalKey(S.String.annotate({ "description": "Full source code of the test file, this can be used to display in the report." })),
|
|
907
|
+
"tests": S.Array(TestDefinition)
|
|
908
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
909
|
+
"title": "TestFile",
|
|
910
|
+
"description": "A file containing one or more tests",
|
|
911
|
+
"identifier": "testFile"
|
|
912
|
+
});
|
|
913
|
+
const FileResultDictionary = S.Record(S.String, FileResult).annotate({
|
|
914
|
+
"title": "FileResultDictionary",
|
|
915
|
+
"description": "All mutated files.",
|
|
916
|
+
"identifier": "fileResultDictionary"
|
|
917
|
+
});
|
|
918
|
+
const TestFileDefinitionDictionary = S.Record(S.String, TestFile).annotate({
|
|
919
|
+
"title": "TestFileDefinitionDictionary",
|
|
920
|
+
"description": "Test file definitions by file path OR class name.",
|
|
921
|
+
"identifier": "testFileDefinitionDictionary"
|
|
922
|
+
});
|
|
923
|
+
const MutationTestResult = S.StructWithRest(S.Struct({
|
|
924
|
+
"config": S.optionalKey(S.Record(S.String, S.Json.annotate({ "expected": "JSON value" })).annotate({ "description": "Free-format object that represents the configuration used to run mutation testing." })),
|
|
925
|
+
"schemaVersion": S.String.annotate({
|
|
926
|
+
"description": "Major version of this report. Used for compatibility.",
|
|
927
|
+
"examples": [
|
|
928
|
+
"1",
|
|
929
|
+
"2.0",
|
|
930
|
+
"2.0.0"
|
|
931
|
+
]
|
|
932
|
+
}).check(S.isPattern(/* @__PURE__ */ new RegExp("^([1-2])(\\.(([1-9]\\d*)|0)){0,2}$", "u")).annotate({ "expected": "a string matching the RegExp ^([1-2])(\\.(([1-9]\\d*)|0)){0,2}$" })),
|
|
933
|
+
"files": FileResultDictionary,
|
|
934
|
+
"testFiles": S.optionalKey(TestFileDefinitionDictionary),
|
|
935
|
+
"thresholds": Thresholds,
|
|
936
|
+
"projectRoot": S.optionalKey(S.String.annotate({
|
|
937
|
+
"description": "The optional location of the project root.",
|
|
938
|
+
"examples": ["C:\\Projects\\project-under-test", "/home/user/projects/project-under-test"]
|
|
939
|
+
})),
|
|
940
|
+
"performance": S.optionalKey(PerformanceStatistics),
|
|
941
|
+
"framework": S.optionalKey(FrameworkInformation),
|
|
942
|
+
"system": S.optionalKey(SystemInformation)
|
|
943
|
+
}), [S.Record(S.String, S.Json.annotate({ "expected": "JSON value" }))]).annotate({
|
|
944
|
+
"title": "MutationTestResult",
|
|
945
|
+
"description": "Schema for a mutation testing report."
|
|
946
|
+
});
|
|
947
|
+
const TestId = S.NonEmptyString.pipe(S.brand("TestId"));
|
|
948
|
+
const DryRunStatus = S.Literals([
|
|
949
|
+
"complete",
|
|
950
|
+
"error",
|
|
951
|
+
"timeout"
|
|
952
|
+
]);
|
|
953
|
+
const TestStatus = S.Literals([
|
|
954
|
+
"success",
|
|
955
|
+
"failed",
|
|
956
|
+
"skipped"
|
|
957
|
+
]);
|
|
958
|
+
const MutantRunStatus = S.Literals([
|
|
959
|
+
"killed",
|
|
960
|
+
"survived",
|
|
961
|
+
"timeout",
|
|
962
|
+
"error"
|
|
963
|
+
]);
|
|
964
|
+
const TestResultBase = {
|
|
965
|
+
id: TestId,
|
|
966
|
+
name: S.String,
|
|
967
|
+
timeSpentMs: NonNegativeFinite,
|
|
968
|
+
fileName: S.optionalKey(S.String),
|
|
969
|
+
startPosition: S.optionalKey(Position$1)
|
|
970
|
+
};
|
|
971
|
+
const TestResultSchema = S.Union([
|
|
972
|
+
S.Struct({
|
|
973
|
+
...TestResultBase,
|
|
974
|
+
status: S.Literal("failed"),
|
|
975
|
+
failureMessage: S.String
|
|
976
|
+
}),
|
|
977
|
+
S.Struct({
|
|
978
|
+
...TestResultBase,
|
|
979
|
+
status: S.Literal("skipped")
|
|
980
|
+
}),
|
|
981
|
+
S.Struct({
|
|
982
|
+
...TestResultBase,
|
|
983
|
+
status: S.Literal("success")
|
|
984
|
+
})
|
|
985
|
+
]);
|
|
986
|
+
const DryRunResultSchema = S.Union([
|
|
987
|
+
S.Struct({
|
|
988
|
+
status: S.Literal("complete"),
|
|
989
|
+
tests: S.Array(TestResultSchema),
|
|
990
|
+
mutantCoverage: S.optionalKey(MutantCoverageSchema),
|
|
991
|
+
globalTestInputs: S.String.pipe(S.Array, S.optionalKey)
|
|
992
|
+
}),
|
|
993
|
+
S.Struct({
|
|
994
|
+
status: S.Literal("timeout"),
|
|
995
|
+
reason: S.optionalKey(S.String)
|
|
996
|
+
}),
|
|
997
|
+
S.Struct({
|
|
998
|
+
status: S.Literal("error"),
|
|
999
|
+
errorMessage: S.String
|
|
1000
|
+
})
|
|
1001
|
+
]);
|
|
1002
|
+
const ExecutedTestSchema = S.Struct({
|
|
1003
|
+
id: TestId,
|
|
1004
|
+
timeSpentMs: NonNegativeFinite
|
|
1005
|
+
});
|
|
1006
|
+
const MutantRunResultSchema = S.Union([
|
|
1007
|
+
S.Struct({
|
|
1008
|
+
status: S.Literal("killed"),
|
|
1009
|
+
killedBy: S.Array(TestId),
|
|
1010
|
+
failureMessage: S.String,
|
|
1011
|
+
nrOfTests: NonNegativeInt,
|
|
1012
|
+
executedTests: S.Array(ExecutedTestSchema)
|
|
1013
|
+
}),
|
|
1014
|
+
S.Struct({
|
|
1015
|
+
status: S.Literal("survived"),
|
|
1016
|
+
nrOfTests: NonNegativeInt,
|
|
1017
|
+
executedTests: S.Array(ExecutedTestSchema)
|
|
1018
|
+
}),
|
|
1019
|
+
S.Struct({
|
|
1020
|
+
status: S.Literal("timeout"),
|
|
1021
|
+
reason: S.optionalKey(S.String)
|
|
1022
|
+
}),
|
|
1023
|
+
S.Struct({
|
|
1024
|
+
status: S.Literal("error"),
|
|
1025
|
+
errorMessage: S.String
|
|
1026
|
+
})
|
|
1027
|
+
]);
|
|
1028
|
+
const CoverageAnalysisSchema = S.Literals([
|
|
1029
|
+
"off",
|
|
1030
|
+
"all",
|
|
1031
|
+
"perTest"
|
|
1032
|
+
]);
|
|
1033
|
+
const DryRunOptionsSchema = S.Struct({
|
|
1034
|
+
...RunOptionsFields,
|
|
1035
|
+
coverageAnalysis: CoverageAnalysisSchema,
|
|
1036
|
+
files: S.String.pipe(S.Array, S.optionalKey),
|
|
1037
|
+
testFiles: S.String.pipe(S.Array, S.optionalKey)
|
|
1038
|
+
});
|
|
1039
|
+
const TestRunnerCapabilitiesSchema = S.Struct({ reloadEnvironment: S.Boolean });
|
|
1040
|
+
var TestRunnerFailed = class extends S.TaggedError()("TestRunnerFailed", {
|
|
1041
|
+
cause: S.String,
|
|
1042
|
+
phase: S.Literals([
|
|
1043
|
+
"capabilities",
|
|
1044
|
+
"dispose",
|
|
1045
|
+
"dryRun",
|
|
1046
|
+
"init",
|
|
1047
|
+
"mutantRun"
|
|
1048
|
+
]),
|
|
1049
|
+
runnerName: S.String
|
|
1050
|
+
}) {
|
|
1051
|
+
get message() {
|
|
1052
|
+
return `Test runner "${this.runnerName}" failed during ${this.phase}: ${this.cause}`;
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
const RunTimingSchema = S.Struct({
|
|
1056
|
+
net: NonNegativeFinite,
|
|
1057
|
+
overhead: NonNegativeFinite
|
|
1058
|
+
});
|
|
1059
|
+
const ReporterPlanKind = S.Literals(["EarlyResult", "Run"]);
|
|
1060
|
+
const ReporterPlanDescriptorSchema = S.Struct({
|
|
1061
|
+
mutantId: MutantId,
|
|
1062
|
+
plan: ReporterPlanKind,
|
|
1063
|
+
netTime: NonNegativeFinite,
|
|
1064
|
+
reloadEnvironment: S.Boolean
|
|
1065
|
+
});
|
|
1066
|
+
var DryRunCompleted = class extends S.TaggedClass()("dryRunCompleted", {
|
|
1067
|
+
timing: RunTimingSchema,
|
|
1068
|
+
capabilities: TestRunnerCapabilitiesSchema,
|
|
1069
|
+
testCount: NonNegativeInt,
|
|
1070
|
+
tests: S.Array(TestResultSchema)
|
|
1071
|
+
}) {};
|
|
1072
|
+
var MutationTestingPlanReady = class extends S.TaggedClass()("mutationTestingPlanReady", {
|
|
1073
|
+
total: NonNegativeInt,
|
|
1074
|
+
plans: S.Array(ReporterPlanDescriptorSchema)
|
|
1075
|
+
}) {};
|
|
1076
|
+
var MutantTested = class extends S.TaggedClass()("mutantTested", {
|
|
1077
|
+
id: MutantId,
|
|
1078
|
+
status: MutantStatusSchema,
|
|
1079
|
+
fileName: CanonicalFileName,
|
|
1080
|
+
location: Location$1,
|
|
1081
|
+
mutatorName: MutatorName,
|
|
1082
|
+
replacement: S.NullOr(S.String),
|
|
1083
|
+
completed: NonNegativeInt,
|
|
1084
|
+
total: NonNegativeInt
|
|
1085
|
+
}) {};
|
|
1086
|
+
var MutationTestReportReady = class extends S.TaggedClass()("mutationTestReportReady", {
|
|
1087
|
+
report: MutationTestResult,
|
|
1088
|
+
metrics: MetricsResultSchema,
|
|
1089
|
+
static: S.optional(StaticClassSummarySchema)
|
|
1090
|
+
}) {};
|
|
1091
|
+
const ReporterEventUnion = S.Union([
|
|
1092
|
+
DryRunCompleted,
|
|
1093
|
+
MutationTestingPlanReady,
|
|
1094
|
+
MutantTested,
|
|
1095
|
+
MutationTestReportReady
|
|
1096
|
+
]).pipe(S.toTaggedUnion("_tag"));
|
|
1097
|
+
const ReporterEventKind = S.Literals(ReporterEventUnion.discriminants);
|
|
1098
|
+
const ReporterEventSchema = S.toStandardSchemaV1(ReporterEventUnion);
|
|
1099
|
+
var ReporterFailed = class extends S.TaggedError()("ReporterFailed", {
|
|
1100
|
+
cause: S.String,
|
|
1101
|
+
event: ReporterEventKind,
|
|
1102
|
+
reporterName: S.String
|
|
1103
|
+
}) {
|
|
1104
|
+
get message() {
|
|
1105
|
+
return `Reporter "${this.reporterName}" failed while handling ${this.event}: ${this.cause}`;
|
|
1106
|
+
}
|
|
1107
|
+
};
|
|
1108
|
+
const TraceparentHeader = S.Literal("traceparent");
|
|
1109
|
+
const TracestateHeader = S.Literal("tracestate");
|
|
1110
|
+
const VERSION = S.String.pipe(S.check(S.isPattern(/^([0-9a-e][0-9a-f]|[0-9a-f][0-9a-e])$/u)));
|
|
1111
|
+
const TRACE_ID = S.String.pipe(S.check(S.isPattern(/^[0-9a-f]*[1-9a-f][0-9a-f]*$/u)), S.check(S.isBetweenLength(32, 32)));
|
|
1112
|
+
const SPAN_ID = S.String.pipe(S.check(S.isPattern(/^[0-9a-f]*[1-9a-f][0-9a-f]*$/u)), S.check(S.isBetweenLength(16, 16)));
|
|
1113
|
+
const TraceContextPartsSchema = S.Struct({
|
|
1114
|
+
version: VERSION,
|
|
1115
|
+
traceId: TRACE_ID,
|
|
1116
|
+
spanId: SPAN_ID,
|
|
1117
|
+
traceFlags: S.Int.pipe(S.check(S.isBetween({
|
|
1118
|
+
minimum: 0,
|
|
1119
|
+
maximum: 255
|
|
1120
|
+
}))),
|
|
1121
|
+
traceState: S.optional(S.String)
|
|
1122
|
+
});
|
|
1123
|
+
const TraceparentPartsSchema = S.Struct({
|
|
1124
|
+
version: VERSION,
|
|
1125
|
+
traceId: TRACE_ID,
|
|
1126
|
+
spanId: SPAN_ID,
|
|
1127
|
+
traceFlags: S.Int.pipe(S.check(S.isBetween({
|
|
1128
|
+
minimum: 0,
|
|
1129
|
+
maximum: 255
|
|
1130
|
+
})))
|
|
1131
|
+
});
|
|
1132
|
+
const HEX_VERSION = /^[0-9a-f]{2}$/;
|
|
1133
|
+
const HEX_TRACE_ID = /^[0-9a-f]{32}$/;
|
|
1134
|
+
const HEX_SPAN_ID = /^[0-9a-f]{16}$/;
|
|
1135
|
+
const HEX_FLAGS = /^[0-9a-f]{2}$/;
|
|
1136
|
+
const ALL_ZERO = /^0+$/;
|
|
1137
|
+
const FORBIDDEN_VERSION = "ff";
|
|
1138
|
+
const CURRENT_VERSION = "00";
|
|
1139
|
+
const TRACEPARENT_FIELD_COUNT = 4;
|
|
1140
|
+
const fieldAt = (fields, index) => fields[index] ?? "";
|
|
1141
|
+
const isNonZeroHex = (pattern, value) => pattern.test(value) && !ALL_ZERO.test(value);
|
|
1142
|
+
const acceptsFieldCount = (version, count) => version !== CURRENT_VERSION || count === TRACEPARENT_FIELD_COUNT;
|
|
1143
|
+
const isKnownVersion = (version) => HEX_VERSION.test(version) && version !== FORBIDDEN_VERSION;
|
|
1144
|
+
const isWellFormedTraceparent = (value) => {
|
|
1145
|
+
const fields = value.split("-");
|
|
1146
|
+
return [
|
|
1147
|
+
acceptsFieldCount(fieldAt(fields, 0), fields.length),
|
|
1148
|
+
isKnownVersion(fieldAt(fields, 0)),
|
|
1149
|
+
isNonZeroHex(HEX_TRACE_ID, fieldAt(fields, 1)),
|
|
1150
|
+
isNonZeroHex(HEX_SPAN_ID, fieldAt(fields, 2)),
|
|
1151
|
+
HEX_FLAGS.test(fieldAt(fields, 3))
|
|
1152
|
+
].every((check) => check);
|
|
1153
|
+
};
|
|
1154
|
+
const partsOf = (value) => {
|
|
1155
|
+
const fields = value.split("-");
|
|
1156
|
+
return {
|
|
1157
|
+
version: fieldAt(fields, 0),
|
|
1158
|
+
traceId: fieldAt(fields, 1),
|
|
1159
|
+
spanId: fieldAt(fields, 2),
|
|
1160
|
+
traceFlags: Number.parseInt(fieldAt(fields, 3), 16)
|
|
1161
|
+
};
|
|
1162
|
+
};
|
|
1163
|
+
const formatOf = (parts) => `${parts.version}-${parts.traceId}-${parts.spanId}-${(parts.traceFlags & 255).toString(16).padStart(2, "0")}`;
|
|
1164
|
+
const malformedTraceparent = (value) => new SchemaIssue.InvalidValue({ message: "expected a W3C traceparent: version-traceId-spanId-flags" }, value);
|
|
1165
|
+
const decodeParts = SchemaGetter.transformEffect((value) => Boolean$1.match(isWellFormedTraceparent(value), {
|
|
1166
|
+
onTrue: () => Effect$1.succeed(partsOf(value)),
|
|
1167
|
+
onFalse: () => Effect$1.fail(malformedTraceparent(value))
|
|
1168
|
+
}));
|
|
1169
|
+
const encodeText = SchemaGetter.transform(formatOf);
|
|
1170
|
+
const Traceparent = S.String.pipe(S.decodeTo(TraceparentPartsSchema, SchemaTransformation.makeTransformation({
|
|
1171
|
+
decode: decodeParts,
|
|
1172
|
+
encode: encodeText
|
|
1173
|
+
})));
|
|
1174
|
+
const TRACESTATE_MEMBER = "[a-z][_0-9a-z\\-*/]{0,255}=[\\x20-\\x2b\\x2d-\\x3c\\x3e-\\x7e]{0,255}";
|
|
1175
|
+
const TRACESTATE_OWS = "[ \\t]*";
|
|
1176
|
+
const TRACESTATE = new RegExp(`^${TRACESTATE_MEMBER}(${TRACESTATE_OWS},${TRACESTATE_OWS}${TRACESTATE_MEMBER}){0,31}$`, "u");
|
|
1177
|
+
const Tracestate = S.String.pipe(S.check(S.isPattern(TRACESTATE, { expected: "a W3C tracestate: comma-separated key=value members" })));
|
|
1178
|
+
const WorkerPluginKind = S.Literals([
|
|
1179
|
+
"TestRunner",
|
|
1180
|
+
"Checker",
|
|
1181
|
+
"Reporter"
|
|
1182
|
+
]);
|
|
1183
|
+
const EvaluatorPluginKind = S.Literal("Evaluator");
|
|
1184
|
+
const PluginKindSchema = S.Union([WorkerPluginKind, EvaluatorPluginKind]);
|
|
1185
|
+
const TestRunnerDryRunRequest = S.Struct({ options: DryRunOptionsSchema });
|
|
1186
|
+
const TestRunnerMutantRunRequest = S.Struct({ options: MutantRunOptionsSchema });
|
|
1187
|
+
const CheckerRequest = S.Struct({
|
|
1188
|
+
checkerName: S.String,
|
|
1189
|
+
mutants: S.Array(CheckerMutantWire)
|
|
1190
|
+
});
|
|
1191
|
+
const CheckerCheckResult = S.Record(S.String, CheckResultSchema);
|
|
1192
|
+
const CheckerGroupResult = S.String.pipe(S.Array, S.Array);
|
|
1193
|
+
const ReporterInitOptions = S.Struct({
|
|
1194
|
+
traceparent: S.optionalKey(Traceparent),
|
|
1195
|
+
tracestate: S.optionalKey(Tracestate)
|
|
1196
|
+
});
|
|
1197
|
+
const ReporterEventBatch = S.Array(ReporterEventUnion);
|
|
1198
|
+
const ReporterAck = S.Void;
|
|
1199
|
+
const ReporterDrained = S.Void;
|
|
1200
|
+
var BoundaryPayloadRejected = class extends S.TaggedError()("BoundaryPayloadRejected", {
|
|
1201
|
+
pluginName: S.String,
|
|
1202
|
+
method: S.String,
|
|
1203
|
+
cause: S.String
|
|
1204
|
+
}) {
|
|
1205
|
+
get message() {
|
|
1206
|
+
return `Plugin "${this.pluginName}" rejected the payload for ${this.method}: ${this.cause}`;
|
|
1207
|
+
}
|
|
1208
|
+
};
|
|
1209
|
+
var BoundaryUnrecognizedSignal = class extends S.TaggedError()("BoundaryUnrecognizedSignal", {
|
|
1210
|
+
pluginName: S.String,
|
|
1211
|
+
method: S.String,
|
|
1212
|
+
signal: S.String
|
|
1213
|
+
}) {
|
|
1214
|
+
get message() {
|
|
1215
|
+
return `Plugin "${this.pluginName}" sent an unrecognized signal "${this.signal}" for ${this.method}`;
|
|
1216
|
+
}
|
|
1217
|
+
};
|
|
1218
|
+
const BoundaryErrorSchema = S.Union([
|
|
1219
|
+
BoundaryPayloadRejected,
|
|
1220
|
+
BoundaryUnrecognizedSignal,
|
|
1221
|
+
TestRunnerFailed,
|
|
1222
|
+
CheckerFailed,
|
|
1223
|
+
ReporterFailed
|
|
1224
|
+
]);
|
|
1225
|
+
const WorkerEntryUrl = S.String.check(S.isPattern(/^file:\/\//u, { expected: "a file: URL of the worker program" }));
|
|
1226
|
+
const WorkerPluginSpawnSchema = S.Struct({
|
|
1227
|
+
kind: WorkerPluginKind,
|
|
1228
|
+
entrypoint: WorkerEntryUrl
|
|
1229
|
+
});
|
|
1230
|
+
var PropagatedTrace = class extends Context.Service()("@systemfsoftware/stryker-js-plugin-interface/TraceContextRpc.service/PropagatedTrace") {};
|
|
1231
|
+
var TraceContextMiddleware = class extends RpcMiddleware.Service()("@systemfsoftware/stryker-js-plugin-interface/TraceContextMiddleware", { requiredForClient: true }) {};
|
|
1232
|
+
const capabilities = Rpc.make("capabilities", {
|
|
1233
|
+
success: TestRunnerCapabilitiesSchema,
|
|
1234
|
+
error: TestRunnerFailed
|
|
1235
|
+
}).middleware(TraceContextMiddleware);
|
|
1236
|
+
const dryRun = Rpc.make("dryRun", {
|
|
1237
|
+
payload: TestRunnerDryRunRequest,
|
|
1238
|
+
success: DryRunResultSchema,
|
|
1239
|
+
error: TestRunnerFailed
|
|
1240
|
+
}).middleware(TraceContextMiddleware);
|
|
1241
|
+
const mutantRun = Rpc.make("mutantRun", {
|
|
1242
|
+
payload: TestRunnerMutantRunRequest,
|
|
1243
|
+
success: MutantRunResultSchema,
|
|
1244
|
+
error: TestRunnerFailed
|
|
1245
|
+
}).middleware(TraceContextMiddleware);
|
|
1246
|
+
const check = Rpc.make("check", {
|
|
1247
|
+
payload: CheckerRequest,
|
|
1248
|
+
success: CheckerCheckResult,
|
|
1249
|
+
error: CheckerFailed
|
|
1250
|
+
}).middleware(TraceContextMiddleware);
|
|
1251
|
+
const group = Rpc.make("group", {
|
|
1252
|
+
payload: CheckerRequest,
|
|
1253
|
+
success: CheckerGroupResult,
|
|
1254
|
+
error: CheckerFailed
|
|
1255
|
+
}).middleware(TraceContextMiddleware);
|
|
1256
|
+
const init = Rpc.make("init", {
|
|
1257
|
+
payload: ReporterInitOptions,
|
|
1258
|
+
success: ReporterAck,
|
|
1259
|
+
error: ReporterFailed
|
|
1260
|
+
}).middleware(TraceContextMiddleware);
|
|
1261
|
+
const onEventBatch = Rpc.make("onEventBatch", {
|
|
1262
|
+
payload: ReporterEventBatch,
|
|
1263
|
+
success: ReporterAck,
|
|
1264
|
+
error: ReporterFailed
|
|
1265
|
+
}).middleware(TraceContextMiddleware);
|
|
1266
|
+
const flush = Rpc.make("flush", {
|
|
1267
|
+
success: ReporterDrained,
|
|
1268
|
+
error: ReporterFailed
|
|
1269
|
+
}).middleware(TraceContextMiddleware);
|
|
1270
|
+
const TestRunnerRpcs = RpcGroup.make(capabilities, dryRun, mutantRun);
|
|
1271
|
+
const CheckerRpcs = RpcGroup.make(check, group);
|
|
1272
|
+
const ReporterRpcs = RpcGroup.make(init, onEventBatch, flush);
|
|
1273
|
+
var Plugin_exports = /* @__PURE__ */ __exportAll({
|
|
1274
|
+
BoundaryErrorSchema: () => BoundaryErrorSchema,
|
|
1275
|
+
BoundaryPayloadRejected: () => BoundaryPayloadRejected,
|
|
1276
|
+
BoundaryUnrecognizedSignal: () => BoundaryUnrecognizedSignal,
|
|
1277
|
+
CheckerCheckResult: () => CheckerCheckResult,
|
|
1278
|
+
CheckerGroupResult: () => CheckerGroupResult,
|
|
1279
|
+
CheckerRequest: () => CheckerRequest,
|
|
1280
|
+
CheckerRpcs: () => CheckerRpcs,
|
|
1281
|
+
EvaluatorPluginKind: () => EvaluatorPluginKind,
|
|
1282
|
+
ExitClass: () => ExitClass,
|
|
1283
|
+
ExitCode: () => ExitCode,
|
|
1284
|
+
ExitCodeFromClass: () => ExitCodeFromClass,
|
|
1285
|
+
PluginKindSchema: () => PluginKindSchema,
|
|
1286
|
+
ReporterAck: () => ReporterAck,
|
|
1287
|
+
ReporterDrained: () => ReporterDrained,
|
|
1288
|
+
ReporterEventBatch: () => ReporterEventBatch,
|
|
1289
|
+
ReporterInitOptions: () => ReporterInitOptions,
|
|
1290
|
+
ReporterRpcs: () => ReporterRpcs,
|
|
1291
|
+
TestRunnerDryRunRequest: () => TestRunnerDryRunRequest,
|
|
1292
|
+
TestRunnerMutantRunRequest: () => TestRunnerMutantRunRequest,
|
|
1293
|
+
TestRunnerRpcs: () => TestRunnerRpcs,
|
|
1294
|
+
WorkerEntryUrl: () => WorkerEntryUrl,
|
|
1295
|
+
WorkerPluginKind: () => WorkerPluginKind,
|
|
1296
|
+
WorkerPluginSpawnSchema: () => WorkerPluginSpawnSchema
|
|
1297
|
+
});
|
|
1298
|
+
const countOf = (mutants, status) => mutants.filter((mutant) => mutant.status === status).length;
|
|
1299
|
+
const metricsFromMutants = (mutants) => Metrics.make({
|
|
1300
|
+
pending: countOf(mutants, "Pending"),
|
|
1301
|
+
killed: countOf(mutants, "Killed"),
|
|
1302
|
+
timeout: countOf(mutants, "Timeout"),
|
|
1303
|
+
survived: countOf(mutants, "Survived"),
|
|
1304
|
+
noCoverage: countOf(mutants, "NoCoverage"),
|
|
1305
|
+
runtimeErrors: countOf(mutants, "RuntimeError"),
|
|
1306
|
+
compileErrors: countOf(mutants, "CompileError"),
|
|
1307
|
+
ignored: countOf(mutants, "Ignored")
|
|
1308
|
+
});
|
|
1309
|
+
const WrittenSchemaVersion = S.Literal("1.0");
|
|
1310
|
+
var Report_exports = /* @__PURE__ */ __exportAll({
|
|
1311
|
+
BrandingInformation: () => BrandingInformation,
|
|
1312
|
+
CpuInformation: () => CpuInformation,
|
|
1313
|
+
Dependencies: () => Dependencies,
|
|
1314
|
+
DetectedStatus: () => DetectedStatus,
|
|
1315
|
+
FileResult: () => FileResult,
|
|
1316
|
+
FileResultDictionary: () => FileResultDictionary,
|
|
1317
|
+
FrameworkInformation: () => FrameworkInformation,
|
|
1318
|
+
InvalidStatus: () => InvalidStatus,
|
|
1319
|
+
Location: () => Location,
|
|
1320
|
+
Metrics: () => Metrics,
|
|
1321
|
+
MetricsResultSchema: () => MetricsResultSchema,
|
|
1322
|
+
MetricsSchema: () => MetricsSchema,
|
|
1323
|
+
MutantResult: () => MutantResult,
|
|
1324
|
+
MutationScore: () => MutationScore,
|
|
1325
|
+
MutationTestResult: () => MutationTestResult,
|
|
1326
|
+
NonNegativeFinite: () => NonNegativeFinite,
|
|
1327
|
+
NonNegativeInt: () => NonNegativeInt,
|
|
1328
|
+
OSInformation: () => OSInformation,
|
|
1329
|
+
OpenEndLocation: () => OpenEndLocation,
|
|
1330
|
+
Percentage: () => Percentage,
|
|
1331
|
+
PerformanceStatistics: () => PerformanceStatistics,
|
|
1332
|
+
Position: () => Position,
|
|
1333
|
+
RamInformation: () => RamInformation,
|
|
1334
|
+
StaticClassSummarySchema: () => StaticClassSummarySchema,
|
|
1335
|
+
SystemInformation: () => SystemInformation,
|
|
1336
|
+
TestDefinition: () => TestDefinition,
|
|
1337
|
+
TestFile: () => TestFile,
|
|
1338
|
+
TestFileDefinitionDictionary: () => TestFileDefinitionDictionary,
|
|
1339
|
+
Thresholds: () => Thresholds,
|
|
1340
|
+
UndetectedStatus: () => UndetectedStatus,
|
|
1341
|
+
UntestedStatus: () => UntestedStatus,
|
|
1342
|
+
WrittenSchemaVersion: () => WrittenSchemaVersion,
|
|
1343
|
+
metricsFromMutants: () => metricsFromMutants
|
|
1344
|
+
});
|
|
1345
|
+
var Reporter_exports = /* @__PURE__ */ __exportAll({
|
|
1346
|
+
DryRunCompleted: () => DryRunCompleted,
|
|
1347
|
+
MutantTested: () => MutantTested,
|
|
1348
|
+
MutationTestReportReady: () => MutationTestReportReady,
|
|
1349
|
+
MutationTestingPlanReady: () => MutationTestingPlanReady,
|
|
1350
|
+
ReporterEventKind: () => ReporterEventKind,
|
|
1351
|
+
ReporterEventSchema: () => ReporterEventSchema,
|
|
1352
|
+
ReporterEventUnion: () => ReporterEventUnion,
|
|
1353
|
+
ReporterFailed: () => ReporterFailed,
|
|
1354
|
+
ReporterPlanDescriptorSchema: () => ReporterPlanDescriptorSchema,
|
|
1355
|
+
ReporterPlanKind: () => ReporterPlanKind,
|
|
1356
|
+
RunTimingSchema: () => RunTimingSchema
|
|
1357
|
+
});
|
|
1358
|
+
const HitLimitReasonPrefix = S.Literal("Hit limit reached");
|
|
1359
|
+
const WallClockTimeoutReason = S.Literal("wall-clock-timeout");
|
|
1360
|
+
const HIT_LIMIT_REASON_PREFIX = HitLimitReasonPrefix.literal;
|
|
1361
|
+
const HitLimitReasonText = S.String.check(S.isStartingWith(HIT_LIMIT_REASON_PREFIX, { arbitraryConstraint: {
|
|
1362
|
+
patterns: [{
|
|
1363
|
+
source: `^${HIT_LIMIT_REASON_PREFIX}[\\s\\S]*$`,
|
|
1364
|
+
flags: ""
|
|
1365
|
+
}],
|
|
1366
|
+
minLength: HIT_LIMIT_REASON_PREFIX.length + 2
|
|
1367
|
+
} }));
|
|
1368
|
+
const HIT_LIMIT_REASON_SHAPE = /^Hit limit reached \((\d+)\/(\d+)\)$/;
|
|
1369
|
+
const limitsOf = SchemaGetter.transformEffect((text) => Option$1.match(Option$1.fromNullishOr(HIT_LIMIT_REASON_SHAPE.exec(text)), {
|
|
1370
|
+
onNone: () => Effect$1.fail(malformedHitLimit(text)),
|
|
1371
|
+
onSome: (matched) => Effect$1.succeed({
|
|
1372
|
+
count: Number.parseInt(String(matched[1]), 10),
|
|
1373
|
+
limit: Number.parseInt(String(matched[2]), 10)
|
|
1374
|
+
})
|
|
1375
|
+
}));
|
|
1376
|
+
const textOf = SchemaGetter.transform((limits) => `${HitLimitReasonPrefix.literal} (${limits.count}/${limits.limit})`);
|
|
1377
|
+
const malformedHitLimit = (text) => new SchemaIssue.InvalidValue({ message: "expected \"Hit limit reached (count/limit)\"" }, text);
|
|
1378
|
+
const HitLimitReason = HitLimitReasonText.pipe(S.decodeTo(S.Struct({
|
|
1379
|
+
count: S.Natural,
|
|
1380
|
+
limit: S.Natural
|
|
1381
|
+
}), SchemaTransformation.makeTransformation({
|
|
1382
|
+
decode: limitsOf,
|
|
1383
|
+
encode: textOf
|
|
1384
|
+
})));
|
|
1385
|
+
var TestRunner = class extends Context.Service()("@systemfsoftware/stryker-js-plugin-interface/TestRunner.service/TestRunner") {};
|
|
1386
|
+
var TestRunner_exports = /* @__PURE__ */ __exportAll({
|
|
1387
|
+
CoverageAnalysisSchema: () => CoverageAnalysisSchema,
|
|
1388
|
+
DryRunOptionsSchema: () => DryRunOptionsSchema,
|
|
1389
|
+
DryRunResultSchema: () => DryRunResultSchema,
|
|
1390
|
+
DryRunStatus: () => DryRunStatus,
|
|
1391
|
+
ExecutedTestSchema: () => ExecutedTestSchema,
|
|
1392
|
+
HitLimitReason: () => HitLimitReason,
|
|
1393
|
+
HitLimitReasonPrefix: () => HitLimitReasonPrefix,
|
|
1394
|
+
HitLimitReasonText: () => HitLimitReasonText,
|
|
1395
|
+
MutantRunResultSchema: () => MutantRunResultSchema,
|
|
1396
|
+
MutantRunStatus: () => MutantRunStatus,
|
|
1397
|
+
TestId: () => TestId,
|
|
1398
|
+
TestResultSchema: () => TestResultSchema,
|
|
1399
|
+
TestRunner: () => TestRunner,
|
|
1400
|
+
TestRunnerCapabilitiesSchema: () => TestRunnerCapabilitiesSchema,
|
|
1401
|
+
TestRunnerFailed: () => TestRunnerFailed,
|
|
1402
|
+
TestStatus: () => TestStatus,
|
|
1403
|
+
WallClockTimeoutReason: () => WallClockTimeoutReason
|
|
1404
|
+
});
|
|
1405
|
+
const TraceContextReference = Context.Reference("@systemfsoftware/stryker-js-plugin-interface/TraceContextReference", { defaultValue: () => Option$1.none() });
|
|
1406
|
+
var Trace_exports = /* @__PURE__ */ __exportAll({
|
|
1407
|
+
PropagatedTrace: () => PropagatedTrace,
|
|
1408
|
+
TraceContextMiddleware: () => TraceContextMiddleware,
|
|
1409
|
+
TraceContextPartsSchema: () => TraceContextPartsSchema,
|
|
1410
|
+
TraceContextReference: () => TraceContextReference,
|
|
1411
|
+
Traceparent: () => Traceparent,
|
|
1412
|
+
TraceparentHeader: () => TraceparentHeader,
|
|
1413
|
+
Tracestate: () => Tracestate,
|
|
1414
|
+
TracestateHeader: () => TracestateHeader
|
|
1415
|
+
});
|
|
1416
|
+
//#endregion
|
|
1417
|
+
//#region src/config/merge-config.ts
|
|
1418
|
+
/**
|
|
1419
|
+
* Whether an entry takes part in a merge: a key literally named `__proto__` never does — the
|
|
1420
|
+
* merged record must not gain a document-decided prototype — and an explicitly `undefined`
|
|
1421
|
+
* value states that the author left the key unset, not that they want it set to nothing.
|
|
1422
|
+
*/
|
|
1423
|
+
const usable = (value, key) => key !== "__proto__" && value !== void 0;
|
|
1424
|
+
const usableEntries = (source) => Record$1.filter(source, usable);
|
|
1425
|
+
const isConfigRecord = (value) => Predicate$1.isObject(value);
|
|
1426
|
+
const asConfigRecord = (value) => Option$1.filter(Option$1.fromUndefinedOr(value), isConfigRecord);
|
|
1427
|
+
const mergeNested = (base, override) => Option$1.match(asConfigRecord(override), {
|
|
1428
|
+
onNone: () => override,
|
|
1429
|
+
onSome: (overrideRecord) => mergeRecords(base, overrideRecord)
|
|
1430
|
+
});
|
|
1431
|
+
const hasUsableMember = (key) => (merged) => merged.hasOwnProperty(key) && merged[key] !== void 0;
|
|
1432
|
+
const ownValueOf = (merged, key) => Option$1.map(Option$1.liftPredicate(merged, hasUsableMember(key)), (present) => present[key]);
|
|
1433
|
+
const baseRecordOf = (ownValue) => Option$1.filter(Option$1.flatMap(ownValue, Option$1.fromUndefinedOr), isConfigRecord);
|
|
1434
|
+
const mergeKeyInto = (merged, override, key) => ({
|
|
1435
|
+
...merged,
|
|
1436
|
+
[key]: Option$1.match(baseRecordOf(ownValueOf(merged, key)), {
|
|
1437
|
+
onNone: () => override,
|
|
1438
|
+
onSome: (baseRecord) => mergeNested(baseRecord, override)
|
|
1439
|
+
})
|
|
1440
|
+
});
|
|
1441
|
+
const mergeRecords = (base, overrides) => Record$1.reduce(usableEntries(overrides), usableEntries(base), mergeKeyInto);
|
|
1442
|
+
const mergeConfig = dual(2, (defaults, overrides) => mergeRecords(defaults, overrides));
|
|
1443
|
+
const isNonNullObject = (value) => typeof value === "object" && value !== null;
|
|
1444
|
+
const asUnknownArray = (value) => Array.isArray(value) ? value : [];
|
|
1445
|
+
const isFirstDescriptorOccurrence = (descriptors) => (descriptor, index) => typeof descriptor !== "string" || descriptors.slice(0, index).includes(descriptor) === false;
|
|
1446
|
+
const mergePluginDescriptors = (parentPlugins, childPlugins) => {
|
|
1447
|
+
const merged = [...parentPlugins, ...childPlugins];
|
|
1448
|
+
return merged.filter(isFirstDescriptorOccurrence(merged));
|
|
1449
|
+
};
|
|
1450
|
+
const isConfigOptionsRecord = (value) => isNonNullObject(value) && Array.isArray(value) === false;
|
|
1451
|
+
const mergeConfigRecords = (parentNested, childNested) => ({
|
|
1452
|
+
...parentNested,
|
|
1453
|
+
...childNested
|
|
1454
|
+
});
|
|
1455
|
+
const toConfigRecordOption = (value) => isConfigOptionsRecord(value) ? Option$1.some(value) : Option$1.none();
|
|
1456
|
+
const inheritNested = (parentValue, childValue) => Option$1.match(Option$1.all([toConfigRecordOption(parentValue), toConfigRecordOption(childValue)]), {
|
|
1457
|
+
onSome: ([parentNested, childNested]) => mergeConfigRecords(parentNested, childNested),
|
|
1458
|
+
onNone: () => childValue
|
|
1459
|
+
});
|
|
1460
|
+
const inheritEntry = (out, key, parentValue, childValue) => Match$1.value(childValue).pipe(Match$1.when(null, () => {
|
|
1461
|
+
const next = { ...out };
|
|
1462
|
+
delete next[key];
|
|
1463
|
+
return next;
|
|
1464
|
+
}), Match$1.orElse(() => Match$1.value(key).pipe(Match$1.when("plugins", () => ({
|
|
1465
|
+
...out,
|
|
1466
|
+
[key]: mergePluginDescriptors(asUnknownArray(parentValue), asUnknownArray(childValue))
|
|
1467
|
+
})), Match$1.orElse(() => ({
|
|
1468
|
+
...out,
|
|
1469
|
+
[key]: inheritNested(parentValue, childValue)
|
|
1470
|
+
})))));
|
|
1471
|
+
const mergeConfigs = dual(2, (parent, child) => Object.entries(child).reduce((out, entry) => inheritEntry(out, entry[0], parent[entry[0]], entry[1]), { ...parent }));
|
|
1472
|
+
//#endregion
|
|
1473
|
+
export { MutatorCatalog_exports as a, Plugin_exports as c, TestRunner_exports as d, Trace_exports as f, Mutant_exports as i, Report_exports as l, mergeConfigs as n, MutatorProvider_exports as o, Checker_exports as r, Options_exports as s, mergeConfig as t, Reporter_exports as u };
|