cucumberjs-qase-reporter 2.0.0-beta.0 → 2.0.0-beta.2
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/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/reporter.d.ts +101 -0
- package/dist/reporter.js +287 -0
- package/package.json +2 -2
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Formatter, IFormatterOptions, Status } from '@cucumber/cucumber';
|
|
2
|
+
import { ConfigLoader, ConfigType, StepStatusEnum, TestStatusEnum } from 'qase-javascript-commons';
|
|
3
|
+
type TestStepResultStatus = (typeof Status)[keyof typeof Status];
|
|
4
|
+
export type CucumberQaseOptionsType = IFormatterOptions & {
|
|
5
|
+
qase?: ConfigType;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* @class CucumberQaseReporter
|
|
9
|
+
* @extends Formatter
|
|
10
|
+
*/
|
|
11
|
+
export declare class CucumberQaseReporter extends Formatter {
|
|
12
|
+
/**
|
|
13
|
+
* @type {Record<TestStepResultStatus, TestStatusEnum | null>}
|
|
14
|
+
*/
|
|
15
|
+
static statusMap: Record<TestStepResultStatus, TestStatusEnum | null>;
|
|
16
|
+
/**
|
|
17
|
+
* @type {Record<TestStepResultStatus, StepStatusEnum>}
|
|
18
|
+
*/
|
|
19
|
+
static stepStatusMap: Record<TestStepResultStatus, StepStatusEnum>;
|
|
20
|
+
/**
|
|
21
|
+
* @type {RegExp}
|
|
22
|
+
*/
|
|
23
|
+
static qaseIdRegExp: RegExp;
|
|
24
|
+
/**
|
|
25
|
+
* @param {readonly PickleTag[]} tagsList
|
|
26
|
+
* @returns {number[]}
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
29
|
+
private static getCaseIds;
|
|
30
|
+
/**
|
|
31
|
+
* @type {Record<string, PickleInfoType>}
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
private pickleInfo;
|
|
35
|
+
/**
|
|
36
|
+
* @type {Record<string, TestCaseStarted>}
|
|
37
|
+
* @private
|
|
38
|
+
*/
|
|
39
|
+
private testCaseStarts;
|
|
40
|
+
/**
|
|
41
|
+
* @type {Record<string, >}
|
|
42
|
+
* @private
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* @type {Record<string, TestStepFinished>}
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
private testCaseStepsFinished;
|
|
49
|
+
private testCaseStartedResult;
|
|
50
|
+
/**
|
|
51
|
+
* @type {Record<string, string[]>}
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
private testCaseStartedErrors;
|
|
55
|
+
/**
|
|
56
|
+
* @type {Record<string, string>}
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
private testCaseScenarioId;
|
|
60
|
+
/**
|
|
61
|
+
* @type {Record<string, string>}
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
64
|
+
private scenarios;
|
|
65
|
+
/**
|
|
66
|
+
* @type {Record<string, string>}
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
private attachments;
|
|
70
|
+
/**
|
|
71
|
+
* @type {ReporterInterface}
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
private reporter;
|
|
75
|
+
/**
|
|
76
|
+
* @type {EventEmitter}
|
|
77
|
+
* @private
|
|
78
|
+
*/
|
|
79
|
+
private eventBroadcaster;
|
|
80
|
+
/**
|
|
81
|
+
* @param {CucumberQaseOptionsType} options
|
|
82
|
+
* @param {ConfigLoaderInterface} configLoader
|
|
83
|
+
*/
|
|
84
|
+
constructor(options: CucumberQaseOptionsType, configLoader?: ConfigLoader<Partial<ConfigType> & Record<string, unknown>>);
|
|
85
|
+
/**
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
private bindEventListeners;
|
|
89
|
+
private convertSteps;
|
|
90
|
+
/**
|
|
91
|
+
* @returns {Promise<void>}
|
|
92
|
+
* @private
|
|
93
|
+
*/
|
|
94
|
+
private publishResults;
|
|
95
|
+
/**
|
|
96
|
+
* @returns {Promise<void>}
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
private startTestRun;
|
|
100
|
+
}
|
|
101
|
+
export {};
|
package/dist/reporter.js
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CucumberQaseReporter = void 0;
|
|
4
|
+
const cucumber_1 = require("@cucumber/cucumber");
|
|
5
|
+
const qase_javascript_commons_1 = require("qase-javascript-commons");
|
|
6
|
+
/**
|
|
7
|
+
* @class CucumberQaseReporter
|
|
8
|
+
* @extends Formatter
|
|
9
|
+
*/
|
|
10
|
+
class CucumberQaseReporter extends cucumber_1.Formatter {
|
|
11
|
+
/**
|
|
12
|
+
* @param {readonly PickleTag[]} tagsList
|
|
13
|
+
* @returns {number[]}
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
static getCaseIds(tagsList) {
|
|
17
|
+
return tagsList.reduce((acc, tagInfo) => {
|
|
18
|
+
const ids = Array.from(tagInfo.name.matchAll(CucumberQaseReporter.qaseIdRegExp))
|
|
19
|
+
.map(([, id]) => Number(id))
|
|
20
|
+
.filter((id) => id !== undefined);
|
|
21
|
+
acc.push(...ids);
|
|
22
|
+
return acc;
|
|
23
|
+
}, []);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* @param {CucumberQaseOptionsType} options
|
|
27
|
+
* @param {ConfigLoaderInterface} configLoader
|
|
28
|
+
*/
|
|
29
|
+
constructor(options, configLoader = new qase_javascript_commons_1.ConfigLoader()) {
|
|
30
|
+
const { qase, ...formatterOptions } = options;
|
|
31
|
+
const config = configLoader.load();
|
|
32
|
+
super(formatterOptions);
|
|
33
|
+
/**
|
|
34
|
+
* @type {Record<string, PickleInfoType>}
|
|
35
|
+
* @private
|
|
36
|
+
*/
|
|
37
|
+
this.pickleInfo = {};
|
|
38
|
+
/**
|
|
39
|
+
* @type {Record<string, TestCaseStarted>}
|
|
40
|
+
* @private
|
|
41
|
+
*/
|
|
42
|
+
this.testCaseStarts = {};
|
|
43
|
+
/**
|
|
44
|
+
* @type {Record<string, >}
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* @type {Record<string, TestStepFinished>}
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
this.testCaseStepsFinished = {};
|
|
52
|
+
this.testCaseStartedResult = {};
|
|
53
|
+
/**
|
|
54
|
+
* @type {Record<string, string[]>}
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
this.testCaseStartedErrors = {};
|
|
58
|
+
/**
|
|
59
|
+
* @type {Record<string, string>}
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
this.testCaseScenarioId = {};
|
|
63
|
+
/**
|
|
64
|
+
* @type {Record<string, string>}
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
this.scenarios = {};
|
|
68
|
+
/**
|
|
69
|
+
* @type {Record<string, string>}
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
this.attachments = {};
|
|
73
|
+
this.reporter = qase_javascript_commons_1.QaseReporter.getInstance({
|
|
74
|
+
...(0, qase_javascript_commons_1.composeOptions)(qase, config),
|
|
75
|
+
frameworkPackage: '@cucumber/cucumber',
|
|
76
|
+
frameworkName: 'cucumberjs',
|
|
77
|
+
reporterName: 'cucumberjs-qase-reporter',
|
|
78
|
+
});
|
|
79
|
+
this.eventBroadcaster = formatterOptions.eventBroadcaster;
|
|
80
|
+
this.bindEventListeners();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
bindEventListeners() {
|
|
86
|
+
this.eventBroadcaster.on('envelope', (envelope) => {
|
|
87
|
+
if (envelope.gherkinDocument) {
|
|
88
|
+
if (envelope.gherkinDocument.feature) {
|
|
89
|
+
const { children, name } = envelope.gherkinDocument.feature;
|
|
90
|
+
children.forEach(({ scenario }) => {
|
|
91
|
+
if (scenario) {
|
|
92
|
+
this.scenarios[scenario.id] = name;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (envelope.pickle) {
|
|
98
|
+
this.pickleInfo[envelope.pickle.id] = {
|
|
99
|
+
caseIds: CucumberQaseReporter.getCaseIds(envelope.pickle.tags),
|
|
100
|
+
name: envelope.pickle.name,
|
|
101
|
+
lastAstNodeId: envelope.pickle.astNodeIds[envelope.pickle.astNodeIds.length - 1],
|
|
102
|
+
steps: envelope.pickle.steps,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
else if (envelope.attachment) {
|
|
106
|
+
if (envelope.attachment.testCaseStartedId &&
|
|
107
|
+
envelope.attachment.fileName) {
|
|
108
|
+
this.attachments[envelope.attachment.testCaseStartedId] =
|
|
109
|
+
envelope.attachment.fileName;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (envelope.testRunStarted) {
|
|
113
|
+
this.startTestRun();
|
|
114
|
+
}
|
|
115
|
+
else if (envelope.testRunFinished) {
|
|
116
|
+
void this.publishResults();
|
|
117
|
+
}
|
|
118
|
+
else if (envelope.testCase) {
|
|
119
|
+
this.testCaseScenarioId[envelope.testCase.id] =
|
|
120
|
+
envelope.testCase;
|
|
121
|
+
}
|
|
122
|
+
else if (envelope.testCaseStarted) {
|
|
123
|
+
this.testCaseStarts[envelope.testCaseStarted.id] =
|
|
124
|
+
envelope.testCaseStarted;
|
|
125
|
+
this.testCaseStartedResult[envelope.testCaseStarted.id] =
|
|
126
|
+
qase_javascript_commons_1.TestStatusEnum.passed;
|
|
127
|
+
}
|
|
128
|
+
else if (envelope.testStepFinished) {
|
|
129
|
+
const stepFin = envelope.testStepFinished;
|
|
130
|
+
const oldStatus = this.testCaseStartedResult[stepFin.testCaseStartedId];
|
|
131
|
+
const newStatus = CucumberQaseReporter.statusMap[stepFin.testStepResult.status];
|
|
132
|
+
if (newStatus === null) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.testCaseStepsFinished[stepFin.testStepId] = stepFin;
|
|
136
|
+
if (newStatus !== qase_javascript_commons_1.TestStatusEnum.passed) {
|
|
137
|
+
if (stepFin.testStepResult.message) {
|
|
138
|
+
const errors = this.testCaseStartedErrors[stepFin.testCaseStartedId] ?? [];
|
|
139
|
+
if (!this.testCaseStartedErrors[stepFin.testCaseStartedId]) {
|
|
140
|
+
this.testCaseStartedErrors[stepFin.testCaseStartedId] = errors;
|
|
141
|
+
}
|
|
142
|
+
errors.push(stepFin.testStepResult.message);
|
|
143
|
+
}
|
|
144
|
+
if (oldStatus) {
|
|
145
|
+
if (oldStatus !== qase_javascript_commons_1.TestStatusEnum.failed) {
|
|
146
|
+
this.testCaseStartedResult[stepFin.testCaseStartedId] = newStatus;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
this.testCaseStartedResult[stepFin.testCaseStartedId] = newStatus;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else if (envelope.testCaseFinished) {
|
|
155
|
+
const tcs = this.testCaseStarts[envelope.testCaseFinished.testCaseStartedId];
|
|
156
|
+
if (!tcs) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const testCase = this.testCaseScenarioId[tcs.testCaseId];
|
|
160
|
+
if (!testCase) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const info = this.pickleInfo[testCase.pickleId];
|
|
164
|
+
if (!info) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
let error;
|
|
168
|
+
if (this.testCaseStartedErrors[tcs.id]?.length) {
|
|
169
|
+
error = new Error(this.testCaseStartedErrors[tcs.id]?.join('\n\n'));
|
|
170
|
+
}
|
|
171
|
+
let relations = null;
|
|
172
|
+
if (info.lastAstNodeId != undefined && this.scenarios[info.lastAstNodeId] != undefined) {
|
|
173
|
+
relations = {
|
|
174
|
+
suite: {
|
|
175
|
+
data: [
|
|
176
|
+
{
|
|
177
|
+
title: this.scenarios[info.lastAstNodeId] ?? '',
|
|
178
|
+
public_id: null,
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
void this.reporter.addTestResult({
|
|
185
|
+
attachments: [],
|
|
186
|
+
author: null,
|
|
187
|
+
execution: {
|
|
188
|
+
status: this.testCaseStartedResult[envelope.testCaseFinished.testCaseStartedId] ?? qase_javascript_commons_1.TestStatusEnum.passed,
|
|
189
|
+
start_time: null,
|
|
190
|
+
end_time: null,
|
|
191
|
+
duration: Math.abs(envelope.testCaseFinished.timestamp.seconds - tcs.timestamp.seconds),
|
|
192
|
+
stacktrace: error?.stack ?? null,
|
|
193
|
+
thread: null,
|
|
194
|
+
},
|
|
195
|
+
fields: {},
|
|
196
|
+
message: null,
|
|
197
|
+
muted: false,
|
|
198
|
+
params: {},
|
|
199
|
+
relations: relations,
|
|
200
|
+
run_id: null,
|
|
201
|
+
signature: '',
|
|
202
|
+
steps: this.convertSteps(info.steps, testCase),
|
|
203
|
+
testops_id: info.caseIds.length > 0 ? info.caseIds : null,
|
|
204
|
+
id: tcs.id,
|
|
205
|
+
title: info.name,
|
|
206
|
+
// suiteTitle: info.lastAstNodeId && this.scenarios[info.lastAstNodeId],
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
convertSteps(steps, testCase) {
|
|
212
|
+
const results = [];
|
|
213
|
+
for (const s of testCase.testSteps) {
|
|
214
|
+
const finished = this.testCaseStepsFinished[s.id];
|
|
215
|
+
if (!finished) {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
const step = steps.find((step) => step.id === s.pickleStepId);
|
|
219
|
+
if (!step) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
const result = {
|
|
223
|
+
id: s.id,
|
|
224
|
+
step_type: qase_javascript_commons_1.StepType.GHERKIN,
|
|
225
|
+
data: {
|
|
226
|
+
keyword: step.text,
|
|
227
|
+
name: step.text,
|
|
228
|
+
line: 0,
|
|
229
|
+
},
|
|
230
|
+
execution: {
|
|
231
|
+
status: CucumberQaseReporter.stepStatusMap[finished.testStepResult.status],
|
|
232
|
+
start_time: null,
|
|
233
|
+
end_time: null,
|
|
234
|
+
duration: finished.testStepResult.duration.seconds,
|
|
235
|
+
},
|
|
236
|
+
attachments: [],
|
|
237
|
+
steps: [],
|
|
238
|
+
parent_id: null,
|
|
239
|
+
};
|
|
240
|
+
results.push(result);
|
|
241
|
+
}
|
|
242
|
+
return results;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* @returns {Promise<void>}
|
|
246
|
+
* @private
|
|
247
|
+
*/
|
|
248
|
+
async publishResults() {
|
|
249
|
+
await this.reporter.publish();
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* @returns {Promise<void>}
|
|
253
|
+
* @private
|
|
254
|
+
*/
|
|
255
|
+
startTestRun() {
|
|
256
|
+
this.reporter.startTestRun();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
exports.CucumberQaseReporter = CucumberQaseReporter;
|
|
260
|
+
/**
|
|
261
|
+
* @type {Record<TestStepResultStatus, TestStatusEnum | null>}
|
|
262
|
+
*/
|
|
263
|
+
CucumberQaseReporter.statusMap = {
|
|
264
|
+
[cucumber_1.Status.PASSED]: qase_javascript_commons_1.TestStatusEnum.passed,
|
|
265
|
+
[cucumber_1.Status.FAILED]: qase_javascript_commons_1.TestStatusEnum.failed,
|
|
266
|
+
[cucumber_1.Status.SKIPPED]: qase_javascript_commons_1.TestStatusEnum.skipped,
|
|
267
|
+
[cucumber_1.Status.AMBIGUOUS]: null,
|
|
268
|
+
[cucumber_1.Status.PENDING]: qase_javascript_commons_1.TestStatusEnum.blocked,
|
|
269
|
+
[cucumber_1.Status.UNDEFINED]: null,
|
|
270
|
+
[cucumber_1.Status.UNKNOWN]: null,
|
|
271
|
+
};
|
|
272
|
+
/**
|
|
273
|
+
* @type {Record<TestStepResultStatus, StepStatusEnum>}
|
|
274
|
+
*/
|
|
275
|
+
CucumberQaseReporter.stepStatusMap = {
|
|
276
|
+
[cucumber_1.Status.PASSED]: qase_javascript_commons_1.StepStatusEnum.passed,
|
|
277
|
+
[cucumber_1.Status.FAILED]: qase_javascript_commons_1.StepStatusEnum.failed,
|
|
278
|
+
[cucumber_1.Status.SKIPPED]: qase_javascript_commons_1.StepStatusEnum.blocked,
|
|
279
|
+
[cucumber_1.Status.AMBIGUOUS]: qase_javascript_commons_1.StepStatusEnum.blocked,
|
|
280
|
+
[cucumber_1.Status.PENDING]: qase_javascript_commons_1.StepStatusEnum.blocked,
|
|
281
|
+
[cucumber_1.Status.UNDEFINED]: qase_javascript_commons_1.StepStatusEnum.blocked,
|
|
282
|
+
[cucumber_1.Status.UNKNOWN]: qase_javascript_commons_1.StepStatusEnum.blocked,
|
|
283
|
+
};
|
|
284
|
+
/**
|
|
285
|
+
* @type {RegExp}
|
|
286
|
+
*/
|
|
287
|
+
CucumberQaseReporter.qaseIdRegExp = /^@[Qq]-?(\d+)$/g;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cucumberjs-qase-reporter",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.2",
|
|
4
4
|
"description": "Qase TMS CucumberJS Reporter",
|
|
5
5
|
"homepage": "https://github.com/qase-tms/qase-javascript",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"license": "Apache-2.0",
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@cucumber/messages": "^22.0.0",
|
|
43
|
-
"qase-javascript-commons": "^2.0.0-beta.
|
|
43
|
+
"qase-javascript-commons": "^2.0.0-beta.8"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@cucumber/cucumber": ">=7.0.0"
|