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.
@@ -0,0 +1,2 @@
1
+ import { CucumberQaseReporter } from './reporter';
2
+ export = CucumberQaseReporter;
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ const reporter_1 = require("./reporter");
3
+ module.exports = reporter_1.CucumberQaseReporter;
@@ -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 {};
@@ -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.0",
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.0"
43
+ "qase-javascript-commons": "^2.0.0-beta.8"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@cucumber/cucumber": ">=7.0.0"