@mutineerjs/mutineer 0.9.0 → 0.11.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 +52 -47
- package/dist/__tests__/index.spec.js +8 -0
- package/dist/bin/__tests__/mutineer.spec.js +7 -7
- package/dist/bin/mutineer.d.ts +1 -1
- package/dist/bin/mutineer.js +7 -4
- package/dist/core/__tests__/schemata.spec.js +62 -0
- package/dist/core/__tests__/sfc.spec.js +41 -1
- package/dist/core/schemata.js +15 -21
- package/dist/core/sfc.js +0 -4
- package/dist/core/variant-utils.js +0 -4
- package/dist/mutators/__tests__/utils.spec.js +65 -1
- package/dist/mutators/operator.js +13 -27
- package/dist/mutators/return-value.js +3 -7
- package/dist/mutators/utils.d.ts +2 -2
- package/dist/mutators/utils.js +59 -96
- package/dist/runner/__tests__/args.spec.js +8 -4
- package/dist/runner/__tests__/cache.spec.js +24 -0
- package/dist/runner/__tests__/changed.spec.js +75 -0
- package/dist/runner/__tests__/config.spec.js +50 -1
- package/dist/runner/__tests__/coverage-resolver.spec.js +88 -1
- package/dist/runner/__tests__/discover.spec.js +179 -0
- package/dist/runner/__tests__/orchestrator.spec.js +336 -11
- package/dist/runner/__tests__/pool-executor.spec.js +77 -0
- package/dist/runner/__tests__/ts-checker-worker.spec.d.ts +1 -0
- package/dist/runner/__tests__/ts-checker-worker.spec.js +66 -0
- package/dist/runner/__tests__/ts-checker.spec.js +89 -2
- package/dist/runner/args.d.ts +1 -1
- package/dist/runner/args.js +2 -2
- package/dist/runner/config.js +3 -4
- package/dist/runner/coverage-resolver.js +2 -1
- package/dist/runner/discover.js +2 -2
- package/dist/runner/jest/__tests__/adapter.spec.js +169 -0
- package/dist/runner/jest/__tests__/pool.spec.js +223 -1
- package/dist/runner/jest/adapter.js +3 -45
- package/dist/runner/jest/pool.js +4 -10
- package/dist/runner/jest/worker-runtime.js +2 -1
- package/dist/runner/orchestrator.js +8 -7
- package/dist/runner/pool-executor.js +7 -12
- package/dist/runner/shared/__tests__/strip-mutineer-args.spec.d.ts +1 -0
- package/dist/runner/shared/__tests__/strip-mutineer-args.spec.js +104 -0
- package/dist/runner/shared/__tests__/worker-script.spec.d.ts +1 -0
- package/dist/runner/shared/__tests__/worker-script.spec.js +32 -0
- package/dist/runner/shared/index.d.ts +4 -0
- package/dist/runner/shared/index.js +2 -0
- package/dist/runner/shared/pending-task.d.ts +9 -0
- package/dist/runner/shared/pending-task.js +1 -0
- package/dist/runner/shared/strip-mutineer-args.d.ts +11 -0
- package/dist/runner/shared/strip-mutineer-args.js +47 -0
- package/dist/runner/shared/worker-script.d.ts +5 -0
- package/dist/runner/shared/worker-script.js +12 -0
- package/dist/runner/ts-checker-worker.d.ts +10 -1
- package/dist/runner/ts-checker-worker.js +27 -25
- package/dist/runner/ts-checker.d.ts +6 -0
- package/dist/runner/ts-checker.js +1 -1
- package/dist/runner/vitest/__tests__/adapter.spec.js +294 -0
- package/dist/runner/vitest/__tests__/plugin.spec.js +28 -1
- package/dist/runner/vitest/__tests__/pool.spec.js +711 -0
- package/dist/runner/vitest/__tests__/redirect-loader.spec.js +116 -1
- package/dist/runner/vitest/__tests__/worker-runtime.spec.js +81 -0
- package/dist/runner/vitest/adapter.js +14 -46
- package/dist/runner/vitest/plugin.js +1 -7
- package/dist/runner/vitest/pool.js +6 -19
- package/dist/runner/vitest/redirect-loader.js +3 -1
- package/dist/runner/vitest/worker-runtime.js +16 -1
- package/dist/runner/vitest/worker.mjs +1 -0
- package/dist/types/config.d.ts +2 -2
- package/dist/types/mutant.d.ts +3 -0
- package/dist/utils/__tests__/PoolSpinner.spec.d.ts +1 -0
- package/dist/utils/__tests__/PoolSpinner.spec.js +15 -0
- package/dist/utils/__tests__/coverage.spec.js +89 -0
- package/dist/utils/__tests__/logger.spec.js +9 -0
- package/dist/utils/__tests__/progress.spec.js +38 -0
- package/dist/utils/__tests__/summary.spec.js +70 -31
- package/dist/utils/coverage.js +3 -4
- package/dist/utils/errors.d.ts +4 -0
- package/dist/utils/errors.js +6 -0
- package/dist/utils/summary.d.ts +2 -3
- package/dist/utils/summary.js +5 -6
- package/package.json +1 -1
- package/dist/utils/CompileErrors.d.ts +0 -7
- package/dist/utils/CompileErrors.js +0 -24
- package/dist/utils/__tests__/CompileErrors.spec.js +0 -96
- /package/dist/{utils/__tests__/CompileErrors.spec.d.ts → __tests__/index.spec.d.ts} +0 -0
|
@@ -123,6 +123,42 @@ describe('summary', () => {
|
|
|
123
123
|
expect(lines.some((l) => l.includes('foo.spec.ts'))).toBe(true);
|
|
124
124
|
logSpy.mockRestore();
|
|
125
125
|
});
|
|
126
|
+
it('handles printSummary with no cache argument when total > 0', () => {
|
|
127
|
+
const summary = {
|
|
128
|
+
total: 1,
|
|
129
|
+
killed: 1,
|
|
130
|
+
escaped: 0,
|
|
131
|
+
skipped: 0,
|
|
132
|
+
timeouts: 0,
|
|
133
|
+
compileErrors: 0,
|
|
134
|
+
evaluated: 1,
|
|
135
|
+
killRate: 100,
|
|
136
|
+
};
|
|
137
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
138
|
+
// No cache passed: allEntries=[], maxPathLen=25 (|| 25), maxMutatorLen=10 (|| 10)
|
|
139
|
+
printSummary(summary);
|
|
140
|
+
expect(logSpy).toHaveBeenCalled();
|
|
141
|
+
logSpy.mockRestore();
|
|
142
|
+
});
|
|
143
|
+
it('buildJsonReport includes passingTests when present', () => {
|
|
144
|
+
const cache = {
|
|
145
|
+
a: makeEntry({
|
|
146
|
+
status: 'escaped',
|
|
147
|
+
file: '/tmp/a.ts',
|
|
148
|
+
mutator: 'flip',
|
|
149
|
+
passingTests: ['Suite > test one'],
|
|
150
|
+
}),
|
|
151
|
+
};
|
|
152
|
+
const summary = computeSummary(cache);
|
|
153
|
+
const report = buildJsonReport(summary, cache);
|
|
154
|
+
expect(report.mutants[0].passingTests).toEqual(['Suite > test one']);
|
|
155
|
+
});
|
|
156
|
+
it('buildJsonReport omits passingTests when absent', () => {
|
|
157
|
+
const cache = { a: makeEntry({ status: 'escaped' }) };
|
|
158
|
+
const summary = computeSummary(cache);
|
|
159
|
+
const report = buildJsonReport(summary, cache);
|
|
160
|
+
expect('passingTests' in report.mutants[0]).toBe(false);
|
|
161
|
+
});
|
|
126
162
|
it('does not print covering tests when array is absent', () => {
|
|
127
163
|
const cache = {
|
|
128
164
|
a: makeEntry({ status: 'escaped' }),
|
|
@@ -176,57 +212,60 @@ describe('summary', () => {
|
|
|
176
212
|
expect('originalSnippet' in report.mutants[0]).toBe(false);
|
|
177
213
|
expect('coveringTests' in report.mutants[0]).toBe(false);
|
|
178
214
|
});
|
|
179
|
-
it('prints
|
|
180
|
-
const cache = {
|
|
181
|
-
a: makeEntry({
|
|
182
|
-
status: 'compile-error',
|
|
183
|
-
file: '/tmp/a.ts',
|
|
184
|
-
mutator: 'returnToNull',
|
|
185
|
-
}),
|
|
186
|
-
};
|
|
215
|
+
it('prints report hint line', () => {
|
|
216
|
+
const cache = { a: makeEntry({ status: 'killed' }) };
|
|
187
217
|
const summary = computeSummary(cache);
|
|
188
218
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
189
219
|
printSummary(summary, cache);
|
|
190
220
|
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
191
|
-
expect(lines.some((l) => l.includes('
|
|
221
|
+
expect(lines.some((l) => l.includes('Run with --report json to see full mutation details.'))).toBe(true);
|
|
222
|
+
logSpy.mockRestore();
|
|
223
|
+
});
|
|
224
|
+
it('summarise returns summary and prints', () => {
|
|
225
|
+
const cache = { a: makeEntry({ status: 'killed' }) };
|
|
226
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
227
|
+
const s = summarise(cache);
|
|
228
|
+
expect(s.total).toBe(1);
|
|
229
|
+
expect(logSpy).toHaveBeenCalled();
|
|
192
230
|
logSpy.mockRestore();
|
|
193
231
|
});
|
|
194
|
-
it('
|
|
232
|
+
it('counts compile-error status in compileErrors field', () => {
|
|
233
|
+
const cache = { a: makeEntry({ status: 'compile-error' }) };
|
|
234
|
+
const s = computeSummary(cache);
|
|
235
|
+
expect(s.compileErrors).toBe(1);
|
|
236
|
+
expect(s.killed).toBe(0);
|
|
237
|
+
});
|
|
238
|
+
it('categorizes compile-error entries without throwing in printSummary', () => {
|
|
195
239
|
const cache = {
|
|
196
|
-
a: makeEntry({
|
|
197
|
-
status: 'compile-error',
|
|
198
|
-
file: '/tmp/a.ts',
|
|
199
|
-
mutator: 'returnToNull',
|
|
200
|
-
}),
|
|
240
|
+
a: makeEntry({ status: 'compile-error', file: '/tmp/a.ts' }),
|
|
201
241
|
};
|
|
202
242
|
const summary = computeSummary(cache);
|
|
203
243
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
204
|
-
printSummary(summary, cache
|
|
244
|
+
printSummary(summary, cache);
|
|
245
|
+
expect(summary.compileErrors).toBe(1);
|
|
246
|
+
logSpy.mockRestore();
|
|
247
|
+
});
|
|
248
|
+
it('formats duration in minutes when duration >= 60s', () => {
|
|
249
|
+
const cache = { a: makeEntry({ status: 'killed' }) };
|
|
250
|
+
const summary = computeSummary(cache);
|
|
251
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
252
|
+
printSummary(summary, cache, 90000); // 90 seconds = 1m 30.0s
|
|
205
253
|
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
206
|
-
expect(lines.some((l) => l.includes('
|
|
254
|
+
expect(lines.some((l) => l.includes('1m 30.0s'))).toBe(true);
|
|
207
255
|
logSpy.mockRestore();
|
|
208
256
|
});
|
|
209
|
-
it('
|
|
257
|
+
it('prints +N more when escaped mutant has more than 2 covering tests', () => {
|
|
210
258
|
const cache = {
|
|
211
259
|
a: makeEntry({
|
|
212
|
-
status: '
|
|
213
|
-
|
|
214
|
-
mutator: 'returnToNull',
|
|
260
|
+
status: 'escaped',
|
|
261
|
+
coveringTests: ['/t1.spec.ts', '/t2.spec.ts', '/t3.spec.ts'],
|
|
215
262
|
}),
|
|
216
263
|
};
|
|
217
264
|
const summary = computeSummary(cache);
|
|
218
265
|
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
219
|
-
printSummary(summary, cache
|
|
266
|
+
printSummary(summary, cache);
|
|
220
267
|
const lines = logSpy.mock.calls.map((c) => stripAnsi(c.join(' ')));
|
|
221
|
-
expect(lines.some((l) => l.includes('
|
|
222
|
-
logSpy.mockRestore();
|
|
223
|
-
});
|
|
224
|
-
it('summarise returns summary and prints', () => {
|
|
225
|
-
const cache = { a: makeEntry({ status: 'killed' }) };
|
|
226
|
-
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
227
|
-
const s = summarise(cache);
|
|
228
|
-
expect(s.total).toBe(1);
|
|
229
|
-
expect(logSpy).toHaveBeenCalled();
|
|
268
|
+
expect(lines.some((l) => l.includes('+1 more'))).toBe(true);
|
|
230
269
|
logSpy.mockRestore();
|
|
231
270
|
});
|
|
232
271
|
});
|
package/dist/utils/coverage.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { toErrorMessage } from './errors.js';
|
|
3
4
|
/**
|
|
4
5
|
* Load and parse Istanbul-format coverage JSON file.
|
|
5
6
|
* Supports both coverage-final.json (from Istanbul) and Vitest's coverage output.
|
|
@@ -17,16 +18,14 @@ export async function loadCoverageData(coverageFile, cwd) {
|
|
|
17
18
|
raw = await fs.readFile(absPath, 'utf8');
|
|
18
19
|
}
|
|
19
20
|
catch (err) {
|
|
20
|
-
|
|
21
|
-
throw new Error(`Failed to read coverage file "${absPath}": ${msg}`);
|
|
21
|
+
throw new Error(`Failed to read coverage file "${absPath}": ${toErrorMessage(err)}`);
|
|
22
22
|
}
|
|
23
23
|
let data;
|
|
24
24
|
try {
|
|
25
25
|
data = JSON.parse(raw);
|
|
26
26
|
}
|
|
27
27
|
catch (err) {
|
|
28
|
-
|
|
29
|
-
throw new Error(`Failed to parse coverage file "${absPath}" as JSON: ${msg}`);
|
|
28
|
+
throw new Error(`Failed to parse coverage file "${absPath}" as JSON: ${toErrorMessage(err)}`);
|
|
30
29
|
}
|
|
31
30
|
const coveredLines = new Map();
|
|
32
31
|
for (const [filePath, fileCoverage] of Object.entries(data)) {
|
package/dist/utils/summary.d.ts
CHANGED
|
@@ -10,9 +10,7 @@ export interface Summary {
|
|
|
10
10
|
readonly killRate: number;
|
|
11
11
|
}
|
|
12
12
|
export declare function computeSummary(cache: Readonly<Record<string, MutantCacheEntry>>): Summary;
|
|
13
|
-
export declare function printSummary(summary: Summary, cache?: Readonly<Record<string, MutantCacheEntry>>, durationMs?: number
|
|
14
|
-
skipCompileErrors?: boolean;
|
|
15
|
-
}): void;
|
|
13
|
+
export declare function printSummary(summary: Summary, cache?: Readonly<Record<string, MutantCacheEntry>>, durationMs?: number): void;
|
|
16
14
|
export interface JsonMutant {
|
|
17
15
|
readonly file: string;
|
|
18
16
|
readonly line: number;
|
|
@@ -22,6 +20,7 @@ export interface JsonMutant {
|
|
|
22
20
|
readonly originalSnippet?: string;
|
|
23
21
|
readonly mutatedSnippet?: string;
|
|
24
22
|
readonly coveringTests?: readonly string[];
|
|
23
|
+
readonly passingTests?: readonly string[];
|
|
25
24
|
}
|
|
26
25
|
export interface JsonReport {
|
|
27
26
|
readonly schemaVersion: 1;
|
package/dist/utils/summary.js
CHANGED
|
@@ -44,7 +44,7 @@ function formatDuration(ms) {
|
|
|
44
44
|
const remainingSeconds = seconds % 60;
|
|
45
45
|
return `${minutes}m ${remainingSeconds.toFixed(1)}s`;
|
|
46
46
|
}
|
|
47
|
-
export function printSummary(summary, cache, durationMs
|
|
47
|
+
export function printSummary(summary, cache, durationMs) {
|
|
48
48
|
console.log('\n' + chalk.dim(SEPARATOR));
|
|
49
49
|
console.log(chalk.bold(' Mutineer Test Suite Summary'));
|
|
50
50
|
console.log(chalk.dim(SEPARATOR));
|
|
@@ -113,11 +113,6 @@ export function printSummary(summary, cache, durationMs, opts) {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
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
116
|
if (entriesByStatus.timeouts.length) {
|
|
122
117
|
console.log('\n' + chalk.yellow.bold('Timed Out Mutants:'));
|
|
123
118
|
for (const entry of entriesByStatus.timeouts)
|
|
@@ -148,6 +143,7 @@ export function printSummary(summary, cache, durationMs, opts) {
|
|
|
148
143
|
if (durationMs !== undefined) {
|
|
149
144
|
console.log(`Duration: ${chalk.cyan(formatDuration(durationMs))}`);
|
|
150
145
|
}
|
|
146
|
+
console.log(chalk.dim('Run with --report json to see full mutation details.'));
|
|
151
147
|
console.log(chalk.dim(SEPARATOR) + '\n');
|
|
152
148
|
}
|
|
153
149
|
export function buildJsonReport(summary, cache, durationMs) {
|
|
@@ -166,6 +162,9 @@ export function buildJsonReport(summary, cache, durationMs) {
|
|
|
166
162
|
...(entry.coveringTests !== undefined && {
|
|
167
163
|
coveringTests: entry.coveringTests,
|
|
168
164
|
}),
|
|
165
|
+
...(entry.passingTests !== undefined && {
|
|
166
|
+
passingTests: entry.passingTests,
|
|
167
|
+
}),
|
|
169
168
|
}));
|
|
170
169
|
return {
|
|
171
170
|
schemaVersion: 1,
|
package/package.json
CHANGED
|
@@ -1,24 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
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
|
-
});
|
|
File without changes
|