@wdio/cucumber-framework 7.17.0 → 7.19.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/index.js ADDED
@@ -0,0 +1,328 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.World = exports.When = exports.Then = exports.setWorldConstructor = exports.setDefinitionFunctionWrapper = exports.setDefaultTimeout = exports.Given = exports.defineStep = exports.defineParameterType = exports.DataTable = exports.BeforeStep = exports.BeforeAll = exports.Before = exports.AfterStep = exports.AfterAll = exports.After = exports.adapterFactory = exports.CucumberAdapter = void 0;
30
+ const path_1 = __importDefault(require("path"));
31
+ const events_1 = require("events");
32
+ const mockery_1 = __importDefault(require("mockery"));
33
+ const is_glob_1 = __importDefault(require("is-glob"));
34
+ const glob_1 = __importDefault(require("glob"));
35
+ const Cucumber = __importStar(require("@cucumber/cucumber"));
36
+ const cucumber_1 = require("@cucumber/cucumber");
37
+ Object.defineProperty(exports, "After", { enumerable: true, get: function () { return cucumber_1.After; } });
38
+ Object.defineProperty(exports, "AfterAll", { enumerable: true, get: function () { return cucumber_1.AfterAll; } });
39
+ Object.defineProperty(exports, "AfterStep", { enumerable: true, get: function () { return cucumber_1.AfterStep; } });
40
+ Object.defineProperty(exports, "Before", { enumerable: true, get: function () { return cucumber_1.Before; } });
41
+ Object.defineProperty(exports, "BeforeAll", { enumerable: true, get: function () { return cucumber_1.BeforeAll; } });
42
+ Object.defineProperty(exports, "BeforeStep", { enumerable: true, get: function () { return cucumber_1.BeforeStep; } });
43
+ Object.defineProperty(exports, "DataTable", { enumerable: true, get: function () { return cucumber_1.DataTable; } });
44
+ Object.defineProperty(exports, "defineParameterType", { enumerable: true, get: function () { return cucumber_1.defineParameterType; } });
45
+ Object.defineProperty(exports, "defineStep", { enumerable: true, get: function () { return cucumber_1.defineStep; } });
46
+ Object.defineProperty(exports, "Given", { enumerable: true, get: function () { return cucumber_1.Given; } });
47
+ Object.defineProperty(exports, "setDefaultTimeout", { enumerable: true, get: function () { return cucumber_1.setDefaultTimeout; } });
48
+ Object.defineProperty(exports, "setDefinitionFunctionWrapper", { enumerable: true, get: function () { return cucumber_1.setDefinitionFunctionWrapper; } });
49
+ Object.defineProperty(exports, "setWorldConstructor", { enumerable: true, get: function () { return cucumber_1.setWorldConstructor; } });
50
+ Object.defineProperty(exports, "World", { enumerable: true, get: function () { return cucumber_1.World; } });
51
+ Object.defineProperty(exports, "Then", { enumerable: true, get: function () { return cucumber_1.Then; } });
52
+ Object.defineProperty(exports, "When", { enumerable: true, get: function () { return cucumber_1.When; } });
53
+ const gherkin_streams_1 = require("@cucumber/gherkin-streams");
54
+ const event_data_collector_1 = __importDefault(require("@cucumber/cucumber/lib/formatter/helpers/event_data_collector"));
55
+ const messages_1 = require("@cucumber/messages");
56
+ const utils_1 = require("@wdio/utils");
57
+ const reporter_1 = __importDefault(require("./reporter"));
58
+ const constants_1 = require("./constants");
59
+ const utils_2 = require("./utils");
60
+ const { incrementing } = messages_1.IdGenerator;
61
+ function getResultObject(world) {
62
+ var _a, _b, _c, _d, _e;
63
+ return {
64
+ passed: (((_a = world.result) === null || _a === void 0 ? void 0 : _a.status) === Cucumber.Status.PASSED || ((_b = world.result) === null || _b === void 0 ? void 0 : _b.status) === Cucumber.Status.SKIPPED),
65
+ error: (_c = world.result) === null || _c === void 0 ? void 0 : _c.message,
66
+ duration: ((_e = (_d = world.result) === null || _d === void 0 ? void 0 : _d.duration) === null || _e === void 0 ? void 0 : _e.nanos) / 10e6 // convert into ms
67
+ };
68
+ }
69
+ class CucumberAdapter {
70
+ constructor(_cid, _config, _specs, _capabilities, _reporter) {
71
+ this._cid = _cid;
72
+ this._config = _config;
73
+ this._specs = _specs;
74
+ this._capabilities = _capabilities;
75
+ this._reporter = _reporter;
76
+ this._cwd = process.cwd();
77
+ this._newId = incrementing();
78
+ this._cucumberOpts = Object.assign({}, constants_1.DEFAULT_OPTS, this._config.cucumberOpts);
79
+ this._hasTests = true;
80
+ this._cucumberFeaturesWithLineNumbers = this._config.cucumberFeaturesWithLineNumbers || [];
81
+ this._eventBroadcaster = new events_1.EventEmitter();
82
+ this._eventDataCollector = new event_data_collector_1.default(this._eventBroadcaster);
83
+ const featurePathsToRun = this._cucumberFeaturesWithLineNumbers.length > 0 ? this._cucumberFeaturesWithLineNumbers : this._specs;
84
+ this._pickleFilter = new Cucumber.PickleFilter({
85
+ cwd: this._cwd,
86
+ featurePaths: featurePathsToRun,
87
+ names: this._cucumberOpts.names,
88
+ tagExpression: this._cucumberOpts.tagExpression
89
+ });
90
+ const reporterOptions = {
91
+ capabilities: this._capabilities,
92
+ ignoreUndefinedDefinitions: Boolean(this._cucumberOpts.ignoreUndefinedDefinitions),
93
+ failAmbiguousDefinitions: Boolean(this._cucumberOpts.failAmbiguousDefinitions),
94
+ tagsInTitle: Boolean(this._cucumberOpts.tagsInTitle),
95
+ scenarioLevelReporter: Boolean(this._cucumberOpts.scenarioLevelReporter)
96
+ };
97
+ this._cucumberReporter = new reporter_1.default(this._eventBroadcaster, this._pickleFilter, reporterOptions, this._cid, this._specs, this._reporter);
98
+ }
99
+ async init() {
100
+ try {
101
+ const gherkinMessageStream = gherkin_streams_1.GherkinStreams.fromPaths(this._specs, {
102
+ defaultDialect: this._cucumberOpts.featureDefaultLanguage,
103
+ newId: this._newId
104
+ });
105
+ await Cucumber.parseGherkinMessageStream({
106
+ cwd: this._cwd,
107
+ eventBroadcaster: this._eventBroadcaster,
108
+ gherkinMessageStream,
109
+ eventDataCollector: this._eventDataCollector,
110
+ order: this._cucumberOpts.order,
111
+ pickleFilter: this._pickleFilter
112
+ });
113
+ this._hasTests = this._cucumberReporter.eventListener.getPickleIds(this._capabilities).length > 0;
114
+ }
115
+ catch (runtimeError) {
116
+ await (0, utils_1.executeHooksWithArgs)('after', this._config.after, [runtimeError, this._capabilities, this._specs]);
117
+ throw runtimeError;
118
+ }
119
+ /**
120
+ * import and set options for `expect-webdriverio` assertion lib once
121
+ * the framework was initiated so that it can detect the environment
122
+ */
123
+ const { setOptions } = require('expect-webdriverio');
124
+ setOptions({
125
+ wait: this._config.waitforTimeout,
126
+ interval: this._config.waitforInterval, // interval between attempts
127
+ });
128
+ return this;
129
+ }
130
+ hasTests() {
131
+ return this._hasTests;
132
+ }
133
+ async run() {
134
+ let runtimeError;
135
+ let result;
136
+ try {
137
+ this.registerRequiredModules();
138
+ Cucumber.supportCodeLibraryBuilder.reset(this._cwd, this._newId);
139
+ /**
140
+ * wdio hooks should be added before spec files are loaded
141
+ */
142
+ this.addWdioHooks(this._config);
143
+ this.loadSpecFiles();
144
+ this.wrapSteps(this._config);
145
+ /**
146
+ * we need to somehow identify is function is step or hook
147
+ * so we wrap every user hook function
148
+ */
149
+ (0, utils_2.setUserHookNames)(Cucumber.supportCodeLibraryBuilder);
150
+ Cucumber.setDefaultTimeout(this._cucumberOpts.timeout);
151
+ const supportCodeLibrary = Cucumber.supportCodeLibraryBuilder.finalize();
152
+ /**
153
+ * gets current step data: `{ uri, feature, scenario, step, sourceLocation }`
154
+ * or `null` for some hooks.
155
+ */
156
+ this.getHookParams = this._cucumberReporter
157
+ .eventListener
158
+ .getHookParams
159
+ .bind(this._cucumberReporter.eventListener);
160
+ const runtime = new Cucumber.Runtime({
161
+ newId: this._newId,
162
+ eventBroadcaster: this._eventBroadcaster,
163
+ options: this._cucumberOpts,
164
+ supportCodeLibrary,
165
+ eventDataCollector: this._eventDataCollector,
166
+ pickleIds: this._cucumberReporter.eventListener.getPickleIds(this._capabilities)
167
+ });
168
+ result = await runtime.start() ? 0 : 1;
169
+ /**
170
+ * if we ignore undefined definitions we trust the reporter
171
+ * with the fail count
172
+ */
173
+ if (this._cucumberOpts.ignoreUndefinedDefinitions && result) {
174
+ result = this._cucumberReporter.failedCount;
175
+ }
176
+ }
177
+ catch (err) {
178
+ runtimeError = err;
179
+ result = 1;
180
+ }
181
+ await (0, utils_1.executeHooksWithArgs)('after', this._config.after, [runtimeError || result, this._capabilities, this._specs]);
182
+ /**
183
+ * in case the spec has a runtime error throw after the wdio hook
184
+ */
185
+ if (runtimeError) {
186
+ throw runtimeError;
187
+ }
188
+ return result;
189
+ }
190
+ /**
191
+ * Transpilation https://github.com/cucumber/cucumber-js/blob/master/docs/cli.md#transpilation
192
+ * Usage: `['module']`
193
+ * we extend it a bit with ability to init and pass configuration to modules.
194
+ * Pass an array with path to module and its configuration instead:
195
+ * Usage: `[['module', {}]]`
196
+ * Or pass your own function
197
+ * Usage: `[() => { require('@babel/register')({ ignore: [] }) }]`
198
+ */
199
+ registerRequiredModules() {
200
+ this._cucumberOpts.requireModule.map(requiredModule => {
201
+ if (Array.isArray(requiredModule)) {
202
+ require(requiredModule[0])(requiredModule[1]);
203
+ }
204
+ else if (typeof requiredModule === 'function') {
205
+ requiredModule();
206
+ }
207
+ else {
208
+ require(requiredModule);
209
+ }
210
+ });
211
+ }
212
+ requiredFiles() {
213
+ return this._cucumberOpts.require.reduce((files, requiredFile) => files.concat((0, is_glob_1.default)(requiredFile)
214
+ ? glob_1.default.sync(requiredFile)
215
+ : [requiredFile]), []);
216
+ }
217
+ loadSpecFiles() {
218
+ // we use mockery to allow people to import 'our' cucumber even though their spec files are in their folders
219
+ // because of that we don't have to attach anything to the global object, and the current cucumber spec files
220
+ // should just work with no changes with this framework
221
+ mockery_1.default.enable({
222
+ useCleanCache: false,
223
+ warnOnReplace: false,
224
+ warnOnUnregistered: false
225
+ });
226
+ mockery_1.default.registerMock('@cucumber/cucumber', Cucumber);
227
+ this.requiredFiles().forEach((codePath) => {
228
+ const filepath = path_1.default.isAbsolute(codePath)
229
+ ? codePath
230
+ : path_1.default.join(process.cwd(), codePath);
231
+ // This allows rerunning a stepDefinitions file
232
+ delete require.cache[require.resolve(filepath)];
233
+ require(filepath);
234
+ });
235
+ mockery_1.default.disable();
236
+ }
237
+ /**
238
+ * set `beforeFeature`, `afterFeature`, `beforeScenario`, `afterScenario`, 'beforeStep', 'afterStep'
239
+ * @param {object} config config
240
+ */
241
+ addWdioHooks(config) {
242
+ var _a;
243
+ const eventListener = (_a = this._cucumberReporter) === null || _a === void 0 ? void 0 : _a.eventListener;
244
+ Cucumber.BeforeAll(async function wdioHookBeforeFeature() {
245
+ const params = eventListener === null || eventListener === void 0 ? void 0 : eventListener.getHookParams();
246
+ await (0, utils_1.executeHooksWithArgs)('beforeFeature', config.beforeFeature, [params === null || params === void 0 ? void 0 : params.uri, params === null || params === void 0 ? void 0 : params.feature]);
247
+ });
248
+ Cucumber.AfterAll(async function wdioHookAfterFeature() {
249
+ const params = eventListener === null || eventListener === void 0 ? void 0 : eventListener.getHookParams();
250
+ await (0, utils_1.executeHooksWithArgs)('afterFeature', config.afterFeature, [params === null || params === void 0 ? void 0 : params.uri, params === null || params === void 0 ? void 0 : params.feature]);
251
+ });
252
+ Cucumber.Before(async function wdioHookBeforeScenario(world) {
253
+ await (0, utils_1.executeHooksWithArgs)('beforeScenario', config.beforeScenario, [world, this]);
254
+ });
255
+ Cucumber.After(async function wdioHookAfterScenario(world) {
256
+ await (0, utils_1.executeHooksWithArgs)('afterScenario', config.afterScenario, [world, getResultObject(world), this]);
257
+ });
258
+ Cucumber.BeforeStep(async function wdioHookBeforeStep() {
259
+ const params = eventListener === null || eventListener === void 0 ? void 0 : eventListener.getHookParams();
260
+ await (0, utils_1.executeHooksWithArgs)('beforeStep', config.beforeStep, [params === null || params === void 0 ? void 0 : params.step, params === null || params === void 0 ? void 0 : params.scenario, this]);
261
+ });
262
+ Cucumber.AfterStep(async function wdioHookAfterStep(world) {
263
+ const params = eventListener === null || eventListener === void 0 ? void 0 : eventListener.getHookParams();
264
+ await (0, utils_1.executeHooksWithArgs)('afterStep', config.afterStep, [params === null || params === void 0 ? void 0 : params.step, params === null || params === void 0 ? void 0 : params.scenario, getResultObject(world), this]);
265
+ });
266
+ }
267
+ /**
268
+ * wraps step definition code with sync/async runner with a retry option
269
+ * @param {object} config
270
+ */
271
+ wrapSteps(config) {
272
+ const wrapStep = this.wrapStep;
273
+ const cid = this._cid;
274
+ const getHookParams = () => this.getHookParams && this.getHookParams();
275
+ Cucumber.setDefinitionFunctionWrapper((fn, options = { retry: 0 }) => {
276
+ /**
277
+ * hooks defined in wdio.conf are already wrapped
278
+ */
279
+ if (fn.name.startsWith('wdioHook')) {
280
+ return fn;
281
+ }
282
+ /**
283
+ * this flag is used to:
284
+ * - avoid hook retry
285
+ * - avoid wrap hooks with beforeStep and afterStep
286
+ */
287
+ const isStep = !fn.name.startsWith('userHook');
288
+ return wrapStep(fn, isStep, config, cid, options, getHookParams);
289
+ });
290
+ }
291
+ /**
292
+ * wrap step definition to enable retry ability
293
+ * @param {Function} code step definition
294
+ * @param {boolean} isStep
295
+ * @param {object} config
296
+ * @param {string} cid cid
297
+ * @param {StepDefinitionOptions} options
298
+ * @param {Function} getHookParams step definition
299
+ * @return {Function} wrapped step definition for sync WebdriverIO code
300
+ */
301
+ wrapStep(code, isStep, config, cid, options, getHookParams) {
302
+ return function (...args) {
303
+ const hookParams = getHookParams();
304
+ const retryTest = isStep && isFinite(options.retry) ? options.retry : 0;
305
+ /**
306
+ * wrap user step/hook with wdio before/after hooks
307
+ */
308
+ const beforeFn = config.beforeHook;
309
+ const afterFn = config.afterHook;
310
+ return utils_1.testFnWrapper.call(this, isStep ? 'Step' : 'Hook', { specFn: code, specFnArgs: args }, { beforeFn: beforeFn, beforeFnArgs: (context) => [hookParams === null || hookParams === void 0 ? void 0 : hookParams.step, context] }, { afterFn: afterFn, afterFnArgs: (context) => [hookParams === null || hookParams === void 0 ? void 0 : hookParams.step, context] }, cid, retryTest);
311
+ };
312
+ }
313
+ }
314
+ exports.CucumberAdapter = CucumberAdapter;
315
+ const _CucumberAdapter = CucumberAdapter;
316
+ const adapterFactory = {};
317
+ exports.adapterFactory = adapterFactory;
318
+ /**
319
+ * tested by smoke tests
320
+ */
321
+ /* istanbul ignore next */
322
+ adapterFactory.init = async function (...args) {
323
+ // @ts-ignore just passing through args
324
+ const adapter = new _CucumberAdapter(...args);
325
+ const instance = await adapter.init();
326
+ return instance;
327
+ };
328
+ exports.default = adapterFactory;
@@ -0,0 +1,33 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import { PickleFilter } from '@cucumber/cucumber';
4
+ import { Feature, Pickle, PickleStep, TestStep, TestStepResult } from '@cucumber/messages';
5
+ import CucumberEventListener from './cucumberEventListener';
6
+ import type { ReporterOptions } from './types';
7
+ import { ReporterScenario } from './constants';
8
+ declare class CucumberReporter {
9
+ private _options;
10
+ private _cid;
11
+ private _specs;
12
+ private _reporter;
13
+ eventListener: CucumberEventListener;
14
+ failedCount: number;
15
+ private _tagsInTitle;
16
+ private _scenarioLevelReport;
17
+ private _featureStart?;
18
+ private _scenarioStart?;
19
+ private _testStart?;
20
+ constructor(eventBroadcaster: EventEmitter, pickleFilter: PickleFilter, _options: ReporterOptions, _cid: string, _specs: string[], _reporter: EventEmitter);
21
+ handleBeforeFeature(uri: string, feature: Feature): void;
22
+ handleBeforeScenario(uri: string, feature: Feature, scenario: ReporterScenario): void;
23
+ handleBeforeStep(uri: string, feature: Feature, scenario: Pickle, step: PickleStep | TestStep): void;
24
+ handleAfterStep(uri: string, feature: Feature, scenario: Pickle, step: PickleStep | TestStep, result: TestStepResult): void;
25
+ afterHook(uri: string, feature: Feature, scenario: Pickle, step: TestStep, result: TestStepResult): void;
26
+ afterTest(uri: string, feature: Feature, scenario: Pickle, step: PickleStep, result: TestStepResult): void;
27
+ handleAfterScenario(uri: string, feature: Feature, scenario: Pickle, result: TestStepResult): void;
28
+ handleAfterFeature(uri: string, feature: Feature): void;
29
+ emit(event: string, payload: any): void;
30
+ getTitle(featureOrScenario: Feature | Pickle): string;
31
+ }
32
+ export default CucumberReporter;
33
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAU,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAoC,MAAM,oBAAoB,CAAA;AAE5H,OAAO,qBAAqB,MAAM,yBAAyB,CAAA;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9C,cAAM,gBAAgB;IAad,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IAfd,aAAa,EAAE,qBAAqB,CAAA;IACpC,WAAW,SAAI;IAEtB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,aAAa,CAAC,CAAM;IAC5B,OAAO,CAAC,cAAc,CAAC,CAAM;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAM;gBAGrB,gBAAgB,EAAE,YAAY,EAC9B,YAAY,EAAE,YAAY,EAClB,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EAAE,EAChB,SAAS,EAAE,YAAY;IAkBnC,mBAAmB,CAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAclD,oBAAoB,CAChB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,gBAAgB;IAgB9B,gBAAgB,CACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,GAAG,QAAQ;IAS/B,eAAe,CACX,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,GAAG,QAAQ,EAC3B,MAAM,EAAE,cAAc;IAS1B,SAAS,CACL,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,cAAc;IAkB1B,SAAS,CACL,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,cAAc;IA+F1B,mBAAmB,CACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc;IAiB1B,kBAAkB,CAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IAWjD,IAAI,CAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG;IAUjC,QAAQ,CAAE,iBAAiB,EAAE,OAAO,GAAG,MAAM;CAMhD;AAED,eAAe,gBAAgB,CAAA"}
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const cucumber_1 = require("@cucumber/cucumber");
7
+ const cucumberEventListener_1 = __importDefault(require("./cucumberEventListener"));
8
+ const utils_1 = require("./utils");
9
+ class CucumberReporter {
10
+ constructor(eventBroadcaster, pickleFilter, _options, _cid, _specs, _reporter) {
11
+ this._options = _options;
12
+ this._cid = _cid;
13
+ this._specs = _specs;
14
+ this._reporter = _reporter;
15
+ this.failedCount = 0;
16
+ this._tagsInTitle = this._options.tagsInTitle || false;
17
+ this._scenarioLevelReport = this._options.scenarioLevelReporter;
18
+ this.eventListener = new cucumberEventListener_1.default(eventBroadcaster, pickleFilter)
19
+ .on('before-feature', this.handleBeforeFeature.bind(this))
20
+ .on('before-scenario', this.handleBeforeScenario.bind(this))
21
+ .on('after-scenario', this.handleAfterScenario.bind(this))
22
+ .on('after-feature', this.handleAfterFeature.bind(this));
23
+ if (!this._scenarioLevelReport) {
24
+ this.eventListener
25
+ .on('before-step', this.handleBeforeStep.bind(this))
26
+ .on('after-step', this.handleAfterStep.bind(this));
27
+ }
28
+ }
29
+ handleBeforeFeature(uri, feature) {
30
+ this._featureStart = new Date();
31
+ this.emit('suite:start', {
32
+ uid: (0, utils_1.getFeatureId)(uri, feature),
33
+ title: this.getTitle(feature),
34
+ type: 'feature',
35
+ file: uri,
36
+ tags: feature.tags,
37
+ description: feature.description,
38
+ keyword: feature.keyword
39
+ });
40
+ }
41
+ handleBeforeScenario(uri, feature, scenario) {
42
+ this._scenarioStart = new Date();
43
+ this._testStart = new Date();
44
+ this.emit(this._scenarioLevelReport ? 'test:start' : 'suite:start', {
45
+ uid: scenario.id,
46
+ title: this.getTitle(scenario),
47
+ parent: (0, utils_1.getFeatureId)(uri, feature),
48
+ type: 'scenario',
49
+ file: uri,
50
+ tags: scenario.tags,
51
+ rule: scenario.rule
52
+ });
53
+ }
54
+ handleBeforeStep(uri, feature, scenario, step) {
55
+ this._testStart = new Date();
56
+ const type = (0, utils_1.getStepType)(step);
57
+ const payload = (0, utils_1.buildStepPayload)(uri, feature, scenario, step, { type });
58
+ this.emit(`${type}:start`, payload);
59
+ }
60
+ handleAfterStep(uri, feature, scenario, step, result) {
61
+ const type = (0, utils_1.getStepType)(step);
62
+ if (type === 'hook') {
63
+ return this.afterHook(uri, feature, scenario, step, result);
64
+ }
65
+ return this.afterTest(uri, feature, scenario, step, result);
66
+ }
67
+ afterHook(uri, feature, scenario, step, result) {
68
+ var _a;
69
+ let error;
70
+ if (result.message) {
71
+ error = new Error(result.message.split('\n')[0]);
72
+ error.stack = result.message;
73
+ }
74
+ const payload = (0, utils_1.buildStepPayload)(uri, feature, scenario, step, {
75
+ type: 'hook',
76
+ state: result.status,
77
+ error,
78
+ duration: Date.now() - ((_a = this._testStart) === null || _a === void 0 ? void 0 : _a.getTime())
79
+ });
80
+ this.emit('hook:end', payload);
81
+ }
82
+ afterTest(uri, feature, scenario, step, result) {
83
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
84
+ let state = 'undefined';
85
+ switch (result.status) {
86
+ case cucumber_1.Status.FAILED:
87
+ case cucumber_1.Status.UNDEFINED:
88
+ state = 'fail';
89
+ break;
90
+ case cucumber_1.Status.PASSED:
91
+ state = 'pass';
92
+ break;
93
+ case cucumber_1.Status.PENDING:
94
+ state = 'pending';
95
+ break;
96
+ case cucumber_1.Status.SKIPPED:
97
+ state = 'skip';
98
+ break;
99
+ case cucumber_1.Status.AMBIGUOUS:
100
+ state = 'pending';
101
+ break;
102
+ }
103
+ let error = result.message ? new Error(result.message) : undefined;
104
+ let title = step
105
+ ? step === null || step === void 0 ? void 0 : step.text
106
+ : this.getTitle(scenario);
107
+ if (result.status === cucumber_1.Status.UNDEFINED) {
108
+ if (this._options.ignoreUndefinedDefinitions) {
109
+ /**
110
+ * mark test as pending
111
+ */
112
+ state = 'pending';
113
+ title += ' (undefined step)';
114
+ }
115
+ else {
116
+ /**
117
+ * mark test as failed
118
+ */
119
+ this.failedCount++;
120
+ const err = new Error((step ? `Step "${title}" is not defined. ` : `Scenario ${title} has undefined steps. `) +
121
+ 'You can ignore this error by setting cucumberOpts.ignoreUndefinedDefinitions as true.');
122
+ err.stack = `${err.message}\n\tat Feature(${uri}):1:1\n`;
123
+ const featChildren = (_a = feature.children) === null || _a === void 0 ? void 0 : _a.find(c => { var _a; return scenario.astNodeIds && ((_a = c.scenario) === null || _a === void 0 ? void 0 : _a.id) === scenario.astNodeIds[0]; });
124
+ if (featChildren) {
125
+ err.stack += `\tat Scenario(${(_b = featChildren.scenario) === null || _b === void 0 ? void 0 : _b.name}):${(_d = (_c = featChildren.scenario) === null || _c === void 0 ? void 0 : _c.location) === null || _d === void 0 ? void 0 : _d.line}:${(_f = (_e = featChildren.scenario) === null || _e === void 0 ? void 0 : _e.location) === null || _f === void 0 ? void 0 : _f.column}\n`;
126
+ const featStep = (_h = (_g = featChildren.scenario) === null || _g === void 0 ? void 0 : _g.steps) === null || _h === void 0 ? void 0 : _h.find(s => step.astNodeIds && s.id === step.astNodeIds[0]);
127
+ if (featStep) {
128
+ err.stack += `\tat Step(${featStep.text}):${(_j = featStep.location) === null || _j === void 0 ? void 0 : _j.line}:${(_k = featStep.location) === null || _k === void 0 ? void 0 : _k.column}\n`;
129
+ }
130
+ }
131
+ error = err;
132
+ }
133
+ }
134
+ else if (result.status === cucumber_1.Status.FAILED && !result.willBeRetried) {
135
+ error = new Error((_l = result.message) === null || _l === void 0 ? void 0 : _l.split('\n')[0]);
136
+ error.stack = result.message;
137
+ this.failedCount++;
138
+ }
139
+ else if (result.status === cucumber_1.Status.AMBIGUOUS && this._options.failAmbiguousDefinitions) {
140
+ state = 'fail';
141
+ this.failedCount++;
142
+ error = new Error((_m = result.message) === null || _m === void 0 ? void 0 : _m.split('\n')[0]);
143
+ error.stack = result.message;
144
+ }
145
+ else if (result.willBeRetried) {
146
+ state = 'retry';
147
+ }
148
+ const common = {
149
+ title: title,
150
+ state,
151
+ error,
152
+ duration: Date.now() - ((_o = this._testStart) === null || _o === void 0 ? void 0 : _o.getTime()),
153
+ passed: ['pass', 'skip'].includes(state),
154
+ file: uri
155
+ };
156
+ const payload = step
157
+ ? (0, utils_1.buildStepPayload)(uri, feature, scenario, step, {
158
+ type: 'step',
159
+ ...common
160
+ })
161
+ : {
162
+ type: 'scenario',
163
+ uid: scenario.id,
164
+ parent: (0, utils_1.getFeatureId)(uri, feature),
165
+ tags: scenario.tags,
166
+ ...common
167
+ };
168
+ this.emit('test:' + state, payload);
169
+ }
170
+ handleAfterScenario(uri, feature, scenario, result) {
171
+ var _a;
172
+ if (this._scenarioLevelReport) {
173
+ return this.afterTest(uri, feature, scenario, { id: scenario.id }, result);
174
+ }
175
+ this.emit('suite:end', {
176
+ uid: scenario.id,
177
+ title: this.getTitle(scenario),
178
+ parent: (0, utils_1.getFeatureId)(uri, feature),
179
+ type: 'scenario',
180
+ file: uri,
181
+ duration: Date.now() - ((_a = this._scenarioStart) === null || _a === void 0 ? void 0 : _a.getTime()),
182
+ tags: scenario.tags
183
+ });
184
+ }
185
+ handleAfterFeature(uri, feature) {
186
+ var _a;
187
+ this.emit('suite:end', {
188
+ uid: (0, utils_1.getFeatureId)(uri, feature),
189
+ title: this.getTitle(feature),
190
+ type: 'feature',
191
+ file: uri,
192
+ duration: Date.now() - ((_a = this._featureStart) === null || _a === void 0 ? void 0 : _a.getTime()),
193
+ tags: feature.tags
194
+ });
195
+ }
196
+ emit(event, payload) {
197
+ let message = (0, utils_1.formatMessage)({ payload });
198
+ message.cid = this._cid;
199
+ message.specs = this._specs;
200
+ message.uid = payload.uid;
201
+ this._reporter.emit(event, message);
202
+ }
203
+ getTitle(featureOrScenario) {
204
+ const name = featureOrScenario.name;
205
+ const tags = featureOrScenario.tags;
206
+ if (!this._tagsInTitle || !tags || !tags.length)
207
+ return name;
208
+ return `${tags.map((tag) => tag.name).join(', ')}: ${name}`;
209
+ }
210
+ }
211
+ exports.default = CucumberReporter;