-
Notifications
You must be signed in to change notification settings - Fork 241
/
verify.js
121 lines (107 loc) · 4.4 KB
/
verify.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { promises as fsPromises } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { Stryker } from '@stryker-mutator/core';
import { expect } from 'chai';
import { PlanKind } from '@stryker-mutator/api/core';
import { MutationRunPlanReporter } from './mutation-run-plan-reporter.js';
import '../../../helpers.js';
const incrementalFile = new URL('../reports/stryker-incremental.json', import.meta.url);
describe('incremental', () => {
/**
* @type {import('@stryker-mutator/api/core').PartialStrykerOptions}
*/
let strykerOptions;
beforeEach(async () => {
await fsPromises.rm(incrementalFile, { force: true });
/**
* @type {import('@stryker-mutator/api/core').LogLevel}
*/
strykerOptions = {
incremental: true,
concurrency: 1,
plugins: ['./verify/mutation-run-plan-reporter.js'],
reporters: ['mutation-run-plan', 'html'],
};
await changeFiles('original'); // change the files back to there original state
});
afterEach(async () => {
await changeFiles('original'); // change the files back to there original state
});
const reuseCountExpectation = Object.freeze({
// This is the best result, we should strive to push each test runner to this
withFullTestResults: 4,
// We know which test files are changed and assume each test in that file changed
withoutTestLocations: 2,
// Don't know from which test files the tests originated
withoutTestFiles: 7,
});
/**
* @type {Array<[string, number, import('@stryker-mutator/api/core').PartialStrykerOptions?, boolean?]>}
*/
const tests = [
['cucumber', reuseCountExpectation.withFullTestResults],
['jest', reuseCountExpectation.withFullTestResults, { testRunnerNodeArgs: ['--experimental-vm-modules'], tempDirName: 'stryker-tmp' }],
['mocha', reuseCountExpectation.withoutTestLocations],
['karma', reuseCountExpectation.withoutTestFiles, { karma: { configFile: 'karma.conf.cjs' } }],
['jasmine', reuseCountExpectation.withoutTestFiles, { jasmineConfigFile: 'jasmine.json' }],
['command', reuseCountExpectation.withoutTestFiles, { commandRunner: { command: 'npm run test:mocha' } }],
];
tests.forEach(([testRunner, expectedReuseCount, additionalOptions, focus]) => {
(focus ? it.only : it)(`should reuse expected mutant results for ${testRunner}`, async () => {
// Arrange;
strykerOptions.testRunner = testRunner;
if (testRunner !== 'command') {
strykerOptions.plugins.push(`@stryker-mutator/${testRunner}-runner`);
}
const stryker = new Stryker({
...strykerOptions,
...additionalOptions,
});
await stryker.runMutationTest();
await fsPromises.access(incrementalFile);
await changeFiles('changed');
// Act
await stryker.runMutationTest();
// Assert
let actualReuseCount = 0;
const normalizedTestPlans = MutationRunPlanReporter.instance.event.mutantPlans.map((plan) => {
// Remove all flaky attributes
const { id, fileName, statusReason, ...mutant } = plan.mutant;
if (plan.plan === PlanKind.EarlyResult) {
actualReuseCount++;
}
return {
plan: plan.plan,
mutant: {
...mutant,
killedBy: mutant.killedBy?.map((name) => name.replace(/\\/g, '/')),
coveredBy: mutant.coveredBy?.map((name) => name.replace(/\\/g, '/')),
},
fileName: path.relative(fileURLToPath(new URL('../', import.meta.url)), fileName).replace(/\\/g, '/'),
};
});
expect(actualReuseCount).eq(expectedReuseCount);
expect(normalizedTestPlans).matchSnapshot();
});
});
/**
* @param {'changed' | 'original'} blueprint
* @param location
*/
async function changeFiles(blueprint, location = new URL('../', import.meta.url)) {
const ext = `.${blueprint}`;
const entries = await fsPromises.readdir(location, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory() && entry.name !== 'node_modules') {
const entryLoc = new URL(`${entry.name}/`, location);
await changeFiles(blueprint, entryLoc);
}
if (entry.isFile() && entry.name.endsWith(ext)) {
const entryLoc = new URL(entry.name, location);
const newUrl = new URL(entry.name.substring(0, entry.name.length - ext.length), location);
await fsPromises.copyFile(entryLoc, newUrl);
}
}
}
});