@wdio/allure-reporter 8.0.13 → 8.1.0
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/build/common/api.d.ts +108 -0
- package/build/common/api.d.ts.map +1 -0
- package/build/common/api.js +139 -0
- package/build/compoundError.js +3 -5
- package/build/constants.d.ts +7 -8
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +6 -7
- package/build/index.d.ts +3 -148
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -596
- package/build/reporter.d.ts +70 -0
- package/build/reporter.d.ts.map +1 -0
- package/build/reporter.js +485 -0
- package/build/types.d.ts +6 -0
- package/build/types.d.ts.map +1 -1
- package/build/types.js +1 -1
- package/build/utils.d.ts +3 -10
- package/build/utils.d.ts.map +1 -1
- package/build/utils.js +8 -15
- package/cjs/common/api.js +155 -0
- package/cjs/constants.js +40 -0
- package/cjs/package.json +3 -0
- package/cjs/types.js +9 -0
- package/package.json +17 -8
- package/tsconfig.cjs.json +12 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { stringify } from 'csv-stringify/sync';
|
|
3
|
+
import WDIOReporter from '@wdio/reporter';
|
|
4
|
+
import { addFeature, addLabel, addSeverity, addIssue, addTestId, addStory, addEnvironment, addDescription, addAttachment, startStep, endStep, addStep, addArgument } from './common/api.js';
|
|
5
|
+
import { getTestStatus, isEmpty, isMochaEachHooks, getErrorFromFailedTest, isMochaAllHooks, getLinkByTemplate, attachConsoleLogs } from './utils.js';
|
|
6
|
+
import { events, PASSED, PENDING, SKIPPED, stepStatuses } from './constants.js';
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
/**
|
|
9
|
+
* Allure v1 has no proper TS support
|
|
10
|
+
* ToDo(Christian): update to Allure v2 (https://github.com/webdriverio/webdriverio/issues/6313)
|
|
11
|
+
*/
|
|
12
|
+
const Allure = require('allure-js-commons');
|
|
13
|
+
const Step = require('allure-js-commons/beans/step.js');
|
|
14
|
+
export default class AllureReporter extends WDIOReporter {
|
|
15
|
+
_allure;
|
|
16
|
+
_capabilities;
|
|
17
|
+
_isMultiremote;
|
|
18
|
+
_config;
|
|
19
|
+
_lastScreenshot;
|
|
20
|
+
_options;
|
|
21
|
+
_consoleOutput;
|
|
22
|
+
_originalStdoutWrite;
|
|
23
|
+
_addConsoleLogs;
|
|
24
|
+
_startedFeatures = [];
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
const outputDir = options.outputDir || 'allure-results';
|
|
27
|
+
super({
|
|
28
|
+
...options,
|
|
29
|
+
outputDir,
|
|
30
|
+
});
|
|
31
|
+
this._addConsoleLogs = false;
|
|
32
|
+
this._consoleOutput = '';
|
|
33
|
+
this._originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
34
|
+
this._allure = new Allure();
|
|
35
|
+
this._capabilities = {};
|
|
36
|
+
this._options = options;
|
|
37
|
+
this._allure.setOptions({ targetDir: outputDir });
|
|
38
|
+
this.registerListeners();
|
|
39
|
+
this._lastScreenshot = undefined;
|
|
40
|
+
const processObj = process;
|
|
41
|
+
if (options.addConsoleLogs || this._addConsoleLogs) {
|
|
42
|
+
processObj.stdout.write = (chunk, encoding, callback) => {
|
|
43
|
+
if (typeof chunk === 'string' && !chunk.includes('mwebdriver')) {
|
|
44
|
+
this._consoleOutput += chunk;
|
|
45
|
+
}
|
|
46
|
+
return this._originalStdoutWrite(chunk, encoding, callback);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
registerListeners() {
|
|
51
|
+
process.on(events.addLabel, this.addLabel.bind(this));
|
|
52
|
+
process.on(events.addFeature, this.addFeature.bind(this));
|
|
53
|
+
process.on(events.addStory, this.addStory.bind(this));
|
|
54
|
+
process.on(events.addSeverity, this.addSeverity.bind(this));
|
|
55
|
+
process.on(events.addIssue, this.addIssue.bind(this));
|
|
56
|
+
process.on(events.addTestId, this.addTestId.bind(this));
|
|
57
|
+
process.on(events.addEnvironment, this.addEnvironment.bind(this));
|
|
58
|
+
process.on(events.addAttachment, this.addAttachment.bind(this));
|
|
59
|
+
process.on(events.addDescription, this.addDescription.bind(this));
|
|
60
|
+
process.on(events.startStep, this.startStep.bind(this));
|
|
61
|
+
process.on(events.endStep, this.endStep.bind(this));
|
|
62
|
+
process.on(events.addStep, this.addStep.bind(this));
|
|
63
|
+
process.on(events.addArgument, this.addArgument.bind(this));
|
|
64
|
+
}
|
|
65
|
+
onRunnerStart(runner) {
|
|
66
|
+
this._config = runner.config;
|
|
67
|
+
this._capabilities = runner.capabilities;
|
|
68
|
+
this._isMultiremote = runner.isMultiremote || false;
|
|
69
|
+
}
|
|
70
|
+
onSuiteStart(suite) {
|
|
71
|
+
const isFeature = suite.type === 'feature';
|
|
72
|
+
if (!this._options.useCucumberStepReporter) {
|
|
73
|
+
const currentSuite = this._allure.getCurrentSuite();
|
|
74
|
+
const prefix = currentSuite ? currentSuite.name + ': ' : '';
|
|
75
|
+
this._allure.startSuite(prefix + suite.title);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// handle cucumber features as allure "suite"
|
|
79
|
+
if (isFeature) {
|
|
80
|
+
// temp solution to keep suites stats index for saving allure test ops feature based structure
|
|
81
|
+
this._startedFeatures.push(suite);
|
|
82
|
+
this._allure.startSuite(suite.title);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// handle cucumber scenario as allure "case" instead of "suite"
|
|
86
|
+
this._allure.startCase(suite.title);
|
|
87
|
+
const currentTest = this._allure.getCurrentTest();
|
|
88
|
+
this.getLabels(suite).forEach(({ name, value }) => {
|
|
89
|
+
currentTest.addLabel(name, value);
|
|
90
|
+
});
|
|
91
|
+
if (suite.description) {
|
|
92
|
+
this.addDescription(suite);
|
|
93
|
+
}
|
|
94
|
+
this.setCaseParameters(suite.cid, suite.parent);
|
|
95
|
+
}
|
|
96
|
+
onSuiteEnd(suite) {
|
|
97
|
+
// cleanup suites index to prevent resource leaks
|
|
98
|
+
if (suite.type === 'feature') {
|
|
99
|
+
this._startedFeatures = this._startedFeatures.filter((suite) => suite.uid !== suite.uid);
|
|
100
|
+
}
|
|
101
|
+
if (this._options.useCucumberStepReporter && suite.type === 'scenario') {
|
|
102
|
+
// passing hooks are missing the 'state' property
|
|
103
|
+
suite.hooks = suite.hooks.map((hook) => {
|
|
104
|
+
hook.state = hook.state ? hook.state : 'passed';
|
|
105
|
+
return hook;
|
|
106
|
+
});
|
|
107
|
+
const suiteChildren = [...suite.tests, ...suite.hooks];
|
|
108
|
+
const isPassed = !suiteChildren.some(item => item.state !== 'passed');
|
|
109
|
+
if (isPassed) {
|
|
110
|
+
return this._allure.endCase('passed');
|
|
111
|
+
}
|
|
112
|
+
// A scenario is it skipped if every steps are skipped and hooks are passed or skipped
|
|
113
|
+
const isSkipped = suite.tests.every(item => [SKIPPED].indexOf(item.state) >= 0) && suite.hooks.every(item => [PASSED, SKIPPED].indexOf(item.state) >= 0);
|
|
114
|
+
if (isSkipped) {
|
|
115
|
+
return this._allure.endCase(PENDING);
|
|
116
|
+
}
|
|
117
|
+
// A scenario is it passed if certain steps are passed and all other are skipped and every hooks are passed or skipped
|
|
118
|
+
const isPartiallySkipped = suiteChildren.every(item => [PASSED, SKIPPED].indexOf(item.state) >= 0);
|
|
119
|
+
if (isPartiallySkipped) {
|
|
120
|
+
return this._allure.endCase('passed');
|
|
121
|
+
}
|
|
122
|
+
// Only close passing and skipped tests because
|
|
123
|
+
// failing tests are closed in onTestFailed event
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this._allure.endSuite();
|
|
127
|
+
}
|
|
128
|
+
onTestStart(test) {
|
|
129
|
+
this._consoleOutput = '';
|
|
130
|
+
const testTitle = test.currentTest ? test.currentTest : test.title;
|
|
131
|
+
if (this.isAnyTestRunning() && this._allure.getCurrentTest().name === testTitle) {
|
|
132
|
+
// Test already in progress, most likely started by a before each hook
|
|
133
|
+
this.setCaseParameters(test.cid, test.parent);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (this._options.useCucumberStepReporter) {
|
|
137
|
+
this._allure.startStep(testTitle);
|
|
138
|
+
const testObj = test;
|
|
139
|
+
const argument = testObj?.argument;
|
|
140
|
+
const dataTable = argument?.rows?.map((a) => a?.cells);
|
|
141
|
+
if (dataTable) {
|
|
142
|
+
this._allure.addAttachment('Data Table', stringify(dataTable), 'text/csv');
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this._allure.startCase(testTitle);
|
|
147
|
+
this.setCaseParameters(test.cid, test.parent);
|
|
148
|
+
}
|
|
149
|
+
setCaseParameters(cid, parentUid) {
|
|
150
|
+
const parentSuite = this.getParentSuite(parentUid);
|
|
151
|
+
const currentTest = this._allure.getCurrentTest();
|
|
152
|
+
if (!this._isMultiremote) {
|
|
153
|
+
const caps = this._capabilities;
|
|
154
|
+
const { browserName, deviceName, desired, device } = caps;
|
|
155
|
+
let targetName = device || browserName || deviceName || cid;
|
|
156
|
+
// custom mobile grids can have device information in a `desired` cap
|
|
157
|
+
if (desired && desired.deviceName && desired.platformVersion) {
|
|
158
|
+
targetName = `${device || desired.deviceName} ${desired.platformVersion}`;
|
|
159
|
+
}
|
|
160
|
+
const browserstackVersion = caps.os_version || caps.osVersion;
|
|
161
|
+
const version = browserstackVersion || caps.browserVersion || caps.version || caps.platformVersion || '';
|
|
162
|
+
const paramName = (deviceName || device) ? 'device' : 'browser';
|
|
163
|
+
const paramValue = version ? `${targetName}-${version}` : targetName;
|
|
164
|
+
currentTest.addParameter('argument', paramName, paramValue);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
currentTest.addParameter('argument', 'isMultiremote', 'true');
|
|
168
|
+
}
|
|
169
|
+
// Allure analytics labels. See https://github.com/allure-framework/allure2/blob/master/Analytics.md
|
|
170
|
+
currentTest.addLabel('language', 'javascript');
|
|
171
|
+
currentTest.addLabel('framework', 'wdio');
|
|
172
|
+
currentTest.addLabel('thread', cid);
|
|
173
|
+
if (parentSuite?.title) {
|
|
174
|
+
currentTest.addLabel('feature', parentSuite?.title);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
getParentSuite(uid) {
|
|
178
|
+
if (!uid) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
return this._startedFeatures.find((suite) => suite.uid === uid);
|
|
182
|
+
}
|
|
183
|
+
getLabels({ tags }) {
|
|
184
|
+
const labels = [];
|
|
185
|
+
if (tags) {
|
|
186
|
+
tags.forEach((tag) => {
|
|
187
|
+
const label = tag.name.replace(/[@]/, '').split('=');
|
|
188
|
+
if (label.length === 2) {
|
|
189
|
+
labels.push({ name: label[0], value: label[1] });
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
return labels;
|
|
194
|
+
}
|
|
195
|
+
onTestPass() {
|
|
196
|
+
attachConsoleLogs(this._consoleOutput, this._allure);
|
|
197
|
+
if (this._options.useCucumberStepReporter) {
|
|
198
|
+
const suite = this._allure.getCurrentSuite();
|
|
199
|
+
if (suite && suite.currentStep instanceof Step) {
|
|
200
|
+
return this._allure.endStep('passed');
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
this._allure.endCase(PASSED);
|
|
204
|
+
}
|
|
205
|
+
onTestFail(test) {
|
|
206
|
+
if (this._options.useCucumberStepReporter) {
|
|
207
|
+
attachConsoleLogs(this._consoleOutput, this._allure);
|
|
208
|
+
const testStatus = getTestStatus(test, this._config);
|
|
209
|
+
const stepStatus = Object.values(stepStatuses).indexOf(testStatus) >= 0 ?
|
|
210
|
+
testStatus : 'failed';
|
|
211
|
+
const suite = this._allure.getCurrentSuite();
|
|
212
|
+
if (suite && suite.currentStep instanceof Step) {
|
|
213
|
+
this._allure.endStep(stepStatus);
|
|
214
|
+
}
|
|
215
|
+
this._allure.endCase(testStatus, getErrorFromFailedTest(test));
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (!this.isAnyTestRunning()) { // is any CASE running
|
|
219
|
+
this.onTestStart(test);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
this._allure.getCurrentTest().name = test.title;
|
|
223
|
+
}
|
|
224
|
+
attachConsoleLogs(this._consoleOutput, this._allure);
|
|
225
|
+
const status = getTestStatus(test, this._config);
|
|
226
|
+
while (this._allure.getCurrentSuite().currentStep instanceof Step) {
|
|
227
|
+
this._allure.endStep(status);
|
|
228
|
+
}
|
|
229
|
+
this._allure.endCase(status, getErrorFromFailedTest(test));
|
|
230
|
+
}
|
|
231
|
+
onTestSkip(test) {
|
|
232
|
+
attachConsoleLogs(this._consoleOutput, this._allure);
|
|
233
|
+
if (this._options.useCucumberStepReporter) {
|
|
234
|
+
const suite = this._allure.getCurrentSuite();
|
|
235
|
+
if (suite && suite.currentStep instanceof Step) {
|
|
236
|
+
this._allure.endStep('canceled');
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else if (!this._allure.getCurrentTest() || this._allure.getCurrentTest().name !== test.title) {
|
|
240
|
+
this._allure.pendingCase(test.title);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
this._allure.endCase('pending');
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
onBeforeCommand(command) {
|
|
247
|
+
if (!this.isAnyTestRunning()) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const { disableWebdriverStepsReporting } = this._options;
|
|
251
|
+
if (disableWebdriverStepsReporting || this._isMultiremote) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
this._allure.startStep(command.method
|
|
255
|
+
? `${command.method} ${command.endpoint}`
|
|
256
|
+
: command.command);
|
|
257
|
+
const payload = command.body || command.params;
|
|
258
|
+
if (!isEmpty(payload)) {
|
|
259
|
+
this.dumpJSON('Request', payload);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
onAfterCommand(command) {
|
|
263
|
+
const { disableWebdriverStepsReporting, disableWebdriverScreenshotsReporting } = this._options;
|
|
264
|
+
if (this.isScreenshotCommand(command) && command.result.value) {
|
|
265
|
+
if (!disableWebdriverScreenshotsReporting) {
|
|
266
|
+
this._lastScreenshot = command.result.value;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (!this.isAnyTestRunning()) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
this.attachScreenshot();
|
|
273
|
+
if (this._isMultiremote) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (!disableWebdriverStepsReporting) {
|
|
277
|
+
if (command.result && command.result.value && !this.isScreenshotCommand(command)) {
|
|
278
|
+
this.dumpJSON('Response', command.result.value);
|
|
279
|
+
}
|
|
280
|
+
const suite = this._allure.getCurrentSuite();
|
|
281
|
+
if (!suite || !(suite.currentStep instanceof Step)) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
this._allure.endStep('passed');
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
onHookStart(hook) {
|
|
288
|
+
// ignore global hooks
|
|
289
|
+
if (!hook.parent || !this._allure.getCurrentSuite()) {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
// add beforeEach / afterEach hook as step to test
|
|
293
|
+
if (this._options.disableMochaHooks && isMochaEachHooks(hook.title)) {
|
|
294
|
+
if (this._allure.getCurrentTest()) {
|
|
295
|
+
this._allure.startStep(hook.title);
|
|
296
|
+
}
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
// don't add hook as test to suite for mocha All hooks
|
|
300
|
+
if (this._options.disableMochaHooks && isMochaAllHooks(hook.title)) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
// add hook as test to suite
|
|
304
|
+
this.onTestStart(hook);
|
|
305
|
+
}
|
|
306
|
+
onHookEnd(hook) {
|
|
307
|
+
// ignore global hooks
|
|
308
|
+
if (!hook.parent || !this._allure.getCurrentSuite() || (this._options.disableMochaHooks && !isMochaAllHooks(hook.title) && !this._allure.getCurrentTest())) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
// set beforeEach / afterEach hook (step) status
|
|
312
|
+
if (this._options.disableMochaHooks && isMochaEachHooks(hook.title)) {
|
|
313
|
+
hook.error
|
|
314
|
+
? this._allure.endStep('failed')
|
|
315
|
+
: this._allure.endStep('passed');
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
// set hook (test) status
|
|
319
|
+
if (hook.error) {
|
|
320
|
+
if (this._options.disableMochaHooks && isMochaAllHooks(hook.title)) {
|
|
321
|
+
this.onTestStart(hook);
|
|
322
|
+
this.attachScreenshot();
|
|
323
|
+
}
|
|
324
|
+
this.onTestFail(hook);
|
|
325
|
+
}
|
|
326
|
+
else if ((this._options.disableMochaHooks || this._options.useCucumberStepReporter) &&
|
|
327
|
+
!isMochaAllHooks(hook.title)) {
|
|
328
|
+
this.onTestPass();
|
|
329
|
+
// remove hook from suite if it has no steps
|
|
330
|
+
if (this._allure.getCurrentTest().steps.length === 0 && !this._options.useCucumberStepReporter) {
|
|
331
|
+
this._allure.getCurrentSuite().testcases.pop();
|
|
332
|
+
}
|
|
333
|
+
else if (this._options.useCucumberStepReporter) {
|
|
334
|
+
// remove hook when it's registered as a step and if it's passed
|
|
335
|
+
const step = this._allure.getCurrentTest().steps.pop();
|
|
336
|
+
// if it had any attachments, reattach them to current test
|
|
337
|
+
if (step && step.attachments.length >= 1) {
|
|
338
|
+
step.attachments.forEach((attachment) => {
|
|
339
|
+
this._allure.getCurrentTest().addAttachment(attachment);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
else if (!this._options.disableMochaHooks) {
|
|
345
|
+
this.onTestPass();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
addLabel({ name, value }) {
|
|
349
|
+
if (!this.isAnyTestRunning()) {
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
const test = this._allure.getCurrentTest();
|
|
353
|
+
test.addLabel(name, value);
|
|
354
|
+
}
|
|
355
|
+
addStory({ storyName }) {
|
|
356
|
+
if (!this.isAnyTestRunning()) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
const test = this._allure.getCurrentTest();
|
|
360
|
+
test.addLabel('story', storyName);
|
|
361
|
+
}
|
|
362
|
+
addFeature({ featureName }) {
|
|
363
|
+
if (!this.isAnyTestRunning()) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
const test = this._allure.getCurrentTest();
|
|
367
|
+
test.addLabel('feature', featureName);
|
|
368
|
+
}
|
|
369
|
+
addSeverity({ severity }) {
|
|
370
|
+
if (!this.isAnyTestRunning()) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
const test = this._allure.getCurrentTest();
|
|
374
|
+
test.addLabel('severity', severity);
|
|
375
|
+
}
|
|
376
|
+
addIssue({ issue }) {
|
|
377
|
+
if (!this.isAnyTestRunning()) {
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
const test = this._allure.getCurrentTest();
|
|
381
|
+
const issueLink = getLinkByTemplate(this._options.issueLinkTemplate, issue);
|
|
382
|
+
test.addLabel('issue', issueLink);
|
|
383
|
+
}
|
|
384
|
+
addTestId({ testId }) {
|
|
385
|
+
if (!this.isAnyTestRunning()) {
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
const test = this._allure.getCurrentTest();
|
|
389
|
+
const tmsLink = getLinkByTemplate(this._options.tmsLinkTemplate, testId);
|
|
390
|
+
test.addLabel('testId', tmsLink);
|
|
391
|
+
}
|
|
392
|
+
addEnvironment({ name, value }) {
|
|
393
|
+
if (!this.isAnyTestRunning()) {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
const test = this._allure.getCurrentTest();
|
|
397
|
+
test.addParameter('environment-variable', name, value);
|
|
398
|
+
}
|
|
399
|
+
addDescription({ description, descriptionType }) {
|
|
400
|
+
if (!this.isAnyTestRunning()) {
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
const test = this._allure.getCurrentTest();
|
|
404
|
+
test.setDescription(description, descriptionType);
|
|
405
|
+
}
|
|
406
|
+
addAttachment({ name, content, type = 'text/plain' }) {
|
|
407
|
+
if (!this.isAnyTestRunning()) {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
if (type === 'application/json') {
|
|
411
|
+
this.dumpJSON(name, content);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
this._allure.addAttachment(name, Buffer.from(content), type);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
startStep(title) {
|
|
418
|
+
if (!this.isAnyTestRunning()) {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
this._allure.startStep(title);
|
|
422
|
+
}
|
|
423
|
+
endStep(status) {
|
|
424
|
+
if (!this.isAnyTestRunning()) {
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
this._allure.endStep(status);
|
|
428
|
+
}
|
|
429
|
+
addStep({ step }) {
|
|
430
|
+
if (!this.isAnyTestRunning()) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
this.startStep(step.title);
|
|
434
|
+
if (step.attachment) {
|
|
435
|
+
this.addAttachment(step.attachment);
|
|
436
|
+
}
|
|
437
|
+
this.endStep(step.status);
|
|
438
|
+
}
|
|
439
|
+
addArgument({ name, value }) {
|
|
440
|
+
if (!this.isAnyTestRunning()) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
const test = this._allure.getCurrentTest();
|
|
444
|
+
test.addParameter('argument', name, value);
|
|
445
|
+
}
|
|
446
|
+
isAnyTestRunning() {
|
|
447
|
+
return this._allure.getCurrentSuite() && this._allure.getCurrentTest();
|
|
448
|
+
}
|
|
449
|
+
isScreenshotCommand(command) {
|
|
450
|
+
const isScrenshotEndpoint = /\/session\/[^/]*(\/element\/[^/]*)?\/screenshot/;
|
|
451
|
+
return (
|
|
452
|
+
// WebDriver protocol
|
|
453
|
+
(command.endpoint && isScrenshotEndpoint.test(command.endpoint)) ||
|
|
454
|
+
// DevTools protocol
|
|
455
|
+
command.command === 'takeScreenshot');
|
|
456
|
+
}
|
|
457
|
+
dumpJSON(name, json) {
|
|
458
|
+
const content = JSON.stringify(json, null, 2);
|
|
459
|
+
const isStr = typeof content === 'string';
|
|
460
|
+
this._allure.addAttachment(name, isStr ? content : `${content}`, isStr ? 'application/json' : 'text/plain');
|
|
461
|
+
}
|
|
462
|
+
attachScreenshot() {
|
|
463
|
+
if (this._lastScreenshot && !this._options.disableWebdriverScreenshotsReporting) {
|
|
464
|
+
this._allure.addAttachment('Screenshot', Buffer.from(this._lastScreenshot, 'base64'));
|
|
465
|
+
this._lastScreenshot = undefined;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* public API attached to the reporter
|
|
470
|
+
* deprecated approach and only here for backwards compatibility
|
|
471
|
+
*/
|
|
472
|
+
static addFeature = addFeature;
|
|
473
|
+
static addLabel = addLabel;
|
|
474
|
+
static addSeverity = addSeverity;
|
|
475
|
+
static addIssue = addIssue;
|
|
476
|
+
static addTestId = addTestId;
|
|
477
|
+
static addStory = addStory;
|
|
478
|
+
static addEnvironment = addEnvironment;
|
|
479
|
+
static addDescription = addDescription;
|
|
480
|
+
static addAttachment = addAttachment;
|
|
481
|
+
static startStep = startStep;
|
|
482
|
+
static endStep = endStep;
|
|
483
|
+
static addStep = addStep;
|
|
484
|
+
static addArgument = addArgument;
|
|
485
|
+
}
|
package/build/types.d.ts
CHANGED
|
@@ -94,4 +94,10 @@ export interface Attachment {
|
|
|
94
94
|
end(status: Status, error: Error, timestamp?: number): void;
|
|
95
95
|
toXML(): string;
|
|
96
96
|
}
|
|
97
|
+
declare global {
|
|
98
|
+
namespace WebdriverIO {
|
|
99
|
+
interface ReporterOption extends AllureReporterOptions {
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
97
103
|
//# sourceMappingURL=types.d.ts.map
|
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;OAEG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAA;IACxC;;OAEG;IACH,oCAAoC,CAAC,EAAE,OAAO,CAAA;IAC9C;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;MAGE;IACF,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,oBAAoB;IACjC,QAAQ,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,oBAAY,IAAI;IACZ,IAAI,SAAS;IACb,IAAI,SAAS;IACb,QAAQ,aAAa;CACxB;AAED,MAAM,WAAW,uBAAuB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,IAAI;IACjB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5C,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5D,KAAK,IAAI,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AACzF,MAAM,WAAW,UAAU;IACvB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5C,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5D,KAAK,IAAI,MAAM,CAAC;CACnB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;OAEG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAA;IACxC;;OAEG;IACH,oCAAoC,CAAC,EAAE,OAAO,CAAA;IAC9C;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;MAGE;IACF,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,oBAAoB;IACjC,QAAQ,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,oBAAY,IAAI;IACZ,IAAI,SAAS;IACb,IAAI,SAAS;IACb,QAAQ,aAAa;CACxB;AAED,MAAM,WAAW,uBAAuB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,IAAI;IACjB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5C,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5D,KAAK,IAAI,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AACzF,MAAM,WAAW,UAAU;IACvB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5C,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5D,KAAK,IAAI,MAAM,CAAC;CACnB;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,WAAW,CAAC;QAClB,UAAU,cAAe,SAAQ,qBAAqB;SAAI;KAC7D;CACJ"}
|
package/build/types.js
CHANGED
package/build/utils.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { HookStats, TestStats } from '@wdio/reporter';
|
|
1
|
+
import type { HookStats, TestStats } from '@wdio/reporter';
|
|
2
2
|
import type { Options } from '@wdio/types';
|
|
3
3
|
import CompoundError from './compoundError.js';
|
|
4
|
-
import AllureReporter from './
|
|
5
|
-
import type { Status } from './types';
|
|
4
|
+
import type AllureReporter from './reporter.js';
|
|
5
|
+
import type { Status } from './types.js';
|
|
6
6
|
/**
|
|
7
7
|
* Get allure test status by TestStat object
|
|
8
8
|
* @param test {Object} - TestStat object
|
|
@@ -30,13 +30,6 @@ export declare const isMochaEachHooks: (title: string) => boolean;
|
|
|
30
30
|
* @private
|
|
31
31
|
*/
|
|
32
32
|
export declare const isMochaAllHooks: (title: string) => boolean;
|
|
33
|
-
/**
|
|
34
|
-
* Call reporter
|
|
35
|
-
* @param {string} event - event name
|
|
36
|
-
* @param {Object} msg - event payload
|
|
37
|
-
* @private
|
|
38
|
-
*/
|
|
39
|
-
export declare const tellReporter: (event: string, msg?: any) => void;
|
|
40
33
|
/**
|
|
41
34
|
* Properly format error from different test runners
|
|
42
35
|
* @param {Object} test - TestStat object
|
package/build/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,aAAa,MAAM,oBAAoB,CAAA;AAE9C,OAAO,KAAK,cAAc,MAAM,eAAe,CAAA;AAC/C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAAU,SAAS,GAAG,SAAS,WAAW,QAAQ,UAAU,KAAI,MAiBzF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,OAAO,WAAY,GAAG,YAAgD,CAAA;AAEnF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,UAAW,MAAM,YAAsD,CAAA;AAEpG;;;;;GAKG;AACH,eAAO,MAAM,eAAe,UAAW,MAAM,YAAqD,CAAA;AAElG;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,SAAU,SAAS,GAAG,SAAS,KAAI,KAAK,GAAG,aAAa,GAAG,SAuB7F,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,aAAc,MAAM,GAAG,SAAS,MAAM,MAAM,WAQzE,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,SAAU,MAAM,GAAG,SAAS,UAAU,cAAc,CAAC,SAAS,CAAC,SAS5F,CAAA"}
|
package/build/utils.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import process from 'node:process';
|
|
2
1
|
import stripAnsi from 'strip-ansi';
|
|
3
2
|
import CompoundError from './compoundError.js';
|
|
4
3
|
import { mochaEachHooks, mochaAllHooks, linkPlaceholder } from './constants.js';
|
|
@@ -44,16 +43,6 @@ export const isMochaEachHooks = (title) => mochaEachHooks.some(hook => title.inc
|
|
|
44
43
|
* @private
|
|
45
44
|
*/
|
|
46
45
|
export const isMochaAllHooks = (title) => mochaAllHooks.some(hook => title.includes(hook));
|
|
47
|
-
/**
|
|
48
|
-
* Call reporter
|
|
49
|
-
* @param {string} event - event name
|
|
50
|
-
* @param {Object} msg - event payload
|
|
51
|
-
* @private
|
|
52
|
-
*/
|
|
53
|
-
export const tellReporter = (event, msg = {}) => {
|
|
54
|
-
// Node 14 typings does not accept string in process.emit, but allow string in process.on
|
|
55
|
-
process.emit(event, msg);
|
|
56
|
-
};
|
|
57
46
|
/**
|
|
58
47
|
* Properly format error from different test runners
|
|
59
48
|
* @param {Object} test - TestStat object
|
|
@@ -63,18 +52,22 @@ export const tellReporter = (event, msg = {}) => {
|
|
|
63
52
|
export const getErrorFromFailedTest = (test) => {
|
|
64
53
|
if (test.errors && Array.isArray(test.errors)) {
|
|
65
54
|
for (let i = 0; i < test.errors.length; i += 1) {
|
|
66
|
-
if (test.errors[i].message)
|
|
55
|
+
if (test.errors[i].message) {
|
|
67
56
|
test.errors[i].message = stripAnsi(test.errors[i].message);
|
|
68
|
-
|
|
57
|
+
}
|
|
58
|
+
if (test.errors[i].stack) {
|
|
69
59
|
test.errors[i].stack = stripAnsi(test.errors[i].stack);
|
|
60
|
+
}
|
|
70
61
|
}
|
|
71
62
|
return test.errors.length === 1 ? test.errors[0] : new CompoundError(...test.errors);
|
|
72
63
|
}
|
|
73
64
|
if (test.error) {
|
|
74
|
-
if (test.error.message)
|
|
65
|
+
if (test.error.message) {
|
|
75
66
|
test.error.message = stripAnsi(test.error.message);
|
|
76
|
-
|
|
67
|
+
}
|
|
68
|
+
if (test.error.stack) {
|
|
77
69
|
test.error.stack = stripAnsi(test.error.stack);
|
|
70
|
+
}
|
|
78
71
|
}
|
|
79
72
|
return test.error;
|
|
80
73
|
};
|