cypress-qase-reporter 3.1.0 → 3.1.1
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 +6 -0
- package/dist/reporter.d.ts +38 -0
- package/dist/reporter.js +155 -12
- package/package.json +9 -9
- package/tsconfig.build.json +3 -1
package/changelog.md
CHANGED
package/dist/reporter.d.ts
CHANGED
|
@@ -35,6 +35,12 @@ export declare class CypressQaseReporter extends reporters.Base {
|
|
|
35
35
|
*/
|
|
36
36
|
private reporter;
|
|
37
37
|
private testBeginTime;
|
|
38
|
+
/**
|
|
39
|
+
* Set to track processed tests to identify skipped tests when beforeEach fails
|
|
40
|
+
* @type {Set<string>}
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
private processedTests;
|
|
38
44
|
/**
|
|
39
45
|
* @param {Runner} runner
|
|
40
46
|
* @param {CypressQaseOptionsType} options
|
|
@@ -46,6 +52,38 @@ export declare class CypressQaseReporter extends reporters.Base {
|
|
|
46
52
|
* @private
|
|
47
53
|
*/
|
|
48
54
|
private addRunnerListeners;
|
|
55
|
+
/**
|
|
56
|
+
* Generate a unique identifier for a test
|
|
57
|
+
* @param {Test} test
|
|
58
|
+
* @returns {string}
|
|
59
|
+
* @private
|
|
60
|
+
*/
|
|
61
|
+
private getTestIdentifier;
|
|
62
|
+
/**
|
|
63
|
+
* Mark a test as processed
|
|
64
|
+
* @param {Test} test
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
private markTestAsProcessed;
|
|
68
|
+
/**
|
|
69
|
+
* Check if a test was processed
|
|
70
|
+
* @param {Test} test
|
|
71
|
+
* @returns {boolean}
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
private isTestProcessed;
|
|
75
|
+
/**
|
|
76
|
+
* Handle skipped tests in a suite when beforeEach hook fails
|
|
77
|
+
* @param {Suite} suite
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
private handleSkippedTestsInSuite;
|
|
81
|
+
/**
|
|
82
|
+
* Add a test result for a skipped test (due to beforeEach failure)
|
|
83
|
+
* @param {Test} test
|
|
84
|
+
* @private
|
|
85
|
+
*/
|
|
86
|
+
private addSkippedTestResult;
|
|
49
87
|
/**
|
|
50
88
|
* @param {Test} test
|
|
51
89
|
* @private
|
package/dist/reporter.js
CHANGED
|
@@ -14,7 +14,7 @@ const manager_1 = require("./metadata/manager");
|
|
|
14
14
|
const fileSearcher_1 = require("./fileSearcher");
|
|
15
15
|
const tagParser_1 = require("./utils/tagParser");
|
|
16
16
|
const resultsManager_1 = require("./metadata/resultsManager");
|
|
17
|
-
const { EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING, EVENT_RUN_END, EVENT_TEST_BEGIN, } = mocha_1.Runner.constants;
|
|
17
|
+
const { EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING, EVENT_RUN_END, EVENT_TEST_BEGIN, EVENT_SUITE_END } = mocha_1.Runner.constants;
|
|
18
18
|
/**
|
|
19
19
|
* @class CypressQaseReporter
|
|
20
20
|
* @extends reporters.Base
|
|
@@ -57,6 +57,12 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
57
57
|
*/
|
|
58
58
|
reporter;
|
|
59
59
|
testBeginTime = Date.now();
|
|
60
|
+
/**
|
|
61
|
+
* Set to track processed tests to identify skipped tests when beforeEach fails
|
|
62
|
+
* @type {Set<string>}
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
processedTests = new Set();
|
|
60
66
|
// private options: Omit<(FrameworkOptionsType<'cypress', ReporterOptionsType> & ConfigType & ReporterOptionsType & NonNullable<unknown>) | (null & ReporterOptionsType & NonNullable<unknown>), 'framework'>;
|
|
61
67
|
/**
|
|
62
68
|
* @param {Runner} runner
|
|
@@ -84,26 +90,161 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
84
90
|
* @private
|
|
85
91
|
*/
|
|
86
92
|
addRunnerListeners(runner) {
|
|
87
|
-
runner.on(EVENT_TEST_PASS, (test) =>
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
runner.on(EVENT_TEST_PASS, (test) => {
|
|
94
|
+
this.markTestAsProcessed(test);
|
|
95
|
+
this.addTestResult(test);
|
|
96
|
+
});
|
|
97
|
+
runner.on(EVENT_TEST_PENDING, (test) => {
|
|
98
|
+
this.markTestAsProcessed(test);
|
|
99
|
+
this.addTestResult(test);
|
|
100
|
+
});
|
|
101
|
+
runner.on(EVENT_TEST_FAIL, (test) => {
|
|
102
|
+
this.markTestAsProcessed(test);
|
|
103
|
+
this.addTestResult(test);
|
|
104
|
+
});
|
|
90
105
|
runner.on(EVENT_TEST_BEGIN, () => {
|
|
91
106
|
this.testBeginTime = Date.now();
|
|
92
107
|
manager_1.MetadataManager.clear();
|
|
93
108
|
});
|
|
109
|
+
runner.on(EVENT_SUITE_END, (suite) => {
|
|
110
|
+
this.handleSkippedTestsInSuite(suite);
|
|
111
|
+
});
|
|
94
112
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
95
113
|
runner.once(EVENT_RUN_END, () => {
|
|
96
114
|
const results = this.reporter.getResults();
|
|
97
115
|
resultsManager_1.ResultsManager.setResults(results);
|
|
98
|
-
|
|
99
|
-
// stdio: 'inherit',
|
|
100
|
-
// env: Object.assign(process.env, {
|
|
101
|
-
// reporterConfig: JSON.stringify(this.options),
|
|
102
|
-
// results: JSON.stringify(results),
|
|
103
|
-
// }),
|
|
104
|
-
// });
|
|
116
|
+
this.processedTests.clear();
|
|
105
117
|
});
|
|
106
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Generate a unique identifier for a test
|
|
121
|
+
* @param {Test} test
|
|
122
|
+
* @returns {string}
|
|
123
|
+
* @private
|
|
124
|
+
*/
|
|
125
|
+
getTestIdentifier(test) {
|
|
126
|
+
const file = test.parent ? this.getFile(test.parent) ?? '' : '';
|
|
127
|
+
const suitePath = test.parent ? test.parent.titlePath().join(' > ') : '';
|
|
128
|
+
let testTitle = test.fullTitle();
|
|
129
|
+
// Remove "before each" hook prefix and quotes if present (can be anywhere in the string)
|
|
130
|
+
testTitle = testTitle.replace(/"before each" hook for "/g, '');
|
|
131
|
+
// Remove trailing quote if present
|
|
132
|
+
if (testTitle.endsWith('"')) {
|
|
133
|
+
testTitle = testTitle.slice(0, -1);
|
|
134
|
+
}
|
|
135
|
+
return `${file}::${suitePath}::${testTitle}`;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Mark a test as processed
|
|
139
|
+
* @param {Test} test
|
|
140
|
+
* @private
|
|
141
|
+
*/
|
|
142
|
+
markTestAsProcessed(test) {
|
|
143
|
+
const identifier = this.getTestIdentifier(test);
|
|
144
|
+
this.processedTests.add(identifier);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Check if a test was processed
|
|
148
|
+
* @param {Test} test
|
|
149
|
+
* @returns {boolean}
|
|
150
|
+
* @private
|
|
151
|
+
*/
|
|
152
|
+
isTestProcessed(test) {
|
|
153
|
+
const identifier = this.getTestIdentifier(test);
|
|
154
|
+
return this.processedTests.has(identifier);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Handle skipped tests in a suite when beforeEach hook fails
|
|
158
|
+
* @param {Suite} suite
|
|
159
|
+
* @private
|
|
160
|
+
*/
|
|
161
|
+
handleSkippedTestsInSuite(suite) {
|
|
162
|
+
// Get tests only from the current suite (not nested suites, they will be processed separately)
|
|
163
|
+
const tests = suite.tests ?? [];
|
|
164
|
+
// Find tests that were not processed (skipped due to beforeEach failure)
|
|
165
|
+
for (const test of tests) {
|
|
166
|
+
// Skip if test was already processed (e.g., first test that got EVENT_TEST_FAIL)
|
|
167
|
+
if (!this.isTestProcessed(test)) {
|
|
168
|
+
// Test was skipped due to beforeEach failure, report it as skipped
|
|
169
|
+
this.addSkippedTestResult(test);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Add a test result for a skipped test (due to beforeEach failure)
|
|
175
|
+
* @param {Test} test
|
|
176
|
+
* @private
|
|
177
|
+
*/
|
|
178
|
+
addSkippedTestResult(test) {
|
|
179
|
+
const end_time = Date.now();
|
|
180
|
+
const duration = 0; // Skipped tests have no duration
|
|
181
|
+
const start_time = this.testBeginTime || Date.now();
|
|
182
|
+
const ids = CypressQaseReporter.getCaseId(test.title);
|
|
183
|
+
const testFileName = this.getTestFileName(test);
|
|
184
|
+
const files = this.screenshotsFolder ?
|
|
185
|
+
fileSearcher_1.FileSearcher.findFilesBeforeTime(this.screenshotsFolder, testFileName, new Date(start_time))
|
|
186
|
+
: [];
|
|
187
|
+
const attachments = files.map((file) => ({
|
|
188
|
+
content: '',
|
|
189
|
+
id: (0, uuid_1.v4)(),
|
|
190
|
+
mime_type: 'image/png',
|
|
191
|
+
size: 0,
|
|
192
|
+
file_name: path_1.default.basename(file),
|
|
193
|
+
file_path: file,
|
|
194
|
+
}));
|
|
195
|
+
let relations = {};
|
|
196
|
+
if (test.parent !== undefined) {
|
|
197
|
+
const data = [];
|
|
198
|
+
for (const suite of test.parent.titlePath()) {
|
|
199
|
+
data.push({
|
|
200
|
+
title: suite,
|
|
201
|
+
public_id: null,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
relations = {
|
|
205
|
+
suite: {
|
|
206
|
+
data: data,
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
// For skipped tests, we don't have metadata since the test never ran
|
|
211
|
+
// But we can still check for cucumber tags if the test has a parent with a file
|
|
212
|
+
if (test.parent) {
|
|
213
|
+
const file = this.getFile(test.parent);
|
|
214
|
+
if (file) {
|
|
215
|
+
const tags = (0, tagParser_1.extractTags)(file, test.title);
|
|
216
|
+
ids.push(...this.extractQaseIds(tags));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const result = {
|
|
220
|
+
attachments: attachments,
|
|
221
|
+
author: null,
|
|
222
|
+
fields: {},
|
|
223
|
+
message: null,
|
|
224
|
+
muted: false,
|
|
225
|
+
params: {},
|
|
226
|
+
group_params: {},
|
|
227
|
+
relations: relations,
|
|
228
|
+
run_id: null,
|
|
229
|
+
signature: this.getSignature(test, ids, {}),
|
|
230
|
+
steps: [],
|
|
231
|
+
id: (0, uuid_1.v4)(),
|
|
232
|
+
execution: {
|
|
233
|
+
status: qase_javascript_commons_1.TestStatusEnum.skipped,
|
|
234
|
+
start_time: this.testBeginTime / 1000,
|
|
235
|
+
end_time: end_time / 1000,
|
|
236
|
+
duration: duration,
|
|
237
|
+
stacktrace: null,
|
|
238
|
+
thread: null,
|
|
239
|
+
},
|
|
240
|
+
testops_id: ids.length > 0 ? ids : null,
|
|
241
|
+
title: this.removeQaseIdsFromTitle(test.title),
|
|
242
|
+
preparedAttachments: [],
|
|
243
|
+
};
|
|
244
|
+
void this.reporter.addTestResult(result);
|
|
245
|
+
// Mark as processed to avoid duplicate reporting
|
|
246
|
+
this.markTestAsProcessed(test);
|
|
247
|
+
}
|
|
107
248
|
/**
|
|
108
249
|
* @param {Test} test
|
|
109
250
|
* @private
|
|
@@ -113,6 +254,8 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
113
254
|
const duration = end_time - this.testBeginTime;
|
|
114
255
|
const metadata = manager_1.MetadataManager.getMetadata();
|
|
115
256
|
if (metadata?.ignore) {
|
|
257
|
+
// Mark as processed even if ignored to avoid duplicate reporting
|
|
258
|
+
this.markTestAsProcessed(test);
|
|
116
259
|
manager_1.MetadataManager.clear();
|
|
117
260
|
return;
|
|
118
261
|
}
|
|
@@ -198,7 +341,7 @@ class CypressQaseReporter extends mocha_1.reporters.Base {
|
|
|
198
341
|
steps: steps,
|
|
199
342
|
id: (0, uuid_1.v4)(),
|
|
200
343
|
execution: {
|
|
201
|
-
status: (0, qase_javascript_commons_1.determineTestStatus)(test.err
|
|
344
|
+
status: (0, qase_javascript_commons_1.determineTestStatus)(test.err ?? null, test.state ?? 'failed'),
|
|
202
345
|
start_time: this.testBeginTime / 1000,
|
|
203
346
|
end_time: end_time / 1000,
|
|
204
347
|
duration: duration,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cypress-qase-reporter",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"description": "Qase Cypress Reporter",
|
|
5
5
|
"homepage": "https://github.com/qase-tms/qase-javascript",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -51,19 +51,19 @@
|
|
|
51
51
|
"author": "Qase Team <support@qase.io>",
|
|
52
52
|
"license": "Apache-2.0",
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"qase-javascript-commons": "~2.4.
|
|
54
|
+
"qase-javascript-commons": "~2.4.13",
|
|
55
55
|
"uuid": "^9.0.1"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"cypress": ">=8.0.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@jest/globals": "^29.
|
|
62
|
-
"@types/jest": "^29.5.
|
|
63
|
-
"@types/mocha": "^10.0.
|
|
64
|
-
"ajv": "^8.
|
|
65
|
-
"jest": "^29.
|
|
66
|
-
"mocha": "^10.2
|
|
67
|
-
"ts-jest": "^29.
|
|
61
|
+
"@jest/globals": "^29.7.0",
|
|
62
|
+
"@types/jest": "^29.5.14",
|
|
63
|
+
"@types/mocha": "^10.0.10",
|
|
64
|
+
"ajv": "^8.17.1",
|
|
65
|
+
"jest": "^29.7.0",
|
|
66
|
+
"mocha": "^10.8.2",
|
|
67
|
+
"ts-jest": "^29.4.5"
|
|
68
68
|
}
|
|
69
69
|
}
|