@autometa/executor 1.0.0-rc.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/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/async-context.d.ts +5 -0
- package/dist/events.d.ts +5 -0
- package/dist/execute-plan.d.ts +13 -0
- package/dist/hooks.d.ts +19 -0
- package/dist/index.cjs +2409 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +2345 -0
- package/dist/index.js.map +1 -0
- package/dist/modes.d.ts +5 -0
- package/dist/pending.d.ts +23 -0
- package/dist/runtime/step-data.d.ts +112 -0
- package/dist/scenario-runner.d.ts +4 -0
- package/dist/scope-lifecycle.d.ts +138 -0
- package/dist/tag-filter.d.ts +4 -0
- package/dist/timeouts.d.ts +9 -0
- package/dist/types.d.ts +31 -0
- package/package.json +59 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2409 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var url = require('url');
|
|
7
|
+
var cucumberExpressions = require('@cucumber/cucumber-expressions');
|
|
8
|
+
var events = require('@autometa/events');
|
|
9
|
+
var errors = require('@autometa/errors');
|
|
10
|
+
var gherkin = require('@autometa/gherkin');
|
|
11
|
+
var TagExpressions = require('@cucumber/tag-expressions');
|
|
12
|
+
var async_hooks = require('async_hooks');
|
|
13
|
+
|
|
14
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
+
|
|
16
|
+
function _interopNamespace(e) {
|
|
17
|
+
if (e && e.__esModule) return e;
|
|
18
|
+
var n = Object.create(null);
|
|
19
|
+
if (e) {
|
|
20
|
+
Object.keys(e).forEach(function (k) {
|
|
21
|
+
if (k !== 'default') {
|
|
22
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
23
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function () { return e[k]; }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
n.default = e;
|
|
31
|
+
return Object.freeze(n);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
35
|
+
var TagExpressions__namespace = /*#__PURE__*/_interopNamespace(TagExpressions);
|
|
36
|
+
|
|
37
|
+
// src/timeouts.ts
|
|
38
|
+
var UNIT_TO_MILLISECONDS = {
|
|
39
|
+
ms: 1,
|
|
40
|
+
s: 1e3,
|
|
41
|
+
m: 6e4,
|
|
42
|
+
h: 36e5
|
|
43
|
+
};
|
|
44
|
+
var normalizeSpec = (spec) => {
|
|
45
|
+
if (spec === void 0 || spec === null) {
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
if (typeof spec === "number") {
|
|
49
|
+
return spec <= 0 ? void 0 : spec;
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(spec)) {
|
|
52
|
+
const [value2, unit2] = spec;
|
|
53
|
+
if (typeof value2 !== "number" || value2 <= 0) {
|
|
54
|
+
return void 0;
|
|
55
|
+
}
|
|
56
|
+
const multiplier2 = UNIT_TO_MILLISECONDS[unit2] ?? 1;
|
|
57
|
+
return value2 * multiplier2;
|
|
58
|
+
}
|
|
59
|
+
if (typeof spec !== "object") {
|
|
60
|
+
return void 0;
|
|
61
|
+
}
|
|
62
|
+
const value = "duration" in spec ? spec.duration : spec.value;
|
|
63
|
+
if (typeof value !== "number" || value <= 0) {
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
const unit = "duration" in spec ? spec.unit : spec.unit;
|
|
67
|
+
if (!unit) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
const multiplier = UNIT_TO_MILLISECONDS[unit] ?? 1;
|
|
71
|
+
return value * multiplier;
|
|
72
|
+
};
|
|
73
|
+
var resolveTimeout = (explicit, config, explicitSource = "scenario") => {
|
|
74
|
+
const explicitMs = normalizeSpec(explicit);
|
|
75
|
+
if (explicitMs !== void 0) {
|
|
76
|
+
return { milliseconds: explicitMs, source: explicitSource };
|
|
77
|
+
}
|
|
78
|
+
const configMs = normalizeSpec(config.test?.timeout);
|
|
79
|
+
if (configMs !== void 0) {
|
|
80
|
+
return { milliseconds: configMs, source: "config" };
|
|
81
|
+
}
|
|
82
|
+
return { milliseconds: void 0, source: "default" };
|
|
83
|
+
};
|
|
84
|
+
var chooseTimeout = (primary, secondary, config) => {
|
|
85
|
+
const secondaryResolution = resolveTimeout(secondary, config, "hook");
|
|
86
|
+
if (secondaryResolution.milliseconds !== void 0) {
|
|
87
|
+
return secondaryResolution;
|
|
88
|
+
}
|
|
89
|
+
return resolveTimeout(primary, config, "scenario");
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/hooks.ts
|
|
93
|
+
var EMPTY_COLLECTION = {
|
|
94
|
+
beforeFeature: [],
|
|
95
|
+
afterFeature: [],
|
|
96
|
+
beforeRule: [],
|
|
97
|
+
afterRule: [],
|
|
98
|
+
beforeScenario: [],
|
|
99
|
+
afterScenario: [],
|
|
100
|
+
beforeScenarioOutline: [],
|
|
101
|
+
afterScenarioOutline: [],
|
|
102
|
+
beforeStep: [],
|
|
103
|
+
afterStep: []
|
|
104
|
+
};
|
|
105
|
+
function collectScenarioHooks(adapter, execution) {
|
|
106
|
+
const scopes = buildScopeChain(adapter, execution);
|
|
107
|
+
if (scopes.length === 0) {
|
|
108
|
+
return EMPTY_COLLECTION;
|
|
109
|
+
}
|
|
110
|
+
const buckets = {
|
|
111
|
+
beforeFeature: [],
|
|
112
|
+
afterFeature: [],
|
|
113
|
+
beforeRule: [],
|
|
114
|
+
afterRule: [],
|
|
115
|
+
beforeScenario: [],
|
|
116
|
+
afterScenario: [],
|
|
117
|
+
beforeScenarioOutline: [],
|
|
118
|
+
afterScenarioOutline: [],
|
|
119
|
+
beforeStep: [],
|
|
120
|
+
afterStep: []
|
|
121
|
+
};
|
|
122
|
+
for (const scope of scopes) {
|
|
123
|
+
for (const hook of scope.hooks) {
|
|
124
|
+
addHookToBuckets(buckets, hook, scope);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return buckets;
|
|
128
|
+
}
|
|
129
|
+
function buildScopeChain(adapter, execution) {
|
|
130
|
+
const chain = [adapter.plan.root];
|
|
131
|
+
chain.push(...execution.ancestors);
|
|
132
|
+
chain.push(execution.scope);
|
|
133
|
+
return chain;
|
|
134
|
+
}
|
|
135
|
+
function addHookToBuckets(buckets, hook, scope) {
|
|
136
|
+
const entry = { hook, scope };
|
|
137
|
+
switch (hook.type) {
|
|
138
|
+
case "beforeFeature":
|
|
139
|
+
buckets.beforeFeature.push(entry);
|
|
140
|
+
break;
|
|
141
|
+
case "afterFeature":
|
|
142
|
+
buckets.afterFeature.push(entry);
|
|
143
|
+
break;
|
|
144
|
+
case "beforeRule":
|
|
145
|
+
buckets.beforeRule.push(entry);
|
|
146
|
+
break;
|
|
147
|
+
case "afterRule":
|
|
148
|
+
buckets.afterRule.push(entry);
|
|
149
|
+
break;
|
|
150
|
+
case "beforeScenario":
|
|
151
|
+
buckets.beforeScenario.push(entry);
|
|
152
|
+
break;
|
|
153
|
+
case "afterScenario":
|
|
154
|
+
buckets.afterScenario.push(entry);
|
|
155
|
+
break;
|
|
156
|
+
case "beforeScenarioOutline":
|
|
157
|
+
buckets.beforeScenarioOutline.push(entry);
|
|
158
|
+
break;
|
|
159
|
+
case "afterScenarioOutline":
|
|
160
|
+
buckets.afterScenarioOutline.push(entry);
|
|
161
|
+
break;
|
|
162
|
+
case "beforeStep":
|
|
163
|
+
buckets.beforeStep.push(entry);
|
|
164
|
+
break;
|
|
165
|
+
case "afterStep":
|
|
166
|
+
buckets.afterStep.push(entry);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
var DATA_TABLE_SYMBOL = Symbol.for(
|
|
171
|
+
"autometa:runner:step:data-table"
|
|
172
|
+
);
|
|
173
|
+
var DOCSTRING_SYMBOL = Symbol.for(
|
|
174
|
+
"autometa:runner:step:docstring"
|
|
175
|
+
);
|
|
176
|
+
var DOCSTRING_MEDIA_TYPE_SYMBOL = Symbol.for(
|
|
177
|
+
"autometa:runner:step:docstring:media-type"
|
|
178
|
+
);
|
|
179
|
+
var STEP_RUNTIME_SYMBOL = Symbol.for(
|
|
180
|
+
"autometa:runner:step:runtime"
|
|
181
|
+
);
|
|
182
|
+
var STEP_METADATA_SYMBOL = Symbol.for(
|
|
183
|
+
"autometa:runner:step:metadata"
|
|
184
|
+
);
|
|
185
|
+
var DEFAULT_CONFIG = { ...gherkin.DEFAULT_COERCE_BY_SHAPE };
|
|
186
|
+
var activeConfig = { ...DEFAULT_CONFIG };
|
|
187
|
+
var DEFAULT_DOCSTRING_CONFIG = { transformers: {} };
|
|
188
|
+
var activeDocstringConfig = { ...DEFAULT_DOCSTRING_CONFIG };
|
|
189
|
+
function isObjectLike(value) {
|
|
190
|
+
return typeof value === "object" && value !== null;
|
|
191
|
+
}
|
|
192
|
+
function cloneTable(source) {
|
|
193
|
+
return source.map((row) => [...row]);
|
|
194
|
+
}
|
|
195
|
+
function withCarrier(world) {
|
|
196
|
+
if (!isObjectLike(world)) {
|
|
197
|
+
return void 0;
|
|
198
|
+
}
|
|
199
|
+
return world;
|
|
200
|
+
}
|
|
201
|
+
function configureStepTables(config) {
|
|
202
|
+
if (config.coercePrimitives) {
|
|
203
|
+
activeConfig = {
|
|
204
|
+
...activeConfig,
|
|
205
|
+
...config.coercePrimitives
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function resetStepTableConfig() {
|
|
210
|
+
activeConfig = { ...DEFAULT_CONFIG };
|
|
211
|
+
}
|
|
212
|
+
function setStepTable(world, table) {
|
|
213
|
+
const carrier = withCarrier(world);
|
|
214
|
+
if (!carrier) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (!table) {
|
|
218
|
+
Reflect.deleteProperty(carrier, DATA_TABLE_SYMBOL);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const cloned = cloneTable(table);
|
|
222
|
+
if (Object.prototype.hasOwnProperty.call(carrier, DATA_TABLE_SYMBOL)) {
|
|
223
|
+
carrier[DATA_TABLE_SYMBOL] = cloned;
|
|
224
|
+
} else {
|
|
225
|
+
Object.defineProperty(carrier, DATA_TABLE_SYMBOL, {
|
|
226
|
+
value: cloned,
|
|
227
|
+
writable: true,
|
|
228
|
+
configurable: true,
|
|
229
|
+
enumerable: false
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function clearStepTable(world) {
|
|
234
|
+
const carrier = withCarrier(world);
|
|
235
|
+
if (!carrier) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
Reflect.deleteProperty(carrier, DATA_TABLE_SYMBOL);
|
|
239
|
+
}
|
|
240
|
+
function setStepDocstring(world, docstring) {
|
|
241
|
+
const carrier = withCarrier(world);
|
|
242
|
+
if (!carrier) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (docstring === void 0) {
|
|
246
|
+
Reflect.deleteProperty(carrier, DOCSTRING_SYMBOL);
|
|
247
|
+
Reflect.deleteProperty(carrier, DOCSTRING_MEDIA_TYPE_SYMBOL);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (Object.prototype.hasOwnProperty.call(carrier, DOCSTRING_SYMBOL)) {
|
|
251
|
+
carrier[DOCSTRING_SYMBOL] = docstring;
|
|
252
|
+
} else {
|
|
253
|
+
Object.defineProperty(carrier, DOCSTRING_SYMBOL, {
|
|
254
|
+
value: docstring,
|
|
255
|
+
writable: true,
|
|
256
|
+
configurable: true,
|
|
257
|
+
enumerable: false
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
Reflect.deleteProperty(carrier, DOCSTRING_MEDIA_TYPE_SYMBOL);
|
|
261
|
+
}
|
|
262
|
+
function setStepDocstringInfo(world, docstring) {
|
|
263
|
+
if (docstring === void 0) {
|
|
264
|
+
setStepDocstring(world, void 0);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
setStepDocstring(world, docstring.content);
|
|
268
|
+
const carrier = withCarrier(world);
|
|
269
|
+
if (!carrier) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const mediaType = docstring.mediaType;
|
|
273
|
+
if (mediaType === void 0) {
|
|
274
|
+
Reflect.deleteProperty(carrier, DOCSTRING_MEDIA_TYPE_SYMBOL);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (Object.prototype.hasOwnProperty.call(carrier, DOCSTRING_MEDIA_TYPE_SYMBOL)) {
|
|
278
|
+
carrier[DOCSTRING_MEDIA_TYPE_SYMBOL] = mediaType;
|
|
279
|
+
} else {
|
|
280
|
+
Object.defineProperty(carrier, DOCSTRING_MEDIA_TYPE_SYMBOL, {
|
|
281
|
+
value: mediaType,
|
|
282
|
+
writable: true,
|
|
283
|
+
configurable: true,
|
|
284
|
+
enumerable: false
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function clearStepDocstring(world) {
|
|
289
|
+
const carrier = withCarrier(world);
|
|
290
|
+
if (!carrier) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
Reflect.deleteProperty(carrier, DOCSTRING_SYMBOL);
|
|
294
|
+
Reflect.deleteProperty(carrier, DOCSTRING_MEDIA_TYPE_SYMBOL);
|
|
295
|
+
}
|
|
296
|
+
function setStepMetadata(world, metadata) {
|
|
297
|
+
const carrier = withCarrier(world);
|
|
298
|
+
if (!carrier) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (!metadata) {
|
|
302
|
+
Reflect.deleteProperty(carrier, STEP_METADATA_SYMBOL);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (Object.prototype.hasOwnProperty.call(carrier, STEP_METADATA_SYMBOL)) {
|
|
306
|
+
carrier[STEP_METADATA_SYMBOL] = metadata;
|
|
307
|
+
} else {
|
|
308
|
+
Object.defineProperty(carrier, STEP_METADATA_SYMBOL, {
|
|
309
|
+
value: metadata,
|
|
310
|
+
writable: true,
|
|
311
|
+
configurable: true,
|
|
312
|
+
enumerable: false
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function clearStepMetadata(world) {
|
|
317
|
+
const carrier = withCarrier(world);
|
|
318
|
+
if (!carrier) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
Reflect.deleteProperty(carrier, STEP_METADATA_SYMBOL);
|
|
322
|
+
}
|
|
323
|
+
function getStepMetadata(world) {
|
|
324
|
+
const carrier = withCarrier(world);
|
|
325
|
+
return carrier?.[STEP_METADATA_SYMBOL];
|
|
326
|
+
}
|
|
327
|
+
function getDocstring(world) {
|
|
328
|
+
const carrier = withCarrier(world);
|
|
329
|
+
return carrier?.[DOCSTRING_SYMBOL];
|
|
330
|
+
}
|
|
331
|
+
function getDocstringMediaType(world) {
|
|
332
|
+
const carrier = withCarrier(world);
|
|
333
|
+
return carrier?.[DOCSTRING_MEDIA_TYPE_SYMBOL];
|
|
334
|
+
}
|
|
335
|
+
function getDocstringInfo(world) {
|
|
336
|
+
const content = getDocstring(world);
|
|
337
|
+
if (content === void 0) {
|
|
338
|
+
return void 0;
|
|
339
|
+
}
|
|
340
|
+
const mediaType = getDocstringMediaType(world);
|
|
341
|
+
if (mediaType === void 0) {
|
|
342
|
+
return { content };
|
|
343
|
+
}
|
|
344
|
+
return { content, mediaType };
|
|
345
|
+
}
|
|
346
|
+
function getRawTable(world) {
|
|
347
|
+
const carrier = withCarrier(world);
|
|
348
|
+
return carrier?.[DATA_TABLE_SYMBOL];
|
|
349
|
+
}
|
|
350
|
+
function getStepRuntimeFromWorld(world) {
|
|
351
|
+
const carrier = withCarrier(world);
|
|
352
|
+
return carrier?.[STEP_RUNTIME_SYMBOL];
|
|
353
|
+
}
|
|
354
|
+
function resolveCoerceOverride(shape, coerceOverride) {
|
|
355
|
+
if (typeof coerceOverride === "boolean") {
|
|
356
|
+
return coerceOverride;
|
|
357
|
+
}
|
|
358
|
+
return activeConfig[shape];
|
|
359
|
+
}
|
|
360
|
+
function getTable(world, shape, options) {
|
|
361
|
+
const table = getRawTable(world);
|
|
362
|
+
if (!table) {
|
|
363
|
+
return void 0;
|
|
364
|
+
}
|
|
365
|
+
const coerce = resolveCoerceOverride(shape, options?.coerce);
|
|
366
|
+
switch (shape) {
|
|
367
|
+
case "headerless":
|
|
368
|
+
return gherkin.createTable(table, "headerless", {
|
|
369
|
+
...options,
|
|
370
|
+
coerce
|
|
371
|
+
});
|
|
372
|
+
case "horizontal":
|
|
373
|
+
return gherkin.createTable(table, "horizontal", {
|
|
374
|
+
...options,
|
|
375
|
+
coerce
|
|
376
|
+
});
|
|
377
|
+
case "vertical":
|
|
378
|
+
return gherkin.createTable(table, "vertical", {
|
|
379
|
+
...options,
|
|
380
|
+
coerce
|
|
381
|
+
});
|
|
382
|
+
case "matrix":
|
|
383
|
+
return gherkin.createTable(table, "matrix", {
|
|
384
|
+
...options,
|
|
385
|
+
coerce
|
|
386
|
+
});
|
|
387
|
+
default:
|
|
388
|
+
return void 0;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
function consumeTable(world, shape, options) {
|
|
392
|
+
let instance;
|
|
393
|
+
switch (shape) {
|
|
394
|
+
case "headerless":
|
|
395
|
+
instance = getTable(world, "headerless", options);
|
|
396
|
+
break;
|
|
397
|
+
case "horizontal":
|
|
398
|
+
instance = getTable(world, "horizontal", options);
|
|
399
|
+
break;
|
|
400
|
+
case "vertical":
|
|
401
|
+
instance = getTable(world, "vertical", options);
|
|
402
|
+
break;
|
|
403
|
+
case "matrix":
|
|
404
|
+
instance = getTable(world, "matrix", options);
|
|
405
|
+
break;
|
|
406
|
+
default:
|
|
407
|
+
instance = void 0;
|
|
408
|
+
}
|
|
409
|
+
clearStepTable(world);
|
|
410
|
+
return instance;
|
|
411
|
+
}
|
|
412
|
+
function consumeDocstring(world) {
|
|
413
|
+
const value = getDocstring(world);
|
|
414
|
+
clearStepDocstring(world);
|
|
415
|
+
return value;
|
|
416
|
+
}
|
|
417
|
+
function normalizeDocstringMediaType(mediaType) {
|
|
418
|
+
if (!mediaType) {
|
|
419
|
+
return void 0;
|
|
420
|
+
}
|
|
421
|
+
const normalized = mediaType.trim();
|
|
422
|
+
if (!normalized) {
|
|
423
|
+
return void 0;
|
|
424
|
+
}
|
|
425
|
+
const [primary] = normalized.split(";", 1);
|
|
426
|
+
return primary?.trim().toLowerCase() || void 0;
|
|
427
|
+
}
|
|
428
|
+
function resolveDocstringTransformer(transformers, mediaType) {
|
|
429
|
+
const normalized = normalizeDocstringMediaType(mediaType);
|
|
430
|
+
if (!normalized) {
|
|
431
|
+
return void 0;
|
|
432
|
+
}
|
|
433
|
+
if (transformers[normalized]) {
|
|
434
|
+
return transformers[normalized];
|
|
435
|
+
}
|
|
436
|
+
const slashIndex = normalized.indexOf("/");
|
|
437
|
+
if (slashIndex !== -1) {
|
|
438
|
+
const subtype = normalized.slice(slashIndex + 1);
|
|
439
|
+
if (transformers[subtype]) {
|
|
440
|
+
return transformers[subtype];
|
|
441
|
+
}
|
|
442
|
+
const plusIndex = subtype.lastIndexOf("+");
|
|
443
|
+
if (plusIndex !== -1) {
|
|
444
|
+
const suffix = subtype.slice(plusIndex + 1);
|
|
445
|
+
if (transformers[`+${suffix}`]) {
|
|
446
|
+
return transformers[`+${suffix}`];
|
|
447
|
+
}
|
|
448
|
+
if (transformers[suffix]) {
|
|
449
|
+
return transformers[suffix];
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return void 0;
|
|
454
|
+
}
|
|
455
|
+
function configureStepDocstrings(config) {
|
|
456
|
+
if (config.transformers) {
|
|
457
|
+
activeDocstringConfig = {
|
|
458
|
+
...activeDocstringConfig,
|
|
459
|
+
transformers: {
|
|
460
|
+
...activeDocstringConfig.transformers,
|
|
461
|
+
...config.transformers
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function resetStepDocstringConfig() {
|
|
467
|
+
activeDocstringConfig = { ...DEFAULT_DOCSTRING_CONFIG };
|
|
468
|
+
}
|
|
469
|
+
function bindGetTable(world) {
|
|
470
|
+
function getTable2(shape, options) {
|
|
471
|
+
switch (shape) {
|
|
472
|
+
case "headerless":
|
|
473
|
+
return getTableForShape(world, "headerless", options);
|
|
474
|
+
case "horizontal":
|
|
475
|
+
return getTableForShape(world, "horizontal", options);
|
|
476
|
+
case "vertical":
|
|
477
|
+
return getTableForShape(world, "vertical", options);
|
|
478
|
+
case "matrix":
|
|
479
|
+
return getTableForShape(world, "matrix", options);
|
|
480
|
+
default:
|
|
481
|
+
return void 0;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
return getTable2;
|
|
485
|
+
}
|
|
486
|
+
function getTableForShape(world, shape, options) {
|
|
487
|
+
switch (shape) {
|
|
488
|
+
case "headerless":
|
|
489
|
+
return getTable(world, "headerless", options);
|
|
490
|
+
case "horizontal":
|
|
491
|
+
return getTable(world, "horizontal", options);
|
|
492
|
+
case "vertical":
|
|
493
|
+
return getTable(world, "vertical", options);
|
|
494
|
+
case "matrix":
|
|
495
|
+
return getTable(world, "matrix", options);
|
|
496
|
+
default:
|
|
497
|
+
return void 0;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function bindConsumeTable(world) {
|
|
501
|
+
function consume(shape, options) {
|
|
502
|
+
switch (shape) {
|
|
503
|
+
case "headerless":
|
|
504
|
+
return consumeTable(world, "headerless", options);
|
|
505
|
+
case "horizontal":
|
|
506
|
+
return consumeTable(world, "horizontal", options);
|
|
507
|
+
case "vertical":
|
|
508
|
+
return consumeTable(world, "vertical", options);
|
|
509
|
+
case "matrix":
|
|
510
|
+
return consumeTable(world, "matrix", options);
|
|
511
|
+
default:
|
|
512
|
+
return void 0;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return consume;
|
|
516
|
+
}
|
|
517
|
+
function bindRequireTable(world) {
|
|
518
|
+
function require2(shape, options) {
|
|
519
|
+
switch (shape) {
|
|
520
|
+
case "headerless": {
|
|
521
|
+
const table = consumeTable(
|
|
522
|
+
world,
|
|
523
|
+
"headerless",
|
|
524
|
+
options
|
|
525
|
+
);
|
|
526
|
+
if (!table) {
|
|
527
|
+
throw new RangeError("No headerless data table is attached to the current step.");
|
|
528
|
+
}
|
|
529
|
+
return table;
|
|
530
|
+
}
|
|
531
|
+
case "horizontal": {
|
|
532
|
+
const table = consumeTable(
|
|
533
|
+
world,
|
|
534
|
+
"horizontal",
|
|
535
|
+
options
|
|
536
|
+
);
|
|
537
|
+
if (!table) {
|
|
538
|
+
throw new RangeError("No horizontal data table is attached to the current step.");
|
|
539
|
+
}
|
|
540
|
+
return table;
|
|
541
|
+
}
|
|
542
|
+
case "vertical": {
|
|
543
|
+
const table = consumeTable(
|
|
544
|
+
world,
|
|
545
|
+
"vertical",
|
|
546
|
+
options
|
|
547
|
+
);
|
|
548
|
+
if (!table) {
|
|
549
|
+
throw new RangeError("No vertical data table is attached to the current step.");
|
|
550
|
+
}
|
|
551
|
+
return table;
|
|
552
|
+
}
|
|
553
|
+
case "matrix": {
|
|
554
|
+
const table = consumeTable(
|
|
555
|
+
world,
|
|
556
|
+
"matrix",
|
|
557
|
+
options
|
|
558
|
+
);
|
|
559
|
+
if (!table) {
|
|
560
|
+
throw new RangeError("No matrix data table is attached to the current step.");
|
|
561
|
+
}
|
|
562
|
+
return table;
|
|
563
|
+
}
|
|
564
|
+
default:
|
|
565
|
+
throw new RangeError(`Unsupported table shape: ${String(shape)}`);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return require2;
|
|
569
|
+
}
|
|
570
|
+
function cacheRuntime(world, runtime) {
|
|
571
|
+
const carrier = withCarrier(world);
|
|
572
|
+
if (!carrier) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (!Object.prototype.hasOwnProperty.call(carrier, STEP_RUNTIME_SYMBOL)) {
|
|
576
|
+
Object.defineProperty(carrier, STEP_RUNTIME_SYMBOL, {
|
|
577
|
+
value: runtime,
|
|
578
|
+
writable: true,
|
|
579
|
+
configurable: true,
|
|
580
|
+
enumerable: false
|
|
581
|
+
});
|
|
582
|
+
} else {
|
|
583
|
+
carrier[STEP_RUNTIME_SYMBOL] = runtime;
|
|
584
|
+
}
|
|
585
|
+
if (!Object.prototype.hasOwnProperty.call(carrier, "runtime")) {
|
|
586
|
+
Object.defineProperty(carrier, "runtime", {
|
|
587
|
+
get() {
|
|
588
|
+
return carrier[STEP_RUNTIME_SYMBOL];
|
|
589
|
+
},
|
|
590
|
+
enumerable: false,
|
|
591
|
+
configurable: true
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function createStepRuntime(world) {
|
|
596
|
+
const existing = getStepRuntimeFromWorld(world);
|
|
597
|
+
if (existing) {
|
|
598
|
+
return existing;
|
|
599
|
+
}
|
|
600
|
+
const getDocstringTransformed = (options) => {
|
|
601
|
+
const info = getDocstringInfo(world);
|
|
602
|
+
if (!info) {
|
|
603
|
+
return void 0;
|
|
604
|
+
}
|
|
605
|
+
const transformer = resolveDocstringTransformer(
|
|
606
|
+
activeDocstringConfig.transformers,
|
|
607
|
+
info.mediaType
|
|
608
|
+
);
|
|
609
|
+
if (!transformer) {
|
|
610
|
+
if (options?.fallback === "throw") {
|
|
611
|
+
const type = normalizeDocstringMediaType(info.mediaType) ?? "<unknown>";
|
|
612
|
+
throw new RangeError(
|
|
613
|
+
`No docstring transformer is configured for media type '${type}'.`
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
return info.content;
|
|
617
|
+
}
|
|
618
|
+
return transformer(
|
|
619
|
+
info.content,
|
|
620
|
+
info.mediaType === void 0 ? {} : { mediaType: info.mediaType }
|
|
621
|
+
);
|
|
622
|
+
};
|
|
623
|
+
const runtime = {
|
|
624
|
+
get hasTable() {
|
|
625
|
+
return getRawTable(world) !== void 0;
|
|
626
|
+
},
|
|
627
|
+
get hasDocstring() {
|
|
628
|
+
return getDocstring(world) !== void 0;
|
|
629
|
+
},
|
|
630
|
+
get currentStep() {
|
|
631
|
+
return getStepMetadata(world);
|
|
632
|
+
},
|
|
633
|
+
getTable: bindGetTable(world),
|
|
634
|
+
consumeTable: bindConsumeTable(world),
|
|
635
|
+
getRawTable() {
|
|
636
|
+
return getRawTable(world);
|
|
637
|
+
},
|
|
638
|
+
getDocstring() {
|
|
639
|
+
return getDocstring(world);
|
|
640
|
+
},
|
|
641
|
+
getDocstringMediaType() {
|
|
642
|
+
return getDocstringMediaType(world);
|
|
643
|
+
},
|
|
644
|
+
getDocstringInfo() {
|
|
645
|
+
return getDocstringInfo(world);
|
|
646
|
+
},
|
|
647
|
+
consumeDocstring() {
|
|
648
|
+
return consumeDocstring(world);
|
|
649
|
+
},
|
|
650
|
+
getDocstringTransformed,
|
|
651
|
+
consumeDocstringTransformed(options) {
|
|
652
|
+
const result = getDocstringTransformed(options);
|
|
653
|
+
clearStepDocstring(world);
|
|
654
|
+
return result;
|
|
655
|
+
},
|
|
656
|
+
getStepMetadata() {
|
|
657
|
+
return getStepMetadata(world);
|
|
658
|
+
},
|
|
659
|
+
requireTable: bindRequireTable(world)
|
|
660
|
+
};
|
|
661
|
+
cacheRuntime(world, runtime);
|
|
662
|
+
return runtime;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// src/pending.ts
|
|
666
|
+
var PENDING_SCENARIO_SYMBOL = Symbol("autometa:scenario:pending");
|
|
667
|
+
var _a;
|
|
668
|
+
var ScenarioPendingError = class extends Error {
|
|
669
|
+
constructor(reason) {
|
|
670
|
+
super(reason ? `Scenario pending: ${reason}` : "Scenario pending");
|
|
671
|
+
this[_a] = true;
|
|
672
|
+
this.name = "ScenarioPendingError";
|
|
673
|
+
if (reason !== void 0 && reason !== null) {
|
|
674
|
+
const trimmed = String(reason).trim();
|
|
675
|
+
if (trimmed.length > 0) {
|
|
676
|
+
this.reason = trimmed;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
_a = PENDING_SCENARIO_SYMBOL;
|
|
682
|
+
function isScenarioPendingError(error) {
|
|
683
|
+
return typeof error === "object" && error !== null && error[PENDING_SCENARIO_SYMBOL] === true;
|
|
684
|
+
}
|
|
685
|
+
function createPendingError(reason) {
|
|
686
|
+
return new ScenarioPendingError(reason);
|
|
687
|
+
}
|
|
688
|
+
function Pending(reason) {
|
|
689
|
+
return function pendingStepHandler(world, ..._args) {
|
|
690
|
+
throw createPendingError(reason);
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
var ToDo = Pending;
|
|
694
|
+
function markScenarioPending(reason) {
|
|
695
|
+
throw createPendingError(reason);
|
|
696
|
+
}
|
|
697
|
+
function createFeatureRef(feature) {
|
|
698
|
+
return {
|
|
699
|
+
id: feature.id,
|
|
700
|
+
name: feature.name,
|
|
701
|
+
location: feature.location ?? { line: 1, column: 1 },
|
|
702
|
+
tags: feature.tags,
|
|
703
|
+
comments: feature.comments?.map((comment) => comment.text)
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
function createRuleRef(rule) {
|
|
707
|
+
return {
|
|
708
|
+
id: rule.id,
|
|
709
|
+
name: rule.name,
|
|
710
|
+
location: rule.location ?? { line: 1, column: 1 },
|
|
711
|
+
tags: rule.tags
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function requirePickle(feature, scenarioId) {
|
|
715
|
+
const pickle = gherkin.generatePickleById(feature, scenarioId);
|
|
716
|
+
if (!pickle) {
|
|
717
|
+
throw new Error(
|
|
718
|
+
`Unable to generate pickle for scenario "${scenarioId}". Ensure the feature contains compiled scenarios and stable ids.`
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
return pickle;
|
|
722
|
+
}
|
|
723
|
+
function findPickleStep(pickle, stepId) {
|
|
724
|
+
return pickle.steps.find((step) => step.id === stepId || step.astNodeIds?.includes(stepId));
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// src/scenario-runner.ts
|
|
728
|
+
var matcherCache = /* @__PURE__ */ new WeakMap();
|
|
729
|
+
async function runScenarioExecution(execution, context) {
|
|
730
|
+
execution.reset();
|
|
731
|
+
const eventEmitter = context.events ? events.getEventEmitter() : void 0;
|
|
732
|
+
const pickle = context.events?.pickle;
|
|
733
|
+
const { world, beforeStepHooks, afterStepHooks, invokeHooks } = context;
|
|
734
|
+
const parameterRegistry = resolveParameterRegistry(context.parameterRegistry);
|
|
735
|
+
const stepSummaries = [];
|
|
736
|
+
try {
|
|
737
|
+
const { steps, gherkinSteps } = execution;
|
|
738
|
+
for (let index = 0; index < steps.length; index++) {
|
|
739
|
+
const step = steps[index];
|
|
740
|
+
if (!step) {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
const gherkinStep = gherkinSteps[index];
|
|
744
|
+
const metadata = buildStepMetadata(execution, index);
|
|
745
|
+
const stepDetails = {
|
|
746
|
+
index,
|
|
747
|
+
definition: step,
|
|
748
|
+
...gherkinStep ? { gherkin: gherkinStep } : {}
|
|
749
|
+
};
|
|
750
|
+
const beforeOptions = {
|
|
751
|
+
direction: "asc",
|
|
752
|
+
step: stepDetails
|
|
753
|
+
};
|
|
754
|
+
await invokeHooks(beforeStepHooks, beforeOptions);
|
|
755
|
+
const pickleStep = pickle && gherkinStep?.id ? findPickleStep(pickle, gherkinStep.id) : void 0;
|
|
756
|
+
if (eventEmitter && pickle && pickleStep) {
|
|
757
|
+
await eventEmitter.stepStarted({
|
|
758
|
+
feature: pickle.feature,
|
|
759
|
+
scenario: pickle.scenario,
|
|
760
|
+
step: pickleStep,
|
|
761
|
+
pickle,
|
|
762
|
+
...pickle.rule ? { rule: pickle.rule } : {},
|
|
763
|
+
metadata: { index }
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
setStepMetadata(world, metadata);
|
|
767
|
+
setStepTable(world, gherkinStep?.dataTable);
|
|
768
|
+
if (!gherkinStep?.docString) {
|
|
769
|
+
setStepDocstringInfo(world, void 0);
|
|
770
|
+
} else if (gherkinStep.docString.mediaType === void 0) {
|
|
771
|
+
setStepDocstringInfo(world, { content: gherkinStep.docString.content });
|
|
772
|
+
} else {
|
|
773
|
+
setStepDocstringInfo(world, {
|
|
774
|
+
content: gherkinStep.docString.content,
|
|
775
|
+
mediaType: gherkinStep.docString.mediaType
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
let status = "passed";
|
|
779
|
+
try {
|
|
780
|
+
const args = resolveStepArguments(
|
|
781
|
+
step,
|
|
782
|
+
gherkinStep,
|
|
783
|
+
parameterRegistry,
|
|
784
|
+
world
|
|
785
|
+
);
|
|
786
|
+
await step.handler(world, ...args);
|
|
787
|
+
stepSummaries.push(createStepSummary(metadata, gherkinStep, "passed"));
|
|
788
|
+
} catch (error) {
|
|
789
|
+
if (isScenarioPendingError(error)) {
|
|
790
|
+
status = "skipped";
|
|
791
|
+
throw error;
|
|
792
|
+
}
|
|
793
|
+
status = "failed";
|
|
794
|
+
if (eventEmitter && pickle && pickleStep) {
|
|
795
|
+
await eventEmitter.errorRaised({
|
|
796
|
+
error,
|
|
797
|
+
phase: "step",
|
|
798
|
+
feature: pickle.feature,
|
|
799
|
+
scenario: pickle.scenario,
|
|
800
|
+
...pickle.rule ? { rule: pickle.rule } : {},
|
|
801
|
+
pickle,
|
|
802
|
+
metadata: { index, stepId: pickleStep.id }
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
stepSummaries.push(createStepSummary(metadata, gherkinStep, "failed"));
|
|
806
|
+
for (let remaining = index + 1; remaining < gherkinSteps.length; remaining++) {
|
|
807
|
+
const remainingMetadata = buildStepMetadata(execution, remaining);
|
|
808
|
+
const remainingStep = gherkinSteps[remaining];
|
|
809
|
+
stepSummaries.push(
|
|
810
|
+
createStepSummary(remainingMetadata, remainingStep, "skipped")
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
throw enrichStepError(error, metadata, stepSummaries);
|
|
814
|
+
} finally {
|
|
815
|
+
const afterStepDetails = {
|
|
816
|
+
...stepDetails,
|
|
817
|
+
status
|
|
818
|
+
};
|
|
819
|
+
const afterOptions = {
|
|
820
|
+
direction: "desc",
|
|
821
|
+
step: afterStepDetails
|
|
822
|
+
};
|
|
823
|
+
await invokeHooks(afterStepHooks, afterOptions);
|
|
824
|
+
if (eventEmitter && pickle && pickleStep) {
|
|
825
|
+
await eventEmitter.stepCompleted({
|
|
826
|
+
feature: pickle.feature,
|
|
827
|
+
scenario: pickle.scenario,
|
|
828
|
+
step: pickleStep,
|
|
829
|
+
pickle,
|
|
830
|
+
...pickle.rule ? { rule: pickle.rule } : {},
|
|
831
|
+
metadata: { index, status }
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
clearStepTable(world);
|
|
835
|
+
clearStepDocstring(world);
|
|
836
|
+
clearStepMetadata(world);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
execution.markPassed();
|
|
840
|
+
} catch (error) {
|
|
841
|
+
if (isScenarioPendingError(error)) {
|
|
842
|
+
execution.markPending(error.reason);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
execution.markFailed(error);
|
|
846
|
+
throw error;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
function resolveStepArguments(definition, gherkinStep, registry, world) {
|
|
850
|
+
if (!gherkinStep) {
|
|
851
|
+
return [];
|
|
852
|
+
}
|
|
853
|
+
const matcher = getStepArgumentMatcher(definition, registry);
|
|
854
|
+
return matcher(gherkinStep.text, world);
|
|
855
|
+
}
|
|
856
|
+
function getStepArgumentMatcher(definition, registry) {
|
|
857
|
+
const cached = matcherCache.get(definition);
|
|
858
|
+
if (cached) {
|
|
859
|
+
return cached;
|
|
860
|
+
}
|
|
861
|
+
const matcher = createStepArgumentMatcher(
|
|
862
|
+
definition.expression,
|
|
863
|
+
registry
|
|
864
|
+
);
|
|
865
|
+
matcherCache.set(
|
|
866
|
+
definition,
|
|
867
|
+
matcher
|
|
868
|
+
);
|
|
869
|
+
return matcher;
|
|
870
|
+
}
|
|
871
|
+
function createStepArgumentMatcher(expression, registry) {
|
|
872
|
+
if (expression instanceof RegExp) {
|
|
873
|
+
const evaluator2 = new cucumberExpressions.RegularExpression(expression, registry);
|
|
874
|
+
return (text, world) => collectArguments(evaluator2.match(text), world, text, expression);
|
|
875
|
+
}
|
|
876
|
+
const evaluator = new cucumberExpressions.CucumberExpression(expression, registry);
|
|
877
|
+
return (text, world) => collectArguments(evaluator.match(text), world, text, expression);
|
|
878
|
+
}
|
|
879
|
+
function collectArguments(match, world, text, expression) {
|
|
880
|
+
if (!match) {
|
|
881
|
+
throw new Error(
|
|
882
|
+
`Step '${text}' did not match expression ${String(expression)}`
|
|
883
|
+
);
|
|
884
|
+
}
|
|
885
|
+
return match.map((argument) => argument.getValue(world));
|
|
886
|
+
}
|
|
887
|
+
function resolveParameterRegistry(source) {
|
|
888
|
+
if (isParameterTypeRegistry(source)) {
|
|
889
|
+
return source;
|
|
890
|
+
}
|
|
891
|
+
const carrier = source;
|
|
892
|
+
const registry = carrier?.registry;
|
|
893
|
+
if (isParameterTypeRegistry(registry)) {
|
|
894
|
+
return registry;
|
|
895
|
+
}
|
|
896
|
+
return new cucumberExpressions.ParameterTypeRegistry();
|
|
897
|
+
}
|
|
898
|
+
function isParameterTypeRegistry(value) {
|
|
899
|
+
if (!value || typeof value !== "object") {
|
|
900
|
+
return false;
|
|
901
|
+
}
|
|
902
|
+
if (value instanceof cucumberExpressions.ParameterTypeRegistry) {
|
|
903
|
+
return true;
|
|
904
|
+
}
|
|
905
|
+
const registry = value;
|
|
906
|
+
return typeof registry.lookupByTypeName === "function" && typeof registry.defineParameterType === "function" && typeof registry.lookupByRegexp === "function";
|
|
907
|
+
}
|
|
908
|
+
function buildStepMetadata(execution, index) {
|
|
909
|
+
const stepDefinition = execution.steps[index];
|
|
910
|
+
const gherkinStep = execution.gherkinSteps[index];
|
|
911
|
+
const featureNode = execution.feature;
|
|
912
|
+
const feature = featureNode.feature;
|
|
913
|
+
const featureSource = combineSourceRef(
|
|
914
|
+
featureNode.scope.source,
|
|
915
|
+
feature.uri,
|
|
916
|
+
feature.location
|
|
917
|
+
);
|
|
918
|
+
const featureMeta = {
|
|
919
|
+
name: featureNode.name,
|
|
920
|
+
keyword: featureNode.keyword,
|
|
921
|
+
uri: feature.uri,
|
|
922
|
+
...featureSource ? { source: featureSource } : {}
|
|
923
|
+
};
|
|
924
|
+
const scenarioSource = combineSourceRef(
|
|
925
|
+
execution.scope.source,
|
|
926
|
+
feature.uri,
|
|
927
|
+
extractScenarioLocation(execution)
|
|
928
|
+
);
|
|
929
|
+
const scenarioMeta = {
|
|
930
|
+
name: execution.name,
|
|
931
|
+
keyword: execution.keyword,
|
|
932
|
+
...scenarioSource ? { source: scenarioSource } : {}
|
|
933
|
+
};
|
|
934
|
+
const outlineMeta = execution.outline ? (() => {
|
|
935
|
+
const outlineSource = combineSourceRef(
|
|
936
|
+
execution.outline?.scope.source,
|
|
937
|
+
feature.uri,
|
|
938
|
+
execution.outline.outline.location
|
|
939
|
+
);
|
|
940
|
+
return {
|
|
941
|
+
name: execution.outline.name,
|
|
942
|
+
keyword: execution.outline.keyword,
|
|
943
|
+
...outlineSource ? { source: outlineSource } : {}
|
|
944
|
+
};
|
|
945
|
+
})() : void 0;
|
|
946
|
+
const exampleMeta = isScenarioOutlineExample(execution) ? (() => {
|
|
947
|
+
const group = execution.exampleGroup;
|
|
948
|
+
const exampleSource = combineSourceRef(
|
|
949
|
+
void 0,
|
|
950
|
+
feature.uri,
|
|
951
|
+
group.location
|
|
952
|
+
);
|
|
953
|
+
return {
|
|
954
|
+
name: group.name,
|
|
955
|
+
index: execution.exampleIndex,
|
|
956
|
+
values: buildExampleValues(group, execution.exampleIndex),
|
|
957
|
+
...exampleSource ? { source: exampleSource } : {}
|
|
958
|
+
};
|
|
959
|
+
})() : void 0;
|
|
960
|
+
const stepMeta = gherkinStep ? (() => {
|
|
961
|
+
const stepSource = combineSourceRef(
|
|
962
|
+
void 0,
|
|
963
|
+
feature.uri,
|
|
964
|
+
gherkinStep.location
|
|
965
|
+
);
|
|
966
|
+
return {
|
|
967
|
+
keyword: gherkinStep.keyword,
|
|
968
|
+
text: gherkinStep.text,
|
|
969
|
+
...stepSource ? { source: stepSource } : {}
|
|
970
|
+
};
|
|
971
|
+
})() : void 0;
|
|
972
|
+
const definitionMeta = stepDefinition ? (() => {
|
|
973
|
+
const definitionSource = normalizeDefinitionSource(stepDefinition.source);
|
|
974
|
+
return {
|
|
975
|
+
keyword: stepDefinition.keyword,
|
|
976
|
+
expression: stepDefinition.expression,
|
|
977
|
+
...definitionSource ? { source: definitionSource } : {}
|
|
978
|
+
};
|
|
979
|
+
})() : void 0;
|
|
980
|
+
const metadata = {
|
|
981
|
+
...featureMeta ? { feature: featureMeta } : {},
|
|
982
|
+
...scenarioMeta ? { scenario: scenarioMeta } : {},
|
|
983
|
+
...outlineMeta ? { outline: outlineMeta } : {},
|
|
984
|
+
...exampleMeta ? { example: exampleMeta } : {},
|
|
985
|
+
...stepMeta ? { step: stepMeta } : {},
|
|
986
|
+
...definitionMeta ? { definition: definitionMeta } : {}
|
|
987
|
+
};
|
|
988
|
+
return hasMetadata(metadata) ? metadata : void 0;
|
|
989
|
+
}
|
|
990
|
+
function combineSourceRef(source, uri, location) {
|
|
991
|
+
const file = source?.file ?? uri;
|
|
992
|
+
const line = source?.line ?? location?.line;
|
|
993
|
+
const column = source?.column ?? location?.column;
|
|
994
|
+
if (file === void 0 && line === void 0 && column === void 0) {
|
|
995
|
+
return void 0;
|
|
996
|
+
}
|
|
997
|
+
return {
|
|
998
|
+
...file !== void 0 ? { file } : {},
|
|
999
|
+
...line !== void 0 ? { line } : {},
|
|
1000
|
+
...column !== void 0 ? { column } : {}
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
function normalizeDefinitionSource(source) {
|
|
1004
|
+
if (!source) {
|
|
1005
|
+
return void 0;
|
|
1006
|
+
}
|
|
1007
|
+
return {
|
|
1008
|
+
...source.file !== void 0 ? { file: source.file } : {},
|
|
1009
|
+
...source.line !== void 0 ? { line: source.line } : {},
|
|
1010
|
+
...source.column !== void 0 ? { column: source.column } : {}
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
function extractScenarioLocation(execution) {
|
|
1014
|
+
if (execution.type === "example") {
|
|
1015
|
+
return execution.outline?.outline.location;
|
|
1016
|
+
}
|
|
1017
|
+
const scenario = execution.gherkin;
|
|
1018
|
+
return scenario.location;
|
|
1019
|
+
}
|
|
1020
|
+
function isScenarioOutlineExample(execution) {
|
|
1021
|
+
return execution.type === "example";
|
|
1022
|
+
}
|
|
1023
|
+
function buildExampleValues(group, index) {
|
|
1024
|
+
const values = {};
|
|
1025
|
+
const headers = group.tableHeader;
|
|
1026
|
+
const row = group.tableBody[index] ?? [];
|
|
1027
|
+
for (let i = 0; i < headers.length; i++) {
|
|
1028
|
+
const header = headers[i];
|
|
1029
|
+
if (header === void 0 || header.length === 0) {
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
values[header] = row[i] ?? "";
|
|
1033
|
+
}
|
|
1034
|
+
return Object.freeze(values);
|
|
1035
|
+
}
|
|
1036
|
+
function hasMetadata(metadata) {
|
|
1037
|
+
return Boolean(
|
|
1038
|
+
metadata.feature || metadata.scenario || metadata.outline || metadata.example || metadata.step || metadata.definition
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1041
|
+
function enrichStepError(error, metadata, steps) {
|
|
1042
|
+
const base = error instanceof Error ? error : new Error(String(error));
|
|
1043
|
+
if (errors.isGherkinStepError(base)) {
|
|
1044
|
+
return base;
|
|
1045
|
+
}
|
|
1046
|
+
const wrapped = new errors.GherkinStepError(base.message, {
|
|
1047
|
+
cause: base,
|
|
1048
|
+
context: buildGherkinErrorContext(metadata, base, steps) ?? {}
|
|
1049
|
+
});
|
|
1050
|
+
if (base.stack) {
|
|
1051
|
+
Object.defineProperty(wrapped, "stack", {
|
|
1052
|
+
configurable: true,
|
|
1053
|
+
enumerable: false,
|
|
1054
|
+
writable: true,
|
|
1055
|
+
value: base.stack
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
return wrapped;
|
|
1059
|
+
}
|
|
1060
|
+
function buildGherkinErrorContext(metadata, error, steps) {
|
|
1061
|
+
if (!metadata) {
|
|
1062
|
+
return void 0;
|
|
1063
|
+
}
|
|
1064
|
+
const gherkinLocation = toSourceLocation(metadata.step?.source);
|
|
1065
|
+
const definitionLocation = toSourceLocation(metadata.definition?.source);
|
|
1066
|
+
const errorLocation = extractErrorLocation(error);
|
|
1067
|
+
const pathSegments = buildGherkinPath(metadata);
|
|
1068
|
+
const gherkinSegment = gherkinLocation ? {
|
|
1069
|
+
location: gherkinLocation,
|
|
1070
|
+
...metadata.feature?.name !== void 0 ? { featureName: metadata.feature.name } : {},
|
|
1071
|
+
...metadata.step?.keyword !== void 0 ? { stepKeyword: metadata.step.keyword } : {},
|
|
1072
|
+
...metadata.step?.text !== void 0 ? { stepText: metadata.step.text } : {}
|
|
1073
|
+
} : void 0;
|
|
1074
|
+
const expression = metadata.definition?.expression;
|
|
1075
|
+
const functionName = typeof expression === "string" ? expression : expression !== void 0 ? String(expression) : void 0;
|
|
1076
|
+
const codeLocation = errorLocation ?? definitionLocation;
|
|
1077
|
+
const codeSegment = codeLocation ? {
|
|
1078
|
+
location: codeLocation,
|
|
1079
|
+
...functionName !== void 0 ? { functionName } : {}
|
|
1080
|
+
} : void 0;
|
|
1081
|
+
const hasSteps = Boolean(steps && steps.length > 0);
|
|
1082
|
+
if (!gherkinSegment && !codeSegment && !pathSegments && !hasSteps) {
|
|
1083
|
+
return void 0;
|
|
1084
|
+
}
|
|
1085
|
+
return {
|
|
1086
|
+
...gherkinSegment ? { gherkin: gherkinSegment } : {},
|
|
1087
|
+
...codeSegment ? { code: codeSegment } : {},
|
|
1088
|
+
...pathSegments ? { path: pathSegments } : {},
|
|
1089
|
+
...hasSteps && steps ? { steps } : {}
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
1092
|
+
function createStepSummary(metadata, gherkinStep, status) {
|
|
1093
|
+
const keyword = metadata?.step?.keyword ?? gherkinStep?.keyword;
|
|
1094
|
+
const text = metadata?.step?.text ?? gherkinStep?.text;
|
|
1095
|
+
const location = metadata?.step?.source ? toSourceLocation(metadata.step.source) : void 0;
|
|
1096
|
+
return {
|
|
1097
|
+
status,
|
|
1098
|
+
...keyword !== void 0 ? { keyword } : {},
|
|
1099
|
+
...text !== void 0 ? { text } : {},
|
|
1100
|
+
...location ? { location } : {}
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
function buildGherkinPath(metadata) {
|
|
1104
|
+
if (!metadata) {
|
|
1105
|
+
return void 0;
|
|
1106
|
+
}
|
|
1107
|
+
const segments = [];
|
|
1108
|
+
const featureLocation = toSourceLocation(metadata.feature?.source);
|
|
1109
|
+
if (featureLocation) {
|
|
1110
|
+
segments.push({
|
|
1111
|
+
role: "feature",
|
|
1112
|
+
location: featureLocation,
|
|
1113
|
+
...metadata.feature?.keyword !== void 0 ? { keyword: metadata.feature.keyword } : {},
|
|
1114
|
+
...metadata.feature?.name !== void 0 ? { name: metadata.feature.name } : {}
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
const outlineLocation = toSourceLocation(metadata.outline?.source);
|
|
1118
|
+
if (outlineLocation) {
|
|
1119
|
+
segments.push({
|
|
1120
|
+
role: "outline",
|
|
1121
|
+
location: outlineLocation,
|
|
1122
|
+
...metadata.outline?.keyword !== void 0 ? { keyword: metadata.outline.keyword } : {},
|
|
1123
|
+
...metadata.outline?.name !== void 0 ? { name: metadata.outline.name } : {}
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
const scenarioLocation = toSourceLocation(metadata.scenario?.source);
|
|
1127
|
+
if (scenarioLocation) {
|
|
1128
|
+
segments.push({
|
|
1129
|
+
role: "scenario",
|
|
1130
|
+
location: scenarioLocation,
|
|
1131
|
+
...metadata.scenario?.keyword !== void 0 ? { keyword: metadata.scenario.keyword } : {},
|
|
1132
|
+
...metadata.scenario?.name !== void 0 ? { name: metadata.scenario.name } : {}
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
const exampleLocation = toSourceLocation(metadata.example?.source);
|
|
1136
|
+
if (exampleLocation) {
|
|
1137
|
+
segments.push({
|
|
1138
|
+
role: "example",
|
|
1139
|
+
keyword: "Example",
|
|
1140
|
+
location: exampleLocation,
|
|
1141
|
+
...metadata.example?.name !== void 0 ? { name: metadata.example.name } : {},
|
|
1142
|
+
...metadata.example?.index !== void 0 ? { index: metadata.example.index } : {}
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
const stepLocation = toSourceLocation(metadata.step?.source);
|
|
1146
|
+
if (stepLocation) {
|
|
1147
|
+
segments.push({
|
|
1148
|
+
role: "step",
|
|
1149
|
+
location: stepLocation,
|
|
1150
|
+
...metadata.step?.keyword !== void 0 ? { keyword: metadata.step.keyword } : {},
|
|
1151
|
+
...metadata.step?.text !== void 0 ? { text: metadata.step.text } : {}
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
return segments.length ? segments : void 0;
|
|
1155
|
+
}
|
|
1156
|
+
var STACK_FRAME_IGNORE_PATTERNS = [
|
|
1157
|
+
/^node:/,
|
|
1158
|
+
/node:internal\//,
|
|
1159
|
+
/internal\/(?:modules|process)/,
|
|
1160
|
+
/node_modules\/@autometa\//,
|
|
1161
|
+
/packages\/(?:runner|executor|errors|cli|assertions)\//,
|
|
1162
|
+
/\/\.autometa-cli\/cache\//,
|
|
1163
|
+
/\/\.autometa\/cache\//,
|
|
1164
|
+
/\/node_modules\/\.cache\/autometa\//
|
|
1165
|
+
];
|
|
1166
|
+
function extractErrorLocation(error) {
|
|
1167
|
+
if (!error?.stack) {
|
|
1168
|
+
return void 0;
|
|
1169
|
+
}
|
|
1170
|
+
const lines = error.stack.split("\n").slice(1);
|
|
1171
|
+
for (const raw of lines) {
|
|
1172
|
+
const trimmed = raw.trim();
|
|
1173
|
+
if (!trimmed.startsWith("at ")) {
|
|
1174
|
+
continue;
|
|
1175
|
+
}
|
|
1176
|
+
const parsed = parseStackFrame(trimmed);
|
|
1177
|
+
if (!parsed) {
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
if (isFrameworkStackFile(parsed.file)) {
|
|
1181
|
+
continue;
|
|
1182
|
+
}
|
|
1183
|
+
const filePath = normalizeFilePath(parsed.file);
|
|
1184
|
+
return {
|
|
1185
|
+
filePath,
|
|
1186
|
+
start: {
|
|
1187
|
+
line: parsed.line,
|
|
1188
|
+
column: parsed.column
|
|
1189
|
+
}
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
return void 0;
|
|
1193
|
+
}
|
|
1194
|
+
function parseStackFrame(line) {
|
|
1195
|
+
const match = line.match(/at (?:.+?\()?((?:[a-zA-Z]:)?[^():]+):(\d+):(\d+)\)?$/);
|
|
1196
|
+
if (!match) {
|
|
1197
|
+
return void 0;
|
|
1198
|
+
}
|
|
1199
|
+
const [, file = "", lineText = "", columnText = ""] = match;
|
|
1200
|
+
if (!file || !lineText) {
|
|
1201
|
+
return void 0;
|
|
1202
|
+
}
|
|
1203
|
+
const lineNumber = Number.parseInt(lineText, 10);
|
|
1204
|
+
if (Number.isNaN(lineNumber)) {
|
|
1205
|
+
return void 0;
|
|
1206
|
+
}
|
|
1207
|
+
const columnNumber = Number.parseInt(columnText, 10);
|
|
1208
|
+
return {
|
|
1209
|
+
file,
|
|
1210
|
+
line: lineNumber,
|
|
1211
|
+
column: Number.isNaN(columnNumber) ? 1 : columnNumber
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
function isFrameworkStackFile(file) {
|
|
1215
|
+
const normalized = file.replace(/\\/g, "/");
|
|
1216
|
+
return STACK_FRAME_IGNORE_PATTERNS.some((pattern) => pattern.test(normalized));
|
|
1217
|
+
}
|
|
1218
|
+
function toSourceLocation(source) {
|
|
1219
|
+
if (!source?.file) {
|
|
1220
|
+
return void 0;
|
|
1221
|
+
}
|
|
1222
|
+
const filePath = normalizeFilePath(source.file);
|
|
1223
|
+
const line = source.line ?? 1;
|
|
1224
|
+
const column = source.column ?? 1;
|
|
1225
|
+
return {
|
|
1226
|
+
filePath,
|
|
1227
|
+
start: {
|
|
1228
|
+
line,
|
|
1229
|
+
column
|
|
1230
|
+
}
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
function normalizeFilePath(file) {
|
|
1234
|
+
if (file.startsWith("file://")) {
|
|
1235
|
+
try {
|
|
1236
|
+
return url.fileURLToPath(file);
|
|
1237
|
+
} catch {
|
|
1238
|
+
return file;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return path__default.default.isAbsolute(file) ? file : path__default.default.resolve(file);
|
|
1242
|
+
}
|
|
1243
|
+
var ALWAYS_TRUE = {
|
|
1244
|
+
evaluate: () => true
|
|
1245
|
+
};
|
|
1246
|
+
var resolveParser = () => {
|
|
1247
|
+
const namespace = TagExpressions__namespace;
|
|
1248
|
+
if (typeof namespace.parse === "function") {
|
|
1249
|
+
return namespace.parse;
|
|
1250
|
+
}
|
|
1251
|
+
if (typeof namespace.default === "function") {
|
|
1252
|
+
return namespace.default;
|
|
1253
|
+
}
|
|
1254
|
+
throw new Error("Unable to resolve @cucumber/tag-expressions parser export");
|
|
1255
|
+
};
|
|
1256
|
+
var parseExpression = resolveParser();
|
|
1257
|
+
var createTagFilter = (expression) => {
|
|
1258
|
+
if (!expression || expression.trim().length === 0) {
|
|
1259
|
+
return ALWAYS_TRUE;
|
|
1260
|
+
}
|
|
1261
|
+
const parsed = parseExpression(expression);
|
|
1262
|
+
return {
|
|
1263
|
+
evaluate(tags) {
|
|
1264
|
+
return parsed.evaluate(tags.map((tag) => tag.trim()));
|
|
1265
|
+
}
|
|
1266
|
+
};
|
|
1267
|
+
};
|
|
1268
|
+
|
|
1269
|
+
// src/modes.ts
|
|
1270
|
+
var MODE_TAG_ALIASES = {
|
|
1271
|
+
concurrent: "concurrent",
|
|
1272
|
+
sequential: "sequential",
|
|
1273
|
+
failing: "failing",
|
|
1274
|
+
fails: "failing"
|
|
1275
|
+
};
|
|
1276
|
+
function normalizeTagValue(tag) {
|
|
1277
|
+
return tag.replace(/^@/, "").trim().toLowerCase();
|
|
1278
|
+
}
|
|
1279
|
+
function wrapFailingTest(test) {
|
|
1280
|
+
const failing = (title, handler, timeout) => {
|
|
1281
|
+
const wrapped = async () => {
|
|
1282
|
+
let threw = false;
|
|
1283
|
+
try {
|
|
1284
|
+
await handler();
|
|
1285
|
+
} catch (_error) {
|
|
1286
|
+
threw = true;
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
if (!threw) {
|
|
1290
|
+
throw new Error("Expected scenario to fail, but it passed");
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
test(title, wrapped, timeout);
|
|
1294
|
+
};
|
|
1295
|
+
failing.skip = test.skip;
|
|
1296
|
+
failing.only = test.only;
|
|
1297
|
+
if (typeof test.concurrent === "function") {
|
|
1298
|
+
failing.concurrent = test.concurrent;
|
|
1299
|
+
}
|
|
1300
|
+
failing.failing = failing;
|
|
1301
|
+
failing.fails = failing;
|
|
1302
|
+
return failing;
|
|
1303
|
+
}
|
|
1304
|
+
function selectFailingTest(test) {
|
|
1305
|
+
if (typeof test.failing === "function") {
|
|
1306
|
+
return test.failing;
|
|
1307
|
+
}
|
|
1308
|
+
if (typeof test.fails === "function") {
|
|
1309
|
+
return test.fails;
|
|
1310
|
+
}
|
|
1311
|
+
return wrapFailingTest(test);
|
|
1312
|
+
}
|
|
1313
|
+
var selectSuiteByMode = (suite, mode) => {
|
|
1314
|
+
switch (mode) {
|
|
1315
|
+
case "skip":
|
|
1316
|
+
return suite.skip;
|
|
1317
|
+
case "only":
|
|
1318
|
+
return suite.only;
|
|
1319
|
+
case "concurrent":
|
|
1320
|
+
return typeof suite.concurrent === "function" ? suite.concurrent : suite;
|
|
1321
|
+
case "sequential":
|
|
1322
|
+
return typeof suite.sequential === "function" ? suite.sequential : suite;
|
|
1323
|
+
default:
|
|
1324
|
+
return suite;
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
var selectTestByMode = (test, mode) => {
|
|
1328
|
+
switch (mode) {
|
|
1329
|
+
case "skip":
|
|
1330
|
+
return test.skip;
|
|
1331
|
+
case "only":
|
|
1332
|
+
return test.only;
|
|
1333
|
+
case "concurrent":
|
|
1334
|
+
return typeof test.concurrent === "function" ? test.concurrent : test;
|
|
1335
|
+
case "sequential":
|
|
1336
|
+
return typeof test.sequential === "function" ? test.sequential : test;
|
|
1337
|
+
case "failing":
|
|
1338
|
+
return selectFailingTest(test);
|
|
1339
|
+
default:
|
|
1340
|
+
return test;
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
var resolveModeFromTags = (currentMode, tags) => {
|
|
1344
|
+
if (currentMode !== "default") {
|
|
1345
|
+
return currentMode;
|
|
1346
|
+
}
|
|
1347
|
+
if (!tags || tags.length === 0) {
|
|
1348
|
+
return currentMode;
|
|
1349
|
+
}
|
|
1350
|
+
for (const tag of tags) {
|
|
1351
|
+
const normalized = normalizeTagValue(tag);
|
|
1352
|
+
const derived = MODE_TAG_ALIASES[normalized];
|
|
1353
|
+
if (derived) {
|
|
1354
|
+
return derived;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
return currentMode;
|
|
1358
|
+
};
|
|
1359
|
+
var WORLD_CONTEXT_KEY = "__AUTOMETA_EXECUTOR_WORLD_CONTEXT__";
|
|
1360
|
+
var globalTarget = globalThis;
|
|
1361
|
+
var getOrCreateWorldContext = () => {
|
|
1362
|
+
const existing = globalTarget[WORLD_CONTEXT_KEY];
|
|
1363
|
+
if (existing) {
|
|
1364
|
+
return existing;
|
|
1365
|
+
}
|
|
1366
|
+
const created = new async_hooks.AsyncLocalStorage();
|
|
1367
|
+
globalTarget[WORLD_CONTEXT_KEY] = created;
|
|
1368
|
+
return created;
|
|
1369
|
+
};
|
|
1370
|
+
var WorldContext = getOrCreateWorldContext();
|
|
1371
|
+
function getWorld() {
|
|
1372
|
+
const store = WorldContext.getStore();
|
|
1373
|
+
if (store === void 0) {
|
|
1374
|
+
throw new Error(
|
|
1375
|
+
"World context is not available. Are you running inside a scenario?"
|
|
1376
|
+
);
|
|
1377
|
+
}
|
|
1378
|
+
return store;
|
|
1379
|
+
}
|
|
1380
|
+
function tryGetWorld() {
|
|
1381
|
+
return WorldContext.getStore();
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
// src/scope-lifecycle.ts
|
|
1385
|
+
var PERSISTENT_SCOPE_KINDS = /* @__PURE__ */ new Set([
|
|
1386
|
+
"feature",
|
|
1387
|
+
"rule",
|
|
1388
|
+
"scenarioOutline"
|
|
1389
|
+
]);
|
|
1390
|
+
var BEFORE_HOOK_TYPES = {
|
|
1391
|
+
root: void 0,
|
|
1392
|
+
feature: "beforeFeature",
|
|
1393
|
+
rule: "beforeRule",
|
|
1394
|
+
scenario: "beforeScenario",
|
|
1395
|
+
scenarioOutline: "beforeScenarioOutline"
|
|
1396
|
+
};
|
|
1397
|
+
var AFTER_HOOK_TYPES = {
|
|
1398
|
+
root: void 0,
|
|
1399
|
+
feature: "afterFeature",
|
|
1400
|
+
rule: "afterRule",
|
|
1401
|
+
scenario: "afterScenario",
|
|
1402
|
+
scenarioOutline: "afterScenarioOutline"
|
|
1403
|
+
};
|
|
1404
|
+
function formatSourceRef(source) {
|
|
1405
|
+
if (!source?.file) {
|
|
1406
|
+
return void 0;
|
|
1407
|
+
}
|
|
1408
|
+
const line = source.line ? `:${source.line}` : "";
|
|
1409
|
+
const column = source.column ? `:${source.column}` : "";
|
|
1410
|
+
return `${source.file}${line}${column}`;
|
|
1411
|
+
}
|
|
1412
|
+
function isRecord(value) {
|
|
1413
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1414
|
+
}
|
|
1415
|
+
var ScopeLifecycle = class {
|
|
1416
|
+
constructor(adapter, options = {}) {
|
|
1417
|
+
this.adapter = adapter;
|
|
1418
|
+
this.states = /* @__PURE__ */ new Map();
|
|
1419
|
+
this.depthMap = /* @__PURE__ */ new Map();
|
|
1420
|
+
this.root = adapter.plan.root;
|
|
1421
|
+
this.buildDepthMap(this.root, 0);
|
|
1422
|
+
if (options.hookLogger) {
|
|
1423
|
+
this.hookLogger = options.hookLogger;
|
|
1424
|
+
}
|
|
1425
|
+
this.featureLanguage = options.featureLanguage;
|
|
1426
|
+
this.scopeKeywords = options.scopeKeywords ?? /* @__PURE__ */ new Map();
|
|
1427
|
+
}
|
|
1428
|
+
configurePersistentScope(scope, runtime) {
|
|
1429
|
+
if (!this.isPersistentScope(scope)) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
if (!this.shouldMaterializePersistentScope(scope)) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
runtime.beforeAll(async () => {
|
|
1436
|
+
await this.ensureState(scope);
|
|
1437
|
+
});
|
|
1438
|
+
runtime.afterAll(async () => {
|
|
1439
|
+
await this.teardownState(scope);
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
collectScenarioHooks(execution) {
|
|
1443
|
+
return collectScenarioHooks(this.adapter, execution);
|
|
1444
|
+
}
|
|
1445
|
+
async runScenario(execution, hooks, runner, options = {}) {
|
|
1446
|
+
const parentWorld = await this.resolveParentWorldForScenario(execution);
|
|
1447
|
+
const world = await this.adapter.createWorld(execution.scope, parentWorld);
|
|
1448
|
+
const disposeWorld = createWorldDisposer(world);
|
|
1449
|
+
const invokeHooks = this.createHookInvoker(execution, world, options.events);
|
|
1450
|
+
const scenarioContext = {
|
|
1451
|
+
world,
|
|
1452
|
+
parameterRegistry: this.adapter.getParameterRegistry(),
|
|
1453
|
+
beforeStepHooks: hooks.beforeStep,
|
|
1454
|
+
afterStepHooks: hooks.afterStep,
|
|
1455
|
+
...options.events ? { events: options.events } : {},
|
|
1456
|
+
invokeHooks
|
|
1457
|
+
};
|
|
1458
|
+
const errors = [];
|
|
1459
|
+
try {
|
|
1460
|
+
await WorldContext.run(world, async () => {
|
|
1461
|
+
await this.invokeHooks(hooks.beforeScenario, {
|
|
1462
|
+
world,
|
|
1463
|
+
scope: execution.scope,
|
|
1464
|
+
scenario: execution,
|
|
1465
|
+
...options.events ? { events: options.events } : {},
|
|
1466
|
+
direction: "asc"
|
|
1467
|
+
});
|
|
1468
|
+
await runner(world, scenarioContext);
|
|
1469
|
+
});
|
|
1470
|
+
} catch (error) {
|
|
1471
|
+
errors.push(error);
|
|
1472
|
+
} finally {
|
|
1473
|
+
try {
|
|
1474
|
+
await this.invokeHooks(hooks.afterScenario, {
|
|
1475
|
+
world,
|
|
1476
|
+
scope: execution.scope,
|
|
1477
|
+
scenario: execution,
|
|
1478
|
+
...options.events ? { events: options.events } : {},
|
|
1479
|
+
direction: "desc",
|
|
1480
|
+
metadata: { result: execution.result }
|
|
1481
|
+
});
|
|
1482
|
+
} catch (error) {
|
|
1483
|
+
errors.push(error);
|
|
1484
|
+
}
|
|
1485
|
+
try {
|
|
1486
|
+
await disposeWorld();
|
|
1487
|
+
} catch (error) {
|
|
1488
|
+
errors.push(error);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
if (errors.length === 1) {
|
|
1492
|
+
throw toError(errors[0], "Scenario execution failed");
|
|
1493
|
+
}
|
|
1494
|
+
if (errors.length > 1) {
|
|
1495
|
+
throw combineErrors(errors, "Multiple errors occurred during scenario execution");
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
async ensureState(scope) {
|
|
1499
|
+
let state = this.states.get(scope.id);
|
|
1500
|
+
if (state) {
|
|
1501
|
+
if (!state.beforeExecuted) {
|
|
1502
|
+
await this.runScopeHooks(scope, "before", state.world);
|
|
1503
|
+
state.beforeExecuted = true;
|
|
1504
|
+
}
|
|
1505
|
+
return state;
|
|
1506
|
+
}
|
|
1507
|
+
await this.ensureAncestorStates(scope);
|
|
1508
|
+
const parentWorld = await this.resolveParentWorld(scope);
|
|
1509
|
+
const world = await this.adapter.createWorld(scope, parentWorld);
|
|
1510
|
+
const dispose = createWorldDisposer(world);
|
|
1511
|
+
state = {
|
|
1512
|
+
scope,
|
|
1513
|
+
world,
|
|
1514
|
+
dispose,
|
|
1515
|
+
beforeExecuted: false,
|
|
1516
|
+
afterExecuted: false
|
|
1517
|
+
};
|
|
1518
|
+
this.states.set(scope.id, state);
|
|
1519
|
+
await this.runScopeHooks(scope, "before", world);
|
|
1520
|
+
state.beforeExecuted = true;
|
|
1521
|
+
return state;
|
|
1522
|
+
}
|
|
1523
|
+
async teardownState(scope) {
|
|
1524
|
+
const state = this.states.get(scope.id);
|
|
1525
|
+
if (!state) {
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
if (!state.afterExecuted) {
|
|
1529
|
+
await this.runScopeHooks(scope, "after", state.world);
|
|
1530
|
+
state.afterExecuted = true;
|
|
1531
|
+
}
|
|
1532
|
+
await state.dispose();
|
|
1533
|
+
this.states.delete(scope.id);
|
|
1534
|
+
}
|
|
1535
|
+
async ensureAncestorStates(scope) {
|
|
1536
|
+
const parent = this.getParentScope(scope);
|
|
1537
|
+
if (!parent) {
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
if (!this.isPersistentScope(parent)) {
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
if (!this.shouldMaterializePersistentScope(parent)) {
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
await this.ensureState(parent);
|
|
1547
|
+
}
|
|
1548
|
+
async resolveParentWorld(scope) {
|
|
1549
|
+
const parent = this.getParentScope(scope);
|
|
1550
|
+
if (!parent || !this.isPersistentScope(parent)) {
|
|
1551
|
+
return void 0;
|
|
1552
|
+
}
|
|
1553
|
+
if (!this.shouldMaterializePersistentScope(parent)) {
|
|
1554
|
+
return void 0;
|
|
1555
|
+
}
|
|
1556
|
+
const parentState = this.states.get(parent.id) ?? await this.ensureState(parent);
|
|
1557
|
+
return parentState.world;
|
|
1558
|
+
}
|
|
1559
|
+
async resolveParentWorldForScenario(execution) {
|
|
1560
|
+
const scope = execution.scope;
|
|
1561
|
+
const ownState = this.states.get(scope.id);
|
|
1562
|
+
if (ownState) {
|
|
1563
|
+
return ownState.world;
|
|
1564
|
+
}
|
|
1565
|
+
const ancestors = this.adapter.getAncestors(scope.id);
|
|
1566
|
+
for (let index = ancestors.length - 1; index >= 0; index -= 1) {
|
|
1567
|
+
const candidate = ancestors[index];
|
|
1568
|
+
if (!candidate || !this.isPersistentScope(candidate)) {
|
|
1569
|
+
continue;
|
|
1570
|
+
}
|
|
1571
|
+
if (!this.shouldMaterializePersistentScope(candidate)) {
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
const state = this.states.get(candidate.id) ?? await this.ensureState(candidate);
|
|
1575
|
+
if (state) {
|
|
1576
|
+
return state.world;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
return void 0;
|
|
1580
|
+
}
|
|
1581
|
+
getParentScope(scope) {
|
|
1582
|
+
const ancestors = this.adapter.getAncestors(scope.id);
|
|
1583
|
+
if (ancestors.length === 0) {
|
|
1584
|
+
return void 0;
|
|
1585
|
+
}
|
|
1586
|
+
return ancestors[ancestors.length - 1];
|
|
1587
|
+
}
|
|
1588
|
+
isPersistentScope(scope) {
|
|
1589
|
+
return PERSISTENT_SCOPE_KINDS.has(scope.kind);
|
|
1590
|
+
}
|
|
1591
|
+
shouldMaterializePersistentScope(scope) {
|
|
1592
|
+
const beforeType = BEFORE_HOOK_TYPES[scope.kind];
|
|
1593
|
+
const afterType = AFTER_HOOK_TYPES[scope.kind];
|
|
1594
|
+
if (beforeType) {
|
|
1595
|
+
const hooks = this.collectHooksForScope(scope, beforeType);
|
|
1596
|
+
if (hooks.length > 0) {
|
|
1597
|
+
return true;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
if (afterType) {
|
|
1601
|
+
const hooks = this.collectHooksForScope(scope, afterType);
|
|
1602
|
+
if (hooks.length > 0) {
|
|
1603
|
+
return true;
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
return false;
|
|
1607
|
+
}
|
|
1608
|
+
async runScopeHooks(scope, phase, world) {
|
|
1609
|
+
const hookType = phase === "before" ? BEFORE_HOOK_TYPES[scope.kind] : AFTER_HOOK_TYPES[scope.kind];
|
|
1610
|
+
if (!hookType) {
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
const hooks = this.collectHooksForScope(scope, hookType);
|
|
1614
|
+
if (!hooks.length) {
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1617
|
+
await this.invokeHooks(hooks, {
|
|
1618
|
+
world,
|
|
1619
|
+
scope,
|
|
1620
|
+
direction: phase === "before" ? "asc" : "desc"
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1623
|
+
createHookInvoker(execution, world, events) {
|
|
1624
|
+
return async (hooks, options) => {
|
|
1625
|
+
const params = {
|
|
1626
|
+
world,
|
|
1627
|
+
scope: execution.scope,
|
|
1628
|
+
scenario: execution,
|
|
1629
|
+
...events ? { events } : {},
|
|
1630
|
+
...options.direction ? { direction: options.direction } : {},
|
|
1631
|
+
...options.step ? { step: options.step } : {},
|
|
1632
|
+
...options.metadata ? { metadata: options.metadata } : {}
|
|
1633
|
+
};
|
|
1634
|
+
await this.invokeHooks(hooks, params);
|
|
1635
|
+
};
|
|
1636
|
+
}
|
|
1637
|
+
async invokeHooks(hooks, params) {
|
|
1638
|
+
if (hooks.length === 0) {
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
const sorted = this.sortHooks(hooks, params.direction ?? "asc");
|
|
1642
|
+
const eventEmitter = events.getEventEmitter();
|
|
1643
|
+
const pickle = params.events?.pickle;
|
|
1644
|
+
for (const entry of sorted) {
|
|
1645
|
+
const source = formatSourceRef(entry.hook.source ?? entry.scope.source);
|
|
1646
|
+
const hookMetadata = isRecord(entry.hook.options.data) ? entry.hook.options.data : void 0;
|
|
1647
|
+
const pickleStep = pickle && params.step?.gherkin?.id ? findPickleStep(pickle, params.step.gherkin.id) : void 0;
|
|
1648
|
+
const hookDescriptor = {
|
|
1649
|
+
kind: entry.hook.type,
|
|
1650
|
+
...entry.hook.description ? { name: entry.hook.description } : {},
|
|
1651
|
+
...source ? { source } : {},
|
|
1652
|
+
...pickle ? { feature: pickle.feature } : {},
|
|
1653
|
+
...pickle?.rule ? { rule: pickle.rule } : {},
|
|
1654
|
+
...pickle ? { scenario: pickle.scenario } : {},
|
|
1655
|
+
...pickleStep ? { step: pickleStep } : {},
|
|
1656
|
+
...pickle ? { pickle } : {},
|
|
1657
|
+
...hookMetadata ? { metadata: hookMetadata } : {}
|
|
1658
|
+
};
|
|
1659
|
+
await eventEmitter.hookStarted({
|
|
1660
|
+
hook: hookDescriptor,
|
|
1661
|
+
metadata: { hookId: entry.hook.id }
|
|
1662
|
+
});
|
|
1663
|
+
const metadata = this.buildHookMetadata(entry, params);
|
|
1664
|
+
const log = this.createContextLogger(entry, params);
|
|
1665
|
+
const context = {
|
|
1666
|
+
world: params.world,
|
|
1667
|
+
scope: entry.scope,
|
|
1668
|
+
...metadata ? { metadata } : {},
|
|
1669
|
+
...log ? { log } : {}
|
|
1670
|
+
};
|
|
1671
|
+
try {
|
|
1672
|
+
await entry.hook.handler(context);
|
|
1673
|
+
} catch (error) {
|
|
1674
|
+
await eventEmitter.errorRaised({
|
|
1675
|
+
error,
|
|
1676
|
+
phase: "hook",
|
|
1677
|
+
...pickle ? { feature: pickle.feature } : {},
|
|
1678
|
+
...pickle?.rule ? { rule: pickle.rule } : {},
|
|
1679
|
+
...pickle ? { scenario: pickle.scenario } : {},
|
|
1680
|
+
...pickle ? { pickle } : {},
|
|
1681
|
+
metadata: { hook: hookDescriptor, hookId: entry.hook.id }
|
|
1682
|
+
});
|
|
1683
|
+
throw error;
|
|
1684
|
+
} finally {
|
|
1685
|
+
await eventEmitter.hookCompleted({
|
|
1686
|
+
hook: hookDescriptor,
|
|
1687
|
+
metadata: { hookId: entry.hook.id }
|
|
1688
|
+
});
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
buildHookMetadata(entry, params) {
|
|
1693
|
+
const metadata = {};
|
|
1694
|
+
if (params.metadata) {
|
|
1695
|
+
Object.assign(metadata, params.metadata);
|
|
1696
|
+
}
|
|
1697
|
+
if (entry.hook.options.data !== void 0) {
|
|
1698
|
+
metadata.hook = entry.hook.options.data;
|
|
1699
|
+
}
|
|
1700
|
+
metadata.targetScope = {
|
|
1701
|
+
id: params.scope.id,
|
|
1702
|
+
kind: params.scope.kind,
|
|
1703
|
+
name: params.scope.name
|
|
1704
|
+
};
|
|
1705
|
+
if (params.scenario) {
|
|
1706
|
+
metadata.scenario = {
|
|
1707
|
+
id: params.scenario.id,
|
|
1708
|
+
name: params.scenario.name,
|
|
1709
|
+
type: params.scenario.type,
|
|
1710
|
+
tags: params.scenario.tags,
|
|
1711
|
+
qualifiedName: params.scenario.qualifiedName
|
|
1712
|
+
};
|
|
1713
|
+
}
|
|
1714
|
+
if (params.step) {
|
|
1715
|
+
const { step } = params;
|
|
1716
|
+
metadata.step = {
|
|
1717
|
+
index: step.index,
|
|
1718
|
+
status: step.status,
|
|
1719
|
+
keyword: step.gherkin?.keyword ?? step.definition?.keyword,
|
|
1720
|
+
text: step.gherkin?.text
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
1724
|
+
}
|
|
1725
|
+
collectHooksForScope(scope, type) {
|
|
1726
|
+
const chain = this.buildChain(scope);
|
|
1727
|
+
const collected = [];
|
|
1728
|
+
for (const candidate of chain) {
|
|
1729
|
+
for (const hook of candidate.hooks) {
|
|
1730
|
+
if (hook.type === type) {
|
|
1731
|
+
collected.push({ hook, scope: candidate });
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
return collected;
|
|
1736
|
+
}
|
|
1737
|
+
buildChain(scope) {
|
|
1738
|
+
const ancestors = this.adapter.getAncestors(scope.id);
|
|
1739
|
+
return [this.root, ...ancestors, scope];
|
|
1740
|
+
}
|
|
1741
|
+
createContextLogger(entry, params) {
|
|
1742
|
+
if (!this.hookLogger) {
|
|
1743
|
+
return void 0;
|
|
1744
|
+
}
|
|
1745
|
+
const emit = this.hookLogger;
|
|
1746
|
+
return (rawMessage) => {
|
|
1747
|
+
if (rawMessage === void 0 || rawMessage === null) {
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
const message = String(rawMessage);
|
|
1751
|
+
if (message.length === 0) {
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1754
|
+
try {
|
|
1755
|
+
emit(this.buildHookLogEvent(entry, params, message));
|
|
1756
|
+
} catch (error) {
|
|
1757
|
+
if (typeof console !== "undefined" && typeof console.error === "function") {
|
|
1758
|
+
console.error(error);
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
buildHookLogEvent(entry, params, message) {
|
|
1764
|
+
const ancestors = this.adapter.getAncestors(params.scope.id);
|
|
1765
|
+
const path2 = ancestors.map((node) => this.toPathSegment(node));
|
|
1766
|
+
const targetSegment = this.toPathSegment(params.scope);
|
|
1767
|
+
path2.push(targetSegment);
|
|
1768
|
+
const direction = params.direction ?? "asc";
|
|
1769
|
+
const phase = direction === "desc" ? "after" : "before";
|
|
1770
|
+
const scenarioIndex = this.findScenarioSegmentIndex(path2);
|
|
1771
|
+
const scenarioDetails = this.buildScenarioDetails(path2, scenarioIndex, params);
|
|
1772
|
+
const language = this.resolveLanguage(params, scenarioDetails);
|
|
1773
|
+
const targetKeyword = this.scopeKeywords.get(params.scope.id);
|
|
1774
|
+
if (params.step) {
|
|
1775
|
+
path2.push(this.toStepSegment(params.scope, params.step));
|
|
1776
|
+
}
|
|
1777
|
+
return {
|
|
1778
|
+
message,
|
|
1779
|
+
hookId: entry.hook.id,
|
|
1780
|
+
hookType: entry.hook.type,
|
|
1781
|
+
...entry.hook.description ? { hookDescription: entry.hook.description } : {},
|
|
1782
|
+
phase,
|
|
1783
|
+
path: path2,
|
|
1784
|
+
...scenarioDetails ? { scenario: scenarioDetails } : {},
|
|
1785
|
+
...params.step ? { step: this.toStepDetails(params.step) } : {},
|
|
1786
|
+
...targetKeyword ? { targetKeyword } : {},
|
|
1787
|
+
...language ? { language } : {}
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
toPathSegment(scope) {
|
|
1791
|
+
const keyword = this.scopeKeywords.get(scope.id);
|
|
1792
|
+
return {
|
|
1793
|
+
id: scope.id,
|
|
1794
|
+
kind: scope.kind,
|
|
1795
|
+
name: scope.name,
|
|
1796
|
+
...keyword ? { keyword } : {}
|
|
1797
|
+
};
|
|
1798
|
+
}
|
|
1799
|
+
toStepSegment(scope, step) {
|
|
1800
|
+
const keyword = step.gherkin?.keyword ?? step.definition?.keyword;
|
|
1801
|
+
return {
|
|
1802
|
+
id: `${scope.id}:step:${step.index}`,
|
|
1803
|
+
kind: "step",
|
|
1804
|
+
name: this.describeStep(step),
|
|
1805
|
+
...keyword ? { keyword: keyword.trim() } : {}
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
toStepDetails(step) {
|
|
1809
|
+
return {
|
|
1810
|
+
index: step.index,
|
|
1811
|
+
...step.gherkin?.keyword ? { keyword: step.gherkin.keyword } : {},
|
|
1812
|
+
...step.gherkin?.text ? { text: step.gherkin.text } : {},
|
|
1813
|
+
...step.status ? { status: step.status } : {}
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
describeStep(step) {
|
|
1817
|
+
const keyword = step.gherkin?.keyword ?? step.definition?.keyword;
|
|
1818
|
+
const text = step.gherkin?.text ?? this.describeStepExpression(step.definition);
|
|
1819
|
+
if (keyword) {
|
|
1820
|
+
const trimmedKeyword = keyword.trim();
|
|
1821
|
+
if (text && text.length > 0) {
|
|
1822
|
+
const needsSpace = text.startsWith(" ");
|
|
1823
|
+
return `${trimmedKeyword}${needsSpace ? "" : " "}${text}`;
|
|
1824
|
+
}
|
|
1825
|
+
return trimmedKeyword;
|
|
1826
|
+
}
|
|
1827
|
+
if (text && text.length > 0) {
|
|
1828
|
+
return text;
|
|
1829
|
+
}
|
|
1830
|
+
return `Step #${step.index + 1}`;
|
|
1831
|
+
}
|
|
1832
|
+
describeStepExpression(definition) {
|
|
1833
|
+
if (!definition) {
|
|
1834
|
+
return void 0;
|
|
1835
|
+
}
|
|
1836
|
+
const expression = definition.expression;
|
|
1837
|
+
if (typeof expression === "string") {
|
|
1838
|
+
return expression;
|
|
1839
|
+
}
|
|
1840
|
+
return expression.toString();
|
|
1841
|
+
}
|
|
1842
|
+
findScenarioSegmentIndex(path2) {
|
|
1843
|
+
for (let index = path2.length - 1; index >= 0; index -= 1) {
|
|
1844
|
+
const segment = path2[index];
|
|
1845
|
+
if (!segment) {
|
|
1846
|
+
continue;
|
|
1847
|
+
}
|
|
1848
|
+
if (segment.kind === "scenario") {
|
|
1849
|
+
return index;
|
|
1850
|
+
}
|
|
1851
|
+
if (segment.kind === "scenarioOutline") {
|
|
1852
|
+
return index;
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
return -1;
|
|
1856
|
+
}
|
|
1857
|
+
buildScenarioDetails(path2, scenarioIndex, params) {
|
|
1858
|
+
if (scenarioIndex < 0) {
|
|
1859
|
+
return void 0;
|
|
1860
|
+
}
|
|
1861
|
+
const scenarioSegment = path2[scenarioIndex];
|
|
1862
|
+
if (!scenarioSegment) {
|
|
1863
|
+
return void 0;
|
|
1864
|
+
}
|
|
1865
|
+
const segments = path2.slice(0, scenarioIndex + 1).map((segment) => segment.name);
|
|
1866
|
+
const fullName = segments.join(" \u203A ");
|
|
1867
|
+
const scenario = params.scenario;
|
|
1868
|
+
const keyword = scenario?.keyword ?? scenarioSegment.keyword;
|
|
1869
|
+
const language = scenario?.feature.feature.language ?? this.featureLanguage;
|
|
1870
|
+
if (scenario) {
|
|
1871
|
+
return {
|
|
1872
|
+
id: scenario.id,
|
|
1873
|
+
name: scenario.name,
|
|
1874
|
+
fullName,
|
|
1875
|
+
...keyword ? { keyword } : {},
|
|
1876
|
+
...language ? { language } : {}
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
return {
|
|
1880
|
+
id: scenarioSegment.id,
|
|
1881
|
+
name: scenarioSegment.name,
|
|
1882
|
+
fullName,
|
|
1883
|
+
...keyword ? { keyword } : {},
|
|
1884
|
+
...language ? { language } : {}
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
resolveLanguage(params, scenarioDetails) {
|
|
1888
|
+
if (params.scenario) {
|
|
1889
|
+
const scenarioLanguage = params.scenario.feature.feature.language;
|
|
1890
|
+
if (scenarioLanguage) {
|
|
1891
|
+
return scenarioLanguage;
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
if (scenarioDetails?.language) {
|
|
1895
|
+
return scenarioDetails.language;
|
|
1896
|
+
}
|
|
1897
|
+
return this.featureLanguage;
|
|
1898
|
+
}
|
|
1899
|
+
sortHooks(hooks, direction) {
|
|
1900
|
+
return hooks.slice().sort((a, b) => this.compareHooks(a, b, direction));
|
|
1901
|
+
}
|
|
1902
|
+
compareHooks(a, b, direction) {
|
|
1903
|
+
const orderA = a.hook.options.order ?? 5;
|
|
1904
|
+
const orderB = b.hook.options.order ?? 5;
|
|
1905
|
+
if (orderA !== orderB) {
|
|
1906
|
+
return direction === "asc" ? orderA - orderB : orderB - orderA;
|
|
1907
|
+
}
|
|
1908
|
+
const depthA = this.depthMap.get(a.scope.id) ?? 0;
|
|
1909
|
+
const depthB = this.depthMap.get(b.scope.id) ?? 0;
|
|
1910
|
+
if (depthA !== depthB) {
|
|
1911
|
+
return direction === "asc" ? depthB - depthA : depthA - depthB;
|
|
1912
|
+
}
|
|
1913
|
+
return a.hook.id.localeCompare(b.hook.id);
|
|
1914
|
+
}
|
|
1915
|
+
buildDepthMap(node, depth) {
|
|
1916
|
+
this.depthMap.set(node.id, depth);
|
|
1917
|
+
for (const child of node.children) {
|
|
1918
|
+
this.buildDepthMap(child, depth + 1);
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
function normalizeError(value, fallbackMessage) {
|
|
1923
|
+
if (value instanceof Error) {
|
|
1924
|
+
return value;
|
|
1925
|
+
}
|
|
1926
|
+
const error = new Error(fallbackMessage);
|
|
1927
|
+
Object.defineProperty(error, "cause", {
|
|
1928
|
+
configurable: true,
|
|
1929
|
+
enumerable: false,
|
|
1930
|
+
writable: true,
|
|
1931
|
+
value
|
|
1932
|
+
});
|
|
1933
|
+
return error;
|
|
1934
|
+
}
|
|
1935
|
+
function toError(value, fallbackMessage) {
|
|
1936
|
+
return normalizeError(value, fallbackMessage);
|
|
1937
|
+
}
|
|
1938
|
+
function combineErrors(values, message) {
|
|
1939
|
+
const normalized = values.map(
|
|
1940
|
+
(value, index) => normalizeError(value, `${message} (${index + 1})`)
|
|
1941
|
+
);
|
|
1942
|
+
const aggregate = new Error(message);
|
|
1943
|
+
Object.defineProperty(aggregate, "cause", {
|
|
1944
|
+
configurable: true,
|
|
1945
|
+
enumerable: false,
|
|
1946
|
+
writable: true,
|
|
1947
|
+
value: normalized
|
|
1948
|
+
});
|
|
1949
|
+
return aggregate;
|
|
1950
|
+
}
|
|
1951
|
+
function createWorldDisposer(world) {
|
|
1952
|
+
const disposers = [];
|
|
1953
|
+
if (world && typeof world === "object") {
|
|
1954
|
+
const record = world;
|
|
1955
|
+
const app = record.app;
|
|
1956
|
+
if (isDisposable(app)) {
|
|
1957
|
+
disposers.push(async () => {
|
|
1958
|
+
await app.dispose();
|
|
1959
|
+
});
|
|
1960
|
+
}
|
|
1961
|
+
const container = record.di ?? record.container;
|
|
1962
|
+
if (isDisposable(container)) {
|
|
1963
|
+
disposers.push(async () => {
|
|
1964
|
+
await container.dispose();
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
return async () => {
|
|
1969
|
+
if (disposers.length === 0) {
|
|
1970
|
+
return;
|
|
1971
|
+
}
|
|
1972
|
+
const errors = [];
|
|
1973
|
+
for (const dispose of disposers) {
|
|
1974
|
+
try {
|
|
1975
|
+
await dispose();
|
|
1976
|
+
} catch (error) {
|
|
1977
|
+
errors.push(error);
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
if (errors.length === 1) {
|
|
1981
|
+
throw toError(errors[0], "World disposal failed");
|
|
1982
|
+
}
|
|
1983
|
+
if (errors.length > 1) {
|
|
1984
|
+
throw combineErrors(errors, "Multiple errors occurred while disposing world resources");
|
|
1985
|
+
}
|
|
1986
|
+
};
|
|
1987
|
+
}
|
|
1988
|
+
function isDisposable(value) {
|
|
1989
|
+
if (!value || typeof value !== "object") {
|
|
1990
|
+
return false;
|
|
1991
|
+
}
|
|
1992
|
+
const candidate = value;
|
|
1993
|
+
const dispose = candidate.dispose;
|
|
1994
|
+
return typeof dispose === "function";
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
// src/execute-plan.ts
|
|
1998
|
+
function runSuiteWithMetadata(suite, metadata, title, handler, timeout) {
|
|
1999
|
+
const target = suite;
|
|
2000
|
+
if (typeof target.__withMetadata === "function") {
|
|
2001
|
+
target.__withMetadata(metadata, () => {
|
|
2002
|
+
suite(title, handler, timeout);
|
|
2003
|
+
});
|
|
2004
|
+
return;
|
|
2005
|
+
}
|
|
2006
|
+
suite(title, handler, timeout);
|
|
2007
|
+
}
|
|
2008
|
+
function isScenarioOutlineExample2(execution) {
|
|
2009
|
+
return execution.type === "example";
|
|
2010
|
+
}
|
|
2011
|
+
function shouldDisplayExamplesGroup(group, totalGroups) {
|
|
2012
|
+
if (totalGroups > 1) {
|
|
2013
|
+
return true;
|
|
2014
|
+
}
|
|
2015
|
+
const name = group.name?.trim();
|
|
2016
|
+
return Boolean(name && name.length > 0);
|
|
2017
|
+
}
|
|
2018
|
+
function formatExamplesGroupTitle(group, index) {
|
|
2019
|
+
const trimmed = group.name?.trim();
|
|
2020
|
+
if (trimmed && trimmed.length > 0) {
|
|
2021
|
+
return trimmed;
|
|
2022
|
+
}
|
|
2023
|
+
return `Table #${index + 1}`;
|
|
2024
|
+
}
|
|
2025
|
+
function registerFeaturePlan(options) {
|
|
2026
|
+
const { plan, runtime, adapter, config, hookLogger } = options;
|
|
2027
|
+
const feature = plan.feature;
|
|
2028
|
+
const tagFilter = createTagFilter(config.test?.tagFilter);
|
|
2029
|
+
const scopeKeywords = collectScopeKeywords(feature);
|
|
2030
|
+
const eventEmitter = events.getEventEmitter();
|
|
2031
|
+
const featureRef = createFeatureRef(feature.feature);
|
|
2032
|
+
const lifecycle = new ScopeLifecycle(adapter, {
|
|
2033
|
+
...hookLogger ? { hookLogger } : {},
|
|
2034
|
+
featureLanguage: feature.feature.language,
|
|
2035
|
+
scopeKeywords
|
|
2036
|
+
});
|
|
2037
|
+
const featureTags = [
|
|
2038
|
+
...feature.feature.tags ?? [],
|
|
2039
|
+
...feature.scope.tags ?? []
|
|
2040
|
+
];
|
|
2041
|
+
const featureMode = resolveModeFromTags(feature.scope.mode, featureTags);
|
|
2042
|
+
const featureTimeout = resolveTimeout(feature.scope.timeout, config);
|
|
2043
|
+
const featureSuite = selectSuiteByMode(runtime.suite, featureMode);
|
|
2044
|
+
runSuiteWithMetadata(
|
|
2045
|
+
featureSuite,
|
|
2046
|
+
{ kind: "feature", keyword: feature.keyword },
|
|
2047
|
+
feature.name,
|
|
2048
|
+
() => {
|
|
2049
|
+
runtime.beforeAll(async () => {
|
|
2050
|
+
await eventEmitter.featureStarted({ feature: featureRef });
|
|
2051
|
+
});
|
|
2052
|
+
runtime.afterAll(async () => {
|
|
2053
|
+
await eventEmitter.featureCompleted({ feature: featureRef });
|
|
2054
|
+
});
|
|
2055
|
+
lifecycle.configurePersistentScope(feature.scope, runtime);
|
|
2056
|
+
registerScenarios(feature.scenarios, runtime, config, tagFilter, lifecycle, feature.feature);
|
|
2057
|
+
registerScenarioOutlines(feature.scenarioOutlines, runtime, config, tagFilter, lifecycle, feature.feature, featureRef);
|
|
2058
|
+
registerRules(feature.rules, runtime, config, tagFilter, lifecycle, feature.feature, featureRef);
|
|
2059
|
+
},
|
|
2060
|
+
featureTimeout.milliseconds
|
|
2061
|
+
);
|
|
2062
|
+
}
|
|
2063
|
+
function collectScopeKeywords(feature) {
|
|
2064
|
+
const entries = [];
|
|
2065
|
+
entries.push([feature.scope.id, feature.keyword]);
|
|
2066
|
+
for (const scenario of feature.scenarios) {
|
|
2067
|
+
entries.push([scenario.scope.id, scenario.keyword]);
|
|
2068
|
+
}
|
|
2069
|
+
for (const outline of feature.scenarioOutlines) {
|
|
2070
|
+
entries.push([outline.scope.id, outline.keyword]);
|
|
2071
|
+
for (const example of outline.examples) {
|
|
2072
|
+
entries.push([example.scope.id, example.keyword]);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
for (const rule of feature.rules) {
|
|
2076
|
+
entries.push([rule.scope.id, rule.keyword]);
|
|
2077
|
+
for (const scenario of rule.scenarios) {
|
|
2078
|
+
entries.push([scenario.scope.id, scenario.keyword]);
|
|
2079
|
+
}
|
|
2080
|
+
for (const outline of rule.scenarioOutlines) {
|
|
2081
|
+
entries.push([outline.scope.id, outline.keyword]);
|
|
2082
|
+
for (const example of outline.examples) {
|
|
2083
|
+
entries.push([example.scope.id, example.keyword]);
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
return new Map(entries);
|
|
2088
|
+
}
|
|
2089
|
+
function registerRules(rules, runtime, config, tagFilter, lifecycle, feature, featureRef) {
|
|
2090
|
+
const eventEmitter = events.getEventEmitter();
|
|
2091
|
+
for (const rule of rules) {
|
|
2092
|
+
const ruleRef = createRuleRef(rule.rule);
|
|
2093
|
+
const ruleTags = [
|
|
2094
|
+
...rule.rule.tags ?? [],
|
|
2095
|
+
...rule.scope.tags ?? []
|
|
2096
|
+
];
|
|
2097
|
+
const ruleMode = resolveModeFromTags(rule.scope.mode, ruleTags);
|
|
2098
|
+
const suite = selectSuiteByMode(runtime.suite, ruleMode);
|
|
2099
|
+
const timeout = resolveTimeout(rule.scope.timeout, config);
|
|
2100
|
+
runSuiteWithMetadata(
|
|
2101
|
+
suite,
|
|
2102
|
+
{ kind: "rule", keyword: rule.keyword },
|
|
2103
|
+
rule.name,
|
|
2104
|
+
() => {
|
|
2105
|
+
runtime.beforeAll(async () => {
|
|
2106
|
+
await eventEmitter.ruleStarted({ feature: featureRef, rule: ruleRef });
|
|
2107
|
+
});
|
|
2108
|
+
runtime.afterAll(async () => {
|
|
2109
|
+
await eventEmitter.ruleCompleted({ feature: featureRef, rule: ruleRef });
|
|
2110
|
+
});
|
|
2111
|
+
lifecycle.configurePersistentScope(rule.scope, runtime);
|
|
2112
|
+
registerScenarios(rule.scenarios, runtime, config, tagFilter, lifecycle, feature);
|
|
2113
|
+
registerScenarioOutlines(rule.scenarioOutlines, runtime, config, tagFilter, lifecycle, feature, featureRef);
|
|
2114
|
+
},
|
|
2115
|
+
timeout.milliseconds
|
|
2116
|
+
);
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
function registerScenarioOutlines(outlines, runtime, config, tagFilter, lifecycle, feature, featureRef) {
|
|
2120
|
+
const eventEmitter = events.getEventEmitter();
|
|
2121
|
+
for (const outline of outlines) {
|
|
2122
|
+
const outlineMode = resolveModeFromTags(outline.mode, outline.tags);
|
|
2123
|
+
const suite = selectSuiteByMode(runtime.suite, outlineMode);
|
|
2124
|
+
const timeout = resolveTimeout(outline.timeout, config);
|
|
2125
|
+
runSuiteWithMetadata(
|
|
2126
|
+
suite,
|
|
2127
|
+
{ kind: "scenarioOutline", keyword: outline.keyword },
|
|
2128
|
+
outline.name,
|
|
2129
|
+
() => {
|
|
2130
|
+
const firstRule = outline.examples[0]?.rule?.rule;
|
|
2131
|
+
runtime.beforeAll(async () => {
|
|
2132
|
+
await eventEmitter.scenarioOutlineStarted({
|
|
2133
|
+
feature: featureRef,
|
|
2134
|
+
scenarioOutline: outline.outline,
|
|
2135
|
+
...firstRule ? { rule: createRuleRef(firstRule) } : {}
|
|
2136
|
+
});
|
|
2137
|
+
});
|
|
2138
|
+
runtime.afterAll(async () => {
|
|
2139
|
+
await eventEmitter.scenarioOutlineCompleted({
|
|
2140
|
+
feature: featureRef,
|
|
2141
|
+
scenarioOutline: outline.outline,
|
|
2142
|
+
...firstRule ? { rule: createRuleRef(firstRule) } : {}
|
|
2143
|
+
});
|
|
2144
|
+
});
|
|
2145
|
+
lifecycle.configurePersistentScope(outline.scope, runtime);
|
|
2146
|
+
registerScenarioExecutions(outline.examples, runtime, config, tagFilter, lifecycle, feature);
|
|
2147
|
+
},
|
|
2148
|
+
timeout.milliseconds
|
|
2149
|
+
);
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
function registerScenarios(scenarios, runtime, config, tagFilter, lifecycle, feature) {
|
|
2153
|
+
registerScenarioExecutions(scenarios, runtime, config, tagFilter, lifecycle, feature);
|
|
2154
|
+
}
|
|
2155
|
+
function registerScenarioExecutions(executions, runtime, config, tagFilter, lifecycle, feature) {
|
|
2156
|
+
const standaloneExecutions = [];
|
|
2157
|
+
const outlineExamples = /* @__PURE__ */ new Map();
|
|
2158
|
+
for (const execution of executions) {
|
|
2159
|
+
if (isScenarioOutlineExample2(execution)) {
|
|
2160
|
+
const outlineId = execution.outline.scope.id;
|
|
2161
|
+
let collection = outlineExamples.get(outlineId);
|
|
2162
|
+
if (!collection) {
|
|
2163
|
+
collection = {
|
|
2164
|
+
outline: execution.outline,
|
|
2165
|
+
order: [],
|
|
2166
|
+
groups: /* @__PURE__ */ new Map()
|
|
2167
|
+
};
|
|
2168
|
+
outlineExamples.set(outlineId, collection);
|
|
2169
|
+
}
|
|
2170
|
+
const groupId = execution.exampleGroup.id;
|
|
2171
|
+
let groupInfo = collection.groups.get(groupId);
|
|
2172
|
+
if (!groupInfo) {
|
|
2173
|
+
groupInfo = {
|
|
2174
|
+
group: execution.exampleGroup,
|
|
2175
|
+
examples: []
|
|
2176
|
+
};
|
|
2177
|
+
collection.groups.set(groupId, groupInfo);
|
|
2178
|
+
collection.order.push(groupId);
|
|
2179
|
+
}
|
|
2180
|
+
groupInfo.examples.push(execution);
|
|
2181
|
+
continue;
|
|
2182
|
+
}
|
|
2183
|
+
standaloneExecutions.push(execution);
|
|
2184
|
+
}
|
|
2185
|
+
for (const execution of standaloneExecutions) {
|
|
2186
|
+
scheduleScenario(execution, runtime, config, tagFilter, lifecycle, feature);
|
|
2187
|
+
}
|
|
2188
|
+
for (const collection of outlineExamples.values()) {
|
|
2189
|
+
const orderedGroups = collection.order.map((id) => collection.groups.get(id)).filter((info) => Boolean(info));
|
|
2190
|
+
if (orderedGroups.length === 0) {
|
|
2191
|
+
continue;
|
|
2192
|
+
}
|
|
2193
|
+
if (orderedGroups.length === 1) {
|
|
2194
|
+
const [singleGroup] = orderedGroups;
|
|
2195
|
+
if (singleGroup && !shouldDisplayExamplesGroup(singleGroup.group, orderedGroups.length)) {
|
|
2196
|
+
for (const example of singleGroup.examples) {
|
|
2197
|
+
scheduleScenario(example, runtime, config, tagFilter, lifecycle, feature);
|
|
2198
|
+
}
|
|
2199
|
+
continue;
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
orderedGroups.forEach((info, index) => {
|
|
2203
|
+
const title = formatExamplesGroupTitle(info.group, index);
|
|
2204
|
+
const keyword = (info.group.keyword ?? "Examples").trim() || "Examples";
|
|
2205
|
+
runSuiteWithMetadata(
|
|
2206
|
+
runtime.suite,
|
|
2207
|
+
{ kind: "examples", keyword },
|
|
2208
|
+
title,
|
|
2209
|
+
() => {
|
|
2210
|
+
for (const example of info.examples) {
|
|
2211
|
+
scheduleScenario(example, runtime, config, tagFilter, lifecycle, feature);
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
);
|
|
2215
|
+
});
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
function scheduleScenario(execution, runtime, config, tagFilter, lifecycle, feature) {
|
|
2219
|
+
const title = buildScenarioTitle(execution);
|
|
2220
|
+
const eventEmitter = events.getEventEmitter();
|
|
2221
|
+
if (!tagFilter.evaluate(execution.tags)) {
|
|
2222
|
+
runtime.test.skip(title, () => void 0);
|
|
2223
|
+
return;
|
|
2224
|
+
}
|
|
2225
|
+
if (execution.pending) {
|
|
2226
|
+
execution.markPending(execution.pendingReason);
|
|
2227
|
+
registerPendingScenarioTest(execution, runtime, title);
|
|
2228
|
+
return;
|
|
2229
|
+
}
|
|
2230
|
+
const effectiveMode = resolveModeFromTags(execution.mode, execution.tags);
|
|
2231
|
+
const testFn = selectTestByMode(runtime.test, effectiveMode);
|
|
2232
|
+
const scenarioTimeout = resolveTimeout(execution.timeout, config);
|
|
2233
|
+
testFn(title, async () => {
|
|
2234
|
+
const hooks = lifecycle.collectScenarioHooks(execution);
|
|
2235
|
+
const pickle = requirePickle(feature, execution.gherkin.id);
|
|
2236
|
+
const scenarioScope = pickle.scenario;
|
|
2237
|
+
const isExample = isScenarioOutlineExample2(execution);
|
|
2238
|
+
if (isExample) {
|
|
2239
|
+
await eventEmitter.exampleStarted({
|
|
2240
|
+
feature: pickle.feature,
|
|
2241
|
+
scenarioOutline: execution.outline.outline,
|
|
2242
|
+
example: execution.exampleGroup,
|
|
2243
|
+
pickle,
|
|
2244
|
+
...pickle.rule ? { rule: pickle.rule } : {}
|
|
2245
|
+
});
|
|
2246
|
+
}
|
|
2247
|
+
await eventEmitter.scenarioStarted({
|
|
2248
|
+
feature: pickle.feature,
|
|
2249
|
+
scenario: scenarioScope,
|
|
2250
|
+
pickle,
|
|
2251
|
+
...pickle.rule ? { rule: pickle.rule } : {}
|
|
2252
|
+
});
|
|
2253
|
+
let status;
|
|
2254
|
+
try {
|
|
2255
|
+
await lifecycle.runScenario(
|
|
2256
|
+
execution,
|
|
2257
|
+
hooks,
|
|
2258
|
+
async (_world, context) => {
|
|
2259
|
+
await runScenarioExecution(execution, context);
|
|
2260
|
+
},
|
|
2261
|
+
{ events: { pickle } }
|
|
2262
|
+
);
|
|
2263
|
+
status = execution.result.status === "passed" ? events.TestStatus.PASSED : execution.result.status === "failed" ? events.TestStatus.FAILED : execution.result.status === "skipped" ? events.TestStatus.SKIPPED : execution.result.status === "pending" ? events.TestStatus.SKIPPED : void 0;
|
|
2264
|
+
} catch (error) {
|
|
2265
|
+
status = events.TestStatus.FAILED;
|
|
2266
|
+
if (!errors.isGherkinStepError(error)) {
|
|
2267
|
+
await eventEmitter.errorRaised({
|
|
2268
|
+
error,
|
|
2269
|
+
phase: "scenario",
|
|
2270
|
+
feature: pickle.feature,
|
|
2271
|
+
scenario: pickle.scenario,
|
|
2272
|
+
...pickle.rule ? { rule: pickle.rule } : {},
|
|
2273
|
+
pickle
|
|
2274
|
+
});
|
|
2275
|
+
}
|
|
2276
|
+
throw error;
|
|
2277
|
+
} finally {
|
|
2278
|
+
if (status) {
|
|
2279
|
+
await eventEmitter.statusChanged({
|
|
2280
|
+
status,
|
|
2281
|
+
feature: pickle.feature,
|
|
2282
|
+
scenario: pickle.scenario,
|
|
2283
|
+
...pickle.rule ? { rule: pickle.rule } : {},
|
|
2284
|
+
pickle,
|
|
2285
|
+
metadata: { result: execution.result }
|
|
2286
|
+
});
|
|
2287
|
+
}
|
|
2288
|
+
await eventEmitter.scenarioCompleted({
|
|
2289
|
+
feature: pickle.feature,
|
|
2290
|
+
scenario: scenarioScope,
|
|
2291
|
+
pickle,
|
|
2292
|
+
...pickle.rule ? { rule: pickle.rule } : {},
|
|
2293
|
+
metadata: { result: execution.result }
|
|
2294
|
+
});
|
|
2295
|
+
if (isExample) {
|
|
2296
|
+
await eventEmitter.exampleCompleted({
|
|
2297
|
+
feature: pickle.feature,
|
|
2298
|
+
scenarioOutline: execution.outline.outline,
|
|
2299
|
+
example: execution.exampleGroup,
|
|
2300
|
+
pickle,
|
|
2301
|
+
...pickle.rule ? { rule: pickle.rule } : {},
|
|
2302
|
+
metadata: { result: execution.result }
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
}, scenarioTimeout.milliseconds);
|
|
2307
|
+
}
|
|
2308
|
+
function registerPendingScenarioTest(execution, runtime, title) {
|
|
2309
|
+
const reason = execution.pendingReason;
|
|
2310
|
+
const { test } = runtime;
|
|
2311
|
+
if (typeof test.todo === "function") {
|
|
2312
|
+
test.todo(title, reason);
|
|
2313
|
+
return;
|
|
2314
|
+
}
|
|
2315
|
+
if (typeof test.pending === "function") {
|
|
2316
|
+
test.pending(title, reason);
|
|
2317
|
+
return;
|
|
2318
|
+
}
|
|
2319
|
+
if (typeof test.skip === "function") {
|
|
2320
|
+
test.skip(title, () => void 0);
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
test(title, () => void 0);
|
|
2324
|
+
}
|
|
2325
|
+
function buildScenarioTitle(execution) {
|
|
2326
|
+
if (!isScenarioOutlineExample2(execution)) {
|
|
2327
|
+
return execution.name;
|
|
2328
|
+
}
|
|
2329
|
+
const descriptor = formatExampleDescriptor(execution);
|
|
2330
|
+
if (!descriptor) {
|
|
2331
|
+
return `${execution.name} [Example ${execution.exampleIndex + 1}]`;
|
|
2332
|
+
}
|
|
2333
|
+
return `${execution.name} [${descriptor}]`;
|
|
2334
|
+
}
|
|
2335
|
+
function formatExampleDescriptor(example) {
|
|
2336
|
+
const segments = [];
|
|
2337
|
+
segments.push(`Example ${example.exampleIndex + 1}`);
|
|
2338
|
+
const groupName = example.exampleGroup.name?.trim();
|
|
2339
|
+
if (groupName) {
|
|
2340
|
+
segments.push(groupName);
|
|
2341
|
+
}
|
|
2342
|
+
const valueSummary = formatExampleValues(example.exampleGroup, example.exampleIndex);
|
|
2343
|
+
if (valueSummary) {
|
|
2344
|
+
segments.push(valueSummary);
|
|
2345
|
+
}
|
|
2346
|
+
return segments.length > 0 ? segments.join(" \xB7 ") : void 0;
|
|
2347
|
+
}
|
|
2348
|
+
function formatExampleValues(group, index) {
|
|
2349
|
+
const headers = group.tableHeader ?? [];
|
|
2350
|
+
const rows = group.tableBody ?? [];
|
|
2351
|
+
const row = rows[index];
|
|
2352
|
+
if (!row || headers.length === 0) {
|
|
2353
|
+
return void 0;
|
|
2354
|
+
}
|
|
2355
|
+
const pairs = [];
|
|
2356
|
+
headers.forEach((header, headerIndex) => {
|
|
2357
|
+
const key = header?.trim();
|
|
2358
|
+
if (!key) {
|
|
2359
|
+
return;
|
|
2360
|
+
}
|
|
2361
|
+
const value = row[headerIndex] ?? "";
|
|
2362
|
+
pairs.push(`${key}=${String(value).trim()}`);
|
|
2363
|
+
});
|
|
2364
|
+
return pairs.length > 0 ? pairs.join(", ") : void 0;
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// src/index.ts
|
|
2368
|
+
var src_default = {};
|
|
2369
|
+
|
|
2370
|
+
exports.Pending = Pending;
|
|
2371
|
+
exports.ScenarioPendingError = ScenarioPendingError;
|
|
2372
|
+
exports.ScopeLifecycle = ScopeLifecycle;
|
|
2373
|
+
exports.ToDo = ToDo;
|
|
2374
|
+
exports.chooseTimeout = chooseTimeout;
|
|
2375
|
+
exports.clearStepDocstring = clearStepDocstring;
|
|
2376
|
+
exports.clearStepMetadata = clearStepMetadata;
|
|
2377
|
+
exports.clearStepTable = clearStepTable;
|
|
2378
|
+
exports.collectScenarioHooks = collectScenarioHooks;
|
|
2379
|
+
exports.configureStepDocstrings = configureStepDocstrings;
|
|
2380
|
+
exports.configureStepTables = configureStepTables;
|
|
2381
|
+
exports.consumeDocstring = consumeDocstring;
|
|
2382
|
+
exports.consumeTable = consumeTable;
|
|
2383
|
+
exports.createStepRuntime = createStepRuntime;
|
|
2384
|
+
exports.createTagFilter = createTagFilter;
|
|
2385
|
+
exports.default = src_default;
|
|
2386
|
+
exports.getDocstring = getDocstring;
|
|
2387
|
+
exports.getDocstringInfo = getDocstringInfo;
|
|
2388
|
+
exports.getDocstringMediaType = getDocstringMediaType;
|
|
2389
|
+
exports.getRawTable = getRawTable;
|
|
2390
|
+
exports.getStepMetadata = getStepMetadata;
|
|
2391
|
+
exports.getTable = getTable;
|
|
2392
|
+
exports.getWorld = getWorld;
|
|
2393
|
+
exports.isScenarioPendingError = isScenarioPendingError;
|
|
2394
|
+
exports.markScenarioPending = markScenarioPending;
|
|
2395
|
+
exports.registerFeaturePlan = registerFeaturePlan;
|
|
2396
|
+
exports.resetStepDocstringConfig = resetStepDocstringConfig;
|
|
2397
|
+
exports.resetStepTableConfig = resetStepTableConfig;
|
|
2398
|
+
exports.resolveModeFromTags = resolveModeFromTags;
|
|
2399
|
+
exports.resolveTimeout = resolveTimeout;
|
|
2400
|
+
exports.runScenarioExecution = runScenarioExecution;
|
|
2401
|
+
exports.selectSuiteByMode = selectSuiteByMode;
|
|
2402
|
+
exports.selectTestByMode = selectTestByMode;
|
|
2403
|
+
exports.setStepDocstring = setStepDocstring;
|
|
2404
|
+
exports.setStepDocstringInfo = setStepDocstringInfo;
|
|
2405
|
+
exports.setStepMetadata = setStepMetadata;
|
|
2406
|
+
exports.setStepTable = setStepTable;
|
|
2407
|
+
exports.tryGetWorld = tryGetWorld;
|
|
2408
|
+
//# sourceMappingURL=out.js.map
|
|
2409
|
+
//# sourceMappingURL=index.cjs.map
|