@mutineerjs/mutineer 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -15
- package/dist/bin/__tests__/mutineer.spec.js +75 -2
- package/dist/bin/mutineer.d.ts +6 -1
- package/dist/bin/mutineer.js +56 -1
- package/dist/core/__tests__/schemata.spec.d.ts +1 -0
- package/dist/core/__tests__/schemata.spec.js +165 -0
- package/dist/core/schemata.d.ts +22 -0
- package/dist/core/schemata.js +236 -0
- package/dist/runner/__tests__/args.spec.js +40 -0
- package/dist/runner/__tests__/cleanup.spec.js +7 -0
- package/dist/runner/__tests__/coverage-resolver.spec.js +4 -0
- package/dist/runner/__tests__/orchestrator.spec.js +183 -18
- package/dist/runner/__tests__/pool-executor.spec.js +47 -0
- package/dist/runner/__tests__/ts-checker.spec.d.ts +1 -0
- package/dist/runner/__tests__/ts-checker.spec.js +115 -0
- package/dist/runner/args.d.ts +6 -0
- package/dist/runner/args.js +12 -0
- package/dist/runner/cleanup.js +1 -1
- package/dist/runner/jest/__tests__/adapter.spec.js +49 -0
- package/dist/runner/jest/adapter.js +30 -2
- package/dist/runner/orchestrator.js +111 -17
- package/dist/runner/pool-executor.d.ts +2 -0
- package/dist/runner/pool-executor.js +15 -4
- package/dist/runner/shared/__tests__/mutant-paths.spec.js +30 -1
- package/dist/runner/shared/index.d.ts +1 -1
- package/dist/runner/shared/index.js +1 -1
- package/dist/runner/shared/mutant-paths.d.ts +17 -0
- package/dist/runner/shared/mutant-paths.js +24 -0
- package/dist/runner/ts-checker-worker.d.ts +5 -0
- package/dist/runner/ts-checker-worker.js +66 -0
- package/dist/runner/ts-checker.d.ts +36 -0
- package/dist/runner/ts-checker.js +210 -0
- package/dist/runner/types.d.ts +2 -0
- package/dist/runner/vitest/__tests__/adapter.spec.js +70 -0
- package/dist/runner/vitest/__tests__/plugin.spec.js +151 -0
- package/dist/runner/vitest/__tests__/pool.spec.js +85 -0
- package/dist/runner/vitest/__tests__/worker-runtime.spec.js +126 -0
- package/dist/runner/vitest/adapter.js +13 -1
- package/dist/runner/vitest/plugin.d.ts +3 -0
- package/dist/runner/vitest/plugin.js +49 -11
- package/dist/runner/vitest/pool.d.ts +4 -1
- package/dist/runner/vitest/pool.js +25 -4
- package/dist/runner/vitest/worker-runtime.d.ts +1 -0
- package/dist/runner/vitest/worker-runtime.js +57 -18
- package/dist/runner/vitest/worker.mjs +10 -0
- package/dist/types/config.d.ts +14 -0
- package/dist/types/mutant.d.ts +5 -2
- package/dist/utils/CompileErrors.d.ts +7 -0
- package/dist/utils/CompileErrors.js +24 -0
- package/dist/utils/__tests__/CompileErrors.spec.d.ts +1 -0
- package/dist/utils/__tests__/CompileErrors.spec.js +96 -0
- package/dist/utils/__tests__/summary.spec.js +83 -1
- package/dist/utils/summary.d.ts +5 -1
- package/dist/utils/summary.js +38 -3
- package/package.json +2 -2
package/dist/types/mutant.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Centralises the shapes used across the runner and adapters so we
|
|
5
5
|
* don't duplicate unions or object shapes in multiple modules.
|
|
6
6
|
*/
|
|
7
|
-
export type MutantStatus = 'killed' | 'escaped' | 'skipped' | 'error' | 'timeout';
|
|
7
|
+
export type MutantStatus = 'killed' | 'escaped' | 'skipped' | 'error' | 'timeout' | 'compile-error';
|
|
8
8
|
export type MutantRunStatus = MutantStatus;
|
|
9
9
|
export interface MutantLocation {
|
|
10
10
|
readonly file: string;
|
|
@@ -17,7 +17,10 @@ export interface MutantDescriptor extends MutantLocation {
|
|
|
17
17
|
readonly code: string;
|
|
18
18
|
}
|
|
19
19
|
/** Payload passed to workers/pools for execution. */
|
|
20
|
-
export
|
|
20
|
+
export interface MutantPayload extends MutantDescriptor {
|
|
21
|
+
/** When true, this mutant must use the legacy redirect path instead of the schema path. */
|
|
22
|
+
readonly isFallback?: boolean;
|
|
23
|
+
}
|
|
21
24
|
/** Variant with attached test files. */
|
|
22
25
|
export interface Variant extends MutantDescriptor {
|
|
23
26
|
readonly tests: readonly string[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { Box, Text, useInput, useApp } from 'ink';
|
|
4
|
+
import { useState, useEffect } from 'react';
|
|
5
|
+
export function CompileErrors({ entries, cwd }) {
|
|
6
|
+
const { exit } = useApp();
|
|
7
|
+
const [expanded, setExpanded] = useState(false);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (expanded)
|
|
10
|
+
exit();
|
|
11
|
+
}, [expanded, exit]);
|
|
12
|
+
useInput((input, key) => {
|
|
13
|
+
if (input === 'e') {
|
|
14
|
+
setExpanded(true);
|
|
15
|
+
}
|
|
16
|
+
else if (key.return || input === 'q') {
|
|
17
|
+
exit();
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
if (expanded) {
|
|
21
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Compile Error Mutants (type-filtered):" }), entries.map((entry, i) => (_jsxs(Text, { dimColor: true, children: [' \u2022 ', path.relative(cwd, entry.file), "@", entry.line, ",", entry.col, ' ', entry.mutator] }, i)))] }));
|
|
22
|
+
}
|
|
23
|
+
return (_jsxs(Box, { gap: 2, children: [_jsxs(Text, { dimColor: true, children: ["Compile Error Mutants (type-filtered): ", entries.length] }), _jsx(Text, { dimColor: true, children: "e expand return skip" })] }));
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
const mockExit = vi.fn();
|
|
3
|
+
const mockSetExpanded = vi.fn();
|
|
4
|
+
let inputHandler;
|
|
5
|
+
let effectCallback;
|
|
6
|
+
vi.mock('ink', () => ({
|
|
7
|
+
Box: ({ children }) => children,
|
|
8
|
+
Text: ({ children }) => children,
|
|
9
|
+
useInput: vi.fn((fn) => {
|
|
10
|
+
inputHandler = fn;
|
|
11
|
+
}),
|
|
12
|
+
useApp: () => ({ exit: mockExit }),
|
|
13
|
+
}));
|
|
14
|
+
vi.mock('react', async (importOriginal) => {
|
|
15
|
+
const actual = await importOriginal();
|
|
16
|
+
return {
|
|
17
|
+
...actual,
|
|
18
|
+
useState: vi.fn((init) => [init, mockSetExpanded]),
|
|
19
|
+
useEffect: vi.fn((fn) => {
|
|
20
|
+
effectCallback = fn;
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
import { CompileErrors } from '../CompileErrors.js';
|
|
25
|
+
import { useState } from 'react';
|
|
26
|
+
const entries = [
|
|
27
|
+
{
|
|
28
|
+
status: 'compile-error',
|
|
29
|
+
file: '/cwd/src/foo.ts',
|
|
30
|
+
line: 10,
|
|
31
|
+
col: 5,
|
|
32
|
+
mutator: 'returnToNull',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
status: 'compile-error',
|
|
36
|
+
file: '/cwd/src/bar.ts',
|
|
37
|
+
line: 20,
|
|
38
|
+
col: 3,
|
|
39
|
+
mutator: 'returnFlipBool',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
describe('CompileErrors', () => {
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
mockExit.mockClear();
|
|
45
|
+
mockSetExpanded.mockClear();
|
|
46
|
+
inputHandler = undefined;
|
|
47
|
+
effectCallback = undefined;
|
|
48
|
+
vi.mocked(useState).mockImplementation(((init) => [
|
|
49
|
+
init,
|
|
50
|
+
mockSetExpanded,
|
|
51
|
+
]));
|
|
52
|
+
});
|
|
53
|
+
it('registers a useInput handler on render', () => {
|
|
54
|
+
CompileErrors({ entries, cwd: '/cwd' });
|
|
55
|
+
expect(inputHandler).toBeDefined();
|
|
56
|
+
});
|
|
57
|
+
it('calls setExpanded(true) when "e" is pressed', () => {
|
|
58
|
+
CompileErrors({ entries, cwd: '/cwd' });
|
|
59
|
+
inputHandler('e', { return: false });
|
|
60
|
+
expect(mockSetExpanded).toHaveBeenCalledWith(true);
|
|
61
|
+
});
|
|
62
|
+
it('calls exit() when return is pressed', () => {
|
|
63
|
+
CompileErrors({ entries, cwd: '/cwd' });
|
|
64
|
+
inputHandler('', { return: true });
|
|
65
|
+
expect(mockExit).toHaveBeenCalled();
|
|
66
|
+
});
|
|
67
|
+
it('calls exit() when "q" is pressed', () => {
|
|
68
|
+
CompileErrors({ entries, cwd: '/cwd' });
|
|
69
|
+
inputHandler('q', { return: false });
|
|
70
|
+
expect(mockExit).toHaveBeenCalled();
|
|
71
|
+
});
|
|
72
|
+
it('does not call exit() or setExpanded for other keys', () => {
|
|
73
|
+
CompileErrors({ entries, cwd: '/cwd' });
|
|
74
|
+
inputHandler('x', { return: false });
|
|
75
|
+
expect(mockExit).not.toHaveBeenCalled();
|
|
76
|
+
expect(mockSetExpanded).not.toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
it('registers a useEffect handler on render', () => {
|
|
79
|
+
CompileErrors({ entries, cwd: '/cwd' });
|
|
80
|
+
expect(effectCallback).toBeDefined();
|
|
81
|
+
});
|
|
82
|
+
it('useEffect calls exit() when expanded is true', () => {
|
|
83
|
+
vi.mocked(useState).mockReturnValueOnce([
|
|
84
|
+
true,
|
|
85
|
+
mockSetExpanded,
|
|
86
|
+
]);
|
|
87
|
+
CompileErrors({ entries, cwd: '/cwd' });
|
|
88
|
+
effectCallback();
|
|
89
|
+
expect(mockExit).toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
it('useEffect does not call exit() when expanded is false', () => {
|
|
92
|
+
CompileErrors({ entries, cwd: '/cwd' });
|
|
93
|
+
effectCallback();
|
|
94
|
+
expect(mockExit).not.toHaveBeenCalled();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -18,13 +18,16 @@ describe('summary', () => {
|
|
|
18
18
|
a: makeEntry({ status: 'killed' }),
|
|
19
19
|
b: makeEntry({ status: 'escaped' }),
|
|
20
20
|
c: makeEntry({ status: 'skipped' }),
|
|
21
|
+
d: makeEntry({ status: 'timeout' }),
|
|
21
22
|
};
|
|
22
23
|
const s = computeSummary(cache);
|
|
23
24
|
expect(s).toEqual({
|
|
24
|
-
total:
|
|
25
|
+
total: 4,
|
|
25
26
|
killed: 1,
|
|
26
27
|
escaped: 1,
|
|
27
28
|
skipped: 1,
|
|
29
|
+
timeouts: 1,
|
|
30
|
+
compileErrors: 0,
|
|
28
31
|
evaluated: 2,
|
|
29
32
|
killRate: 50,
|
|
30
33
|
});
|
|
@@ -43,6 +46,40 @@ describe('summary', () => {
|
|
|
43
46
|
expect(lines.some((l) => l.includes('Duration: 1.50s'))).toBe(true);
|
|
44
47
|
logSpy.mockRestore();
|
|
45
48
|
});
|
|
49
|
+
it('prints Timed Out Mutants section when timeouts exist', () => {
|
|
50
|
+
const cache = {
|
|
51
|
+
a: makeEntry({ status: 'timeout', file: '/tmp/a.ts', mutator: 'flip' }),
|
|
52
|
+
};
|
|
53
|
+
const summary = computeSummary(cache);
|
|
54
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
55
|
+
printSummary(summary, cache);
|
|
56
|
+
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
57
|
+
expect(lines.some((l) => l.includes('Timed Out Mutants'))).toBe(true);
|
|
58
|
+
logSpy.mockRestore();
|
|
59
|
+
});
|
|
60
|
+
it('shows Timeouts count in stat line when timeouts > 0', () => {
|
|
61
|
+
const cache = {
|
|
62
|
+
a: makeEntry({ status: 'timeout', file: '/tmp/a.ts' }),
|
|
63
|
+
b: makeEntry({ status: 'killed', file: '/tmp/b.ts' }),
|
|
64
|
+
};
|
|
65
|
+
const summary = computeSummary(cache);
|
|
66
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
67
|
+
printSummary(summary, cache);
|
|
68
|
+
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
69
|
+
expect(lines.some((l) => l.includes('Timeouts: 1'))).toBe(true);
|
|
70
|
+
logSpy.mockRestore();
|
|
71
|
+
});
|
|
72
|
+
it('shows Timeouts: 0 in stat line when timeouts is zero', () => {
|
|
73
|
+
const cache = {
|
|
74
|
+
a: makeEntry({ status: 'killed', file: '/tmp/a.ts' }),
|
|
75
|
+
};
|
|
76
|
+
const summary = computeSummary(cache);
|
|
77
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
78
|
+
printSummary(summary, cache);
|
|
79
|
+
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
80
|
+
expect(lines.some((l) => l.includes('Timeouts: 0'))).toBe(true);
|
|
81
|
+
logSpy.mockRestore();
|
|
82
|
+
});
|
|
46
83
|
it('prints diff lines for escaped mutant with snippets', () => {
|
|
47
84
|
const cache = {
|
|
48
85
|
a: makeEntry({
|
|
@@ -139,6 +176,51 @@ describe('summary', () => {
|
|
|
139
176
|
expect('originalSnippet' in report.mutants[0]).toBe(false);
|
|
140
177
|
expect('coveringTests' in report.mutants[0]).toBe(false);
|
|
141
178
|
});
|
|
179
|
+
it('prints compile error mutants section by default', () => {
|
|
180
|
+
const cache = {
|
|
181
|
+
a: makeEntry({
|
|
182
|
+
status: 'compile-error',
|
|
183
|
+
file: '/tmp/a.ts',
|
|
184
|
+
mutator: 'returnToNull',
|
|
185
|
+
}),
|
|
186
|
+
};
|
|
187
|
+
const summary = computeSummary(cache);
|
|
188
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
189
|
+
printSummary(summary, cache);
|
|
190
|
+
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
191
|
+
expect(lines.some((l) => l.includes('Compile Error Mutants'))).toBe(true);
|
|
192
|
+
logSpy.mockRestore();
|
|
193
|
+
});
|
|
194
|
+
it('skips compile error section when skipCompileErrors is true', () => {
|
|
195
|
+
const cache = {
|
|
196
|
+
a: makeEntry({
|
|
197
|
+
status: 'compile-error',
|
|
198
|
+
file: '/tmp/a.ts',
|
|
199
|
+
mutator: 'returnToNull',
|
|
200
|
+
}),
|
|
201
|
+
};
|
|
202
|
+
const summary = computeSummary(cache);
|
|
203
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
204
|
+
printSummary(summary, cache, undefined, { skipCompileErrors: true });
|
|
205
|
+
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
206
|
+
expect(lines.some((l) => l.includes('Compile Error Mutants'))).toBe(false);
|
|
207
|
+
logSpy.mockRestore();
|
|
208
|
+
});
|
|
209
|
+
it('shows compile error section when skipCompileErrors is false', () => {
|
|
210
|
+
const cache = {
|
|
211
|
+
a: makeEntry({
|
|
212
|
+
status: 'compile-error',
|
|
213
|
+
file: '/tmp/a.ts',
|
|
214
|
+
mutator: 'returnToNull',
|
|
215
|
+
}),
|
|
216
|
+
};
|
|
217
|
+
const summary = computeSummary(cache);
|
|
218
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
219
|
+
printSummary(summary, cache, undefined, { skipCompileErrors: false });
|
|
220
|
+
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
221
|
+
expect(lines.some((l) => l.includes('Compile Error Mutants'))).toBe(true);
|
|
222
|
+
logSpy.mockRestore();
|
|
223
|
+
});
|
|
142
224
|
it('summarise returns summary and prints', () => {
|
|
143
225
|
const cache = { a: makeEntry({ status: 'killed' }) };
|
|
144
226
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
package/dist/utils/summary.d.ts
CHANGED
|
@@ -4,11 +4,15 @@ export interface Summary {
|
|
|
4
4
|
readonly killed: number;
|
|
5
5
|
readonly escaped: number;
|
|
6
6
|
readonly skipped: number;
|
|
7
|
+
readonly timeouts: number;
|
|
8
|
+
readonly compileErrors: number;
|
|
7
9
|
readonly evaluated: number;
|
|
8
10
|
readonly killRate: number;
|
|
9
11
|
}
|
|
10
12
|
export declare function computeSummary(cache: Readonly<Record<string, MutantCacheEntry>>): Summary;
|
|
11
|
-
export declare function printSummary(summary: Summary, cache?: Readonly<Record<string, MutantCacheEntry>>, durationMs?: number
|
|
13
|
+
export declare function printSummary(summary: Summary, cache?: Readonly<Record<string, MutantCacheEntry>>, durationMs?: number, opts?: {
|
|
14
|
+
skipCompileErrors?: boolean;
|
|
15
|
+
}): void;
|
|
12
16
|
export interface JsonMutant {
|
|
13
17
|
readonly file: string;
|
|
14
18
|
readonly line: number;
|
package/dist/utils/summary.js
CHANGED
|
@@ -6,18 +6,33 @@ export function computeSummary(cache) {
|
|
|
6
6
|
let killed = 0;
|
|
7
7
|
let escaped = 0;
|
|
8
8
|
let skipped = 0;
|
|
9
|
+
let timeouts = 0;
|
|
10
|
+
let compileErrors = 0;
|
|
9
11
|
for (const entry of allEntries) {
|
|
10
12
|
if (entry.status === 'killed')
|
|
11
13
|
killed++;
|
|
12
14
|
else if (entry.status === 'escaped')
|
|
13
15
|
escaped++;
|
|
16
|
+
else if (entry.status === 'compile-error')
|
|
17
|
+
compileErrors++;
|
|
18
|
+
else if (entry.status === 'timeout')
|
|
19
|
+
timeouts++;
|
|
14
20
|
else
|
|
15
21
|
skipped++;
|
|
16
22
|
}
|
|
17
23
|
const evaluated = killed + escaped;
|
|
18
24
|
const total = allEntries.length;
|
|
19
25
|
const killRate = evaluated === 0 ? 0 : (killed / evaluated) * 100;
|
|
20
|
-
return {
|
|
26
|
+
return {
|
|
27
|
+
total,
|
|
28
|
+
killed,
|
|
29
|
+
escaped,
|
|
30
|
+
skipped,
|
|
31
|
+
timeouts,
|
|
32
|
+
compileErrors,
|
|
33
|
+
evaluated,
|
|
34
|
+
killRate,
|
|
35
|
+
};
|
|
21
36
|
}
|
|
22
37
|
function formatDuration(ms) {
|
|
23
38
|
if (ms < 1000)
|
|
@@ -29,7 +44,7 @@ function formatDuration(ms) {
|
|
|
29
44
|
const remainingSeconds = seconds % 60;
|
|
30
45
|
return `${minutes}m ${remainingSeconds.toFixed(1)}s`;
|
|
31
46
|
}
|
|
32
|
-
export function printSummary(summary, cache, durationMs) {
|
|
47
|
+
export function printSummary(summary, cache, durationMs, opts) {
|
|
33
48
|
console.log('\n' + chalk.dim(SEPARATOR));
|
|
34
49
|
console.log(chalk.bold(' Mutineer Test Suite Summary'));
|
|
35
50
|
console.log(chalk.dim(SEPARATOR));
|
|
@@ -57,6 +72,8 @@ export function printSummary(summary, cache, durationMs) {
|
|
|
57
72
|
const entriesByStatus = {
|
|
58
73
|
killed: [],
|
|
59
74
|
escaped: [],
|
|
75
|
+
compileErrors: [],
|
|
76
|
+
timeouts: [],
|
|
60
77
|
skipped: [],
|
|
61
78
|
};
|
|
62
79
|
for (const entry of allEntries) {
|
|
@@ -64,6 +81,10 @@ export function printSummary(summary, cache, durationMs) {
|
|
|
64
81
|
entriesByStatus.killed.push(entry);
|
|
65
82
|
else if (entry.status === 'escaped')
|
|
66
83
|
entriesByStatus.escaped.push(entry);
|
|
84
|
+
else if (entry.status === 'compile-error')
|
|
85
|
+
entriesByStatus.compileErrors.push(entry);
|
|
86
|
+
else if (entry.status === 'timeout')
|
|
87
|
+
entriesByStatus.timeouts.push(entry);
|
|
67
88
|
else
|
|
68
89
|
entriesByStatus.skipped.push(entry);
|
|
69
90
|
}
|
|
@@ -92,13 +113,27 @@ export function printSummary(summary, cache, durationMs) {
|
|
|
92
113
|
}
|
|
93
114
|
}
|
|
94
115
|
}
|
|
116
|
+
if (entriesByStatus.compileErrors.length && !opts?.skipCompileErrors) {
|
|
117
|
+
console.log('\n' + chalk.dim('Compile Error Mutants (type-filtered):'));
|
|
118
|
+
for (const entry of entriesByStatus.compileErrors)
|
|
119
|
+
console.log(' ' + formatRow(entry));
|
|
120
|
+
}
|
|
121
|
+
if (entriesByStatus.timeouts.length) {
|
|
122
|
+
console.log('\n' + chalk.yellow.bold('Timed Out Mutants:'));
|
|
123
|
+
for (const entry of entriesByStatus.timeouts)
|
|
124
|
+
console.log(' ' + formatRow(entry));
|
|
125
|
+
}
|
|
95
126
|
if (entriesByStatus.skipped.length) {
|
|
96
127
|
console.log('\n' + chalk.dim('Skipped Mutants:'));
|
|
97
128
|
for (const entry of entriesByStatus.skipped)
|
|
98
129
|
console.log(' ' + formatRow(entry));
|
|
99
130
|
}
|
|
100
131
|
console.log('\n' + chalk.dim(SEPARATOR));
|
|
101
|
-
|
|
132
|
+
const compileErrorStr = summary.compileErrors > 0
|
|
133
|
+
? `, ${chalk.dim(`Compile Errors: ${summary.compileErrors}`)}`
|
|
134
|
+
: '';
|
|
135
|
+
const timeoutStr = `, ${chalk.yellow(`Timeouts: ${summary.timeouts}`)}`;
|
|
136
|
+
console.log(`Total: ${summary.total} \u2014 ${chalk.green(`Killed: ${summary.killed}`)}, ${chalk.red(`Escaped: ${summary.escaped}`)}, ${chalk.dim(`Skipped: ${summary.skipped}`)}${timeoutStr}${compileErrorStr}`);
|
|
102
137
|
if (summary.evaluated === 0) {
|
|
103
138
|
console.log(`Kill rate: ${chalk.dim('0.00% (no mutants executed)')}`);
|
|
104
139
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutineerjs/mutineer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "A fast, targeted mutation testing framework for JavaScript and TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -98,7 +98,6 @@
|
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
|
101
|
-
"@vitest/coverage-v8": "^4.0.15",
|
|
102
101
|
"@commitlint/cli": "^20.4.3",
|
|
103
102
|
"@commitlint/config-conventional": "^20.4.3",
|
|
104
103
|
"@types/babel__traverse": "^7.28.0",
|
|
@@ -106,6 +105,7 @@
|
|
|
106
105
|
"@types/react": "^19.2.14",
|
|
107
106
|
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
108
107
|
"@typescript-eslint/parser": "^8.47.0",
|
|
108
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
109
109
|
"eslint": "^10.0.3",
|
|
110
110
|
"husky": "^9.1.7",
|
|
111
111
|
"jsdom": "^28.1.0",
|