-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
124 lines (109 loc) · 3.64 KB
/
index.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
122
123
124
'use strict';
const myJest = require('jest');
const jestJunit = require('jest-junit');
const {
readFileSync, renameSync, existsSync, mkdirSync,
} = require('fs');
const { isKnownToBeFlaky, mergeResults } = require('./helpers');
/**
* Custom jest reporter to rerun known flaky tests and execute junit on final result.
*/
class JestFlakyRetryReporter {
/**
* Constructor of this jest test reporter.
*
* @param {object} globalConfig - The global config of jest.
* @param {object} options - The options given to this reporter.
*/
constructor(globalConfig, options) {
this.globalConfig = globalConfig;
this.options = options;
this.retryTestCases = [];
this.retryTestSuites = [];
this.shouldFail = false;
}
/**
* Called by jest before test execution.
*/
onRunStart() {
const configFileName = this.options.configFile;
// eslint-disable-next-line no-console
console.log('Loading list of known flaky tests from', configFileName);
this.knownFlakyTestCases = JSON.parse(readFileSync(configFileName));
// eslint-disable-next-line no-console
console.log(this.knownFlakyTestCases);
}
/**
* Called by jest after test suite execution.
*
* @param {object} test - Jest test context.
* @param {object} testSuiteResult - The result of the suite execution.
*/
onTestResult(test, testSuiteResult) {
const relativeTestFilePath = testSuiteResult.testFilePath.slice(
process.cwd().length + 1,
);
const retryTestCases = testSuiteResult.testResults.filter(
(testCaseResult) => testCaseResult.status === 'failed'
&& isKnownToBeFlaky(
this.knownFlakyTestCases,
relativeTestFilePath,
testCaseResult,
),
);
if (retryTestCases.length) {
this.retryTestSuites.push(testSuiteResult.testFilePath);
this.retryTestCases.push(...retryTestCases);
}
}
/**
* Called by jest after test execution.
*
* @param {object} contexts - Jest context.
* @param {object} results - The results of the test execution.
*/
async onRunComplete(contexts, results) {
let finalResults = results;
if (this.retryTestCases.length) {
const retryFullNames = this.retryTestCases.map((test) => test.fullName);
// eslint-disable-next-line no-console
console.log('Retrying test cases: ', retryFullNames);
const jestConfig = {
testMatch: this.retryTestSuites,
testNamePattern: retryFullNames.join('|'),
rootDir: this.globalConfig.rootDir,
};
const { results: newResults } = await myJest.runCLI(
{
config: JSON.stringify(jestConfig),
},
[process.cwd()],
);
finalResults = mergeResults(results, newResults);
}
finalResults.success = finalResults.numFailedTestSuites === 0;
this.shouldFail = !finalResults.success;
// Note: Direct processor call of jest-junit is deprecated,
// since testResultsProcessor support in jest is deprecated
jestJunit(finalResults);
const outputDir = this.options.junitOutputDirectory;
if (!existsSync(outputDir)) {
mkdirSync(outputDir, { recursive: true });
}
renameSync('junit.xml', `${outputDir}/junit.xml`);
}
/**
* Called by jest after test execution. Check if test execution shall be
* considered as successful. If unsuccessful, this forces jest to return
* with an error code.
*
* @returns {boolean} Whether jest should consider the test execution as succeeded.
*/
getLastError() {
if (this.shouldFail) {
return new Error('JestFlakyRetryReporter reported an error');
}
return undefined;
}
}
module.exports = JestFlakyRetryReporter;