@autometa/app 0.4.2 → 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/README.md +1 -1
- package/dist/create-step-definitions.d.ts +11 -0
- package/dist/index.cjs +499 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2 -110
- package/dist/index.js +489 -63
- package/dist/index.js.map +1 -1
- package/dist/internal/default-dsl.d.ts +2 -0
- package/dist/internal/scope-manager.d.ts +42 -0
- package/dist/types.d.ts +126 -0
- package/package.json +27 -44
- package/.eslintignore +0 -3
- package/.eslintrc.cjs +0 -4
- package/.turbo/turbo-build.log +0 -21
- package/.turbo/turbo-clean.log +0 -4
- package/.turbo/turbo-coverage.log +0 -22
- package/.turbo/turbo-lint$colon$fix.log +0 -4
- package/.turbo/turbo-lint.log +0 -4
- package/.turbo/turbo-lint:fix.log +0 -4
- package/.turbo/turbo-prettify.log +0 -0
- package/.turbo/turbo-test.log +0 -12
- package/CHANGELOG.md +0 -234
- package/dist/esm/index.js +0 -41
- package/dist/esm/index.js.map +0 -1
- package/dist/index.d.cts +0 -110
- package/tsup.config.ts +0 -14
- package/vite.config.ts +0 -10
package/README.md
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { StepSuite, StepFactoryOptions, StepFlowBuilder } from "./types";
|
|
2
|
+
import type { WorldCtor, StepRuntimeContext } from "./types";
|
|
3
|
+
interface FlowCreator {
|
|
4
|
+
<TScenario extends object, TFeature extends object | undefined = undefined, TRule extends object | undefined = undefined, TOutline extends object | undefined = undefined, Ctx = StepRuntimeContext>(scenario: WorldCtor<TScenario>, options?: StepFactoryOptions<TFeature, TRule, TOutline, Ctx>): StepFlowBuilder;
|
|
5
|
+
}
|
|
6
|
+
interface StepDefinitionsFactory {
|
|
7
|
+
<TScenario extends object, TFeature extends object | undefined = undefined, TRule extends object | undefined = undefined, TOutline extends object | undefined = undefined, Ctx = StepRuntimeContext>(scenario: WorldCtor<TScenario>, options?: StepFactoryOptions<TFeature, TRule, TOutline, Ctx>): StepSuite<TScenario, TFeature, TRule, TOutline, Ctx>;
|
|
8
|
+
flow: FlowCreator;
|
|
9
|
+
}
|
|
10
|
+
export declare const createStepDefinitions: StepDefinitionsFactory;
|
|
11
|
+
export {};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@autometa/errors');
|
|
4
|
+
var injection = require('@autometa/injection');
|
|
5
|
+
|
|
6
|
+
// src/create-step-definitions.ts
|
|
7
|
+
var ScopeManager = class {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.options = options;
|
|
10
|
+
this.root = new injection.Container();
|
|
11
|
+
this.enterHandlers = {
|
|
12
|
+
feature: /* @__PURE__ */ new Set(),
|
|
13
|
+
rule: /* @__PURE__ */ new Set(),
|
|
14
|
+
outline: /* @__PURE__ */ new Set(),
|
|
15
|
+
scenario: /* @__PURE__ */ new Set()
|
|
16
|
+
};
|
|
17
|
+
this.exitHandlers = {
|
|
18
|
+
feature: /* @__PURE__ */ new Set(),
|
|
19
|
+
rule: /* @__PURE__ */ new Set(),
|
|
20
|
+
outline: /* @__PURE__ */ new Set(),
|
|
21
|
+
scenario: /* @__PURE__ */ new Set()
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
getHierarchy() {
|
|
25
|
+
if (!this.scenario) {
|
|
26
|
+
throw new errors.AutomationError("Scenario world has not been initialised yet.");
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
scenario: this.scenario.instance,
|
|
30
|
+
feature: this.feature?.instance ?? void 0,
|
|
31
|
+
rule: this.rule?.instance ?? void 0,
|
|
32
|
+
outline: this.outline?.instance ?? void 0
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async startScenario(rawContext, explicitKeys) {
|
|
36
|
+
const context = rawContext ?? {};
|
|
37
|
+
const keys = explicitKeys ?? this.resolveKeys(context);
|
|
38
|
+
await this.ensureFeature(keys, context);
|
|
39
|
+
await this.ensureRule(keys, context);
|
|
40
|
+
await this.ensureOutline(keys, context);
|
|
41
|
+
if (this.scenario) {
|
|
42
|
+
await this.disposeScenario(false);
|
|
43
|
+
}
|
|
44
|
+
this.scenario = this.createScopeState(
|
|
45
|
+
this.options.scenario,
|
|
46
|
+
keys.scenario,
|
|
47
|
+
this.parentContainerFor("scenario"),
|
|
48
|
+
context
|
|
49
|
+
);
|
|
50
|
+
this.syncHierarchyReferences();
|
|
51
|
+
await this.triggerEnter("scenario", context);
|
|
52
|
+
}
|
|
53
|
+
async finishScenario(context) {
|
|
54
|
+
await this.disposeScenario(true, context);
|
|
55
|
+
}
|
|
56
|
+
async resetAll(context) {
|
|
57
|
+
await this.disposeScenario(true, context);
|
|
58
|
+
await this.disposeOutline(context);
|
|
59
|
+
await this.disposeRule(context);
|
|
60
|
+
await this.disposeFeature(context);
|
|
61
|
+
}
|
|
62
|
+
onEnter(scope, handler) {
|
|
63
|
+
this.enterHandlers[scope].add(handler);
|
|
64
|
+
}
|
|
65
|
+
onExit(scope, handler) {
|
|
66
|
+
this.exitHandlers[scope].add(handler);
|
|
67
|
+
}
|
|
68
|
+
resolveKeys(context) {
|
|
69
|
+
const { keyResolver } = this.options;
|
|
70
|
+
const result = {
|
|
71
|
+
scenario: keyResolver.scenario(context)
|
|
72
|
+
};
|
|
73
|
+
const feature = keyResolver.feature?.(context);
|
|
74
|
+
if (feature) {
|
|
75
|
+
result.feature = feature;
|
|
76
|
+
}
|
|
77
|
+
const rule = keyResolver.rule?.(context);
|
|
78
|
+
if (rule) {
|
|
79
|
+
result.rule = rule;
|
|
80
|
+
}
|
|
81
|
+
const outline = keyResolver.outline?.(context);
|
|
82
|
+
if (outline) {
|
|
83
|
+
result.outline = outline;
|
|
84
|
+
}
|
|
85
|
+
if (!result.feature) {
|
|
86
|
+
result.feature = "feature";
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
hasScenario() {
|
|
91
|
+
return Boolean(this.scenario);
|
|
92
|
+
}
|
|
93
|
+
parentContainerFor(scope) {
|
|
94
|
+
switch (scope) {
|
|
95
|
+
case "feature":
|
|
96
|
+
return this.root;
|
|
97
|
+
case "rule":
|
|
98
|
+
return this.feature?.container ?? this.root;
|
|
99
|
+
case "outline":
|
|
100
|
+
return this.rule?.container ?? this.feature?.container ?? this.root;
|
|
101
|
+
case "scenario":
|
|
102
|
+
default:
|
|
103
|
+
return this.outline?.container ?? this.rule?.container ?? this.feature?.container ?? this.root;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
ensureFeature(keys, context) {
|
|
107
|
+
const featureCtor = this.options.feature;
|
|
108
|
+
if (!featureCtor) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (this.feature && this.feature.key === keys.feature) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
return this.replaceFeature(featureCtor, keys.feature ?? "feature", context);
|
|
115
|
+
}
|
|
116
|
+
async ensureRule(keys, context) {
|
|
117
|
+
const ruleCtor = this.options.rule;
|
|
118
|
+
if (!ruleCtor) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (this.rule && this.rule.key === keys.rule) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
await this.disposeRule(context);
|
|
125
|
+
if (!keys.rule) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this.rule = this.createScopeState(
|
|
129
|
+
ruleCtor,
|
|
130
|
+
keys.rule,
|
|
131
|
+
this.parentContainerFor("rule"),
|
|
132
|
+
context
|
|
133
|
+
);
|
|
134
|
+
this.syncHierarchyReferences();
|
|
135
|
+
await this.triggerEnter("rule", context);
|
|
136
|
+
}
|
|
137
|
+
async ensureOutline(keys, context) {
|
|
138
|
+
const outlineCtor = this.options.outline;
|
|
139
|
+
if (!outlineCtor) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (this.outline && this.outline.key === keys.outline) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
await this.disposeOutline(context);
|
|
146
|
+
if (!keys.outline) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.outline = this.createScopeState(
|
|
150
|
+
outlineCtor,
|
|
151
|
+
keys.outline,
|
|
152
|
+
this.parentContainerFor("outline"),
|
|
153
|
+
context
|
|
154
|
+
);
|
|
155
|
+
this.syncHierarchyReferences();
|
|
156
|
+
await this.triggerEnter("outline", context);
|
|
157
|
+
}
|
|
158
|
+
async replaceFeature(ctor, key, context) {
|
|
159
|
+
await this.disposeFeature(context);
|
|
160
|
+
this.feature = this.createScopeState(ctor, key, this.parentContainerFor("feature"), context);
|
|
161
|
+
this.syncHierarchyReferences();
|
|
162
|
+
await this.triggerEnter("feature", context);
|
|
163
|
+
}
|
|
164
|
+
createScopeState(ctor, key, parent, context) {
|
|
165
|
+
const container = parent.createChild();
|
|
166
|
+
container.registerClass(ctor, { scope: injection.Scope.SINGLETON });
|
|
167
|
+
const instance = container.resolve(ctor);
|
|
168
|
+
return { ctor, key, container, instance, context };
|
|
169
|
+
}
|
|
170
|
+
async disposeScenario(runHandlers, context) {
|
|
171
|
+
if (!this.scenario) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (runHandlers) {
|
|
175
|
+
await this.triggerExit("scenario", context ?? this.scenario.context);
|
|
176
|
+
}
|
|
177
|
+
await this.scenario.container.dispose();
|
|
178
|
+
this.scenario = void 0;
|
|
179
|
+
}
|
|
180
|
+
async disposeOutline(context) {
|
|
181
|
+
if (!this.outline) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
await this.triggerExit("outline", context ?? this.outline.context);
|
|
185
|
+
await this.outline.container.dispose();
|
|
186
|
+
this.outline = void 0;
|
|
187
|
+
}
|
|
188
|
+
async disposeRule(context) {
|
|
189
|
+
if (!this.rule) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
await this.triggerExit("rule", context ?? this.rule.context);
|
|
193
|
+
await this.rule.container.dispose();
|
|
194
|
+
this.rule = void 0;
|
|
195
|
+
}
|
|
196
|
+
async disposeFeature(context) {
|
|
197
|
+
if (!this.feature) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
await this.triggerExit("feature", context ?? this.feature.context);
|
|
201
|
+
await this.feature.container.dispose();
|
|
202
|
+
this.feature = void 0;
|
|
203
|
+
}
|
|
204
|
+
async triggerEnter(scope, context) {
|
|
205
|
+
const handlers = this.enterHandlers[scope];
|
|
206
|
+
if (!handlers.size) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const payload = this.createPayload(scope);
|
|
210
|
+
for (const handler of handlers) {
|
|
211
|
+
await handler(payload, context);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async triggerExit(scope, context) {
|
|
215
|
+
const handlers = this.exitHandlers[scope];
|
|
216
|
+
if (!handlers.size) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const payload = this.createPayload(scope);
|
|
220
|
+
for (const handler of handlers) {
|
|
221
|
+
await handler(payload, context);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
createPayload(scope) {
|
|
225
|
+
switch (scope) {
|
|
226
|
+
case "feature":
|
|
227
|
+
if (!this.feature) {
|
|
228
|
+
throw new errors.AutomationError("Feature world has not been initialised.");
|
|
229
|
+
}
|
|
230
|
+
return { feature: this.feature.instance };
|
|
231
|
+
case "rule":
|
|
232
|
+
if (!this.rule) {
|
|
233
|
+
throw new errors.AutomationError("Rule world has not been initialised.");
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
feature: this.feature?.instance ?? void 0,
|
|
237
|
+
rule: this.rule.instance
|
|
238
|
+
};
|
|
239
|
+
case "outline":
|
|
240
|
+
if (!this.outline) {
|
|
241
|
+
throw new errors.AutomationError("Outline world has not been initialised.");
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
feature: this.feature?.instance ?? void 0,
|
|
245
|
+
rule: this.rule?.instance ?? void 0,
|
|
246
|
+
outline: this.outline.instance
|
|
247
|
+
};
|
|
248
|
+
case "scenario":
|
|
249
|
+
default:
|
|
250
|
+
if (!this.scenario) {
|
|
251
|
+
throw new errors.AutomationError("Scenario world has not been initialised.");
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
feature: this.feature?.instance ?? void 0,
|
|
255
|
+
rule: this.rule?.instance ?? void 0,
|
|
256
|
+
outline: this.outline?.instance ?? void 0,
|
|
257
|
+
scenario: this.scenario.instance
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
syncHierarchyReferences() {
|
|
262
|
+
if (this.rule?.instance && this.feature?.instance) {
|
|
263
|
+
this.attachParent(this.rule.instance, "feature", this.feature.instance);
|
|
264
|
+
}
|
|
265
|
+
if (this.outline?.instance) {
|
|
266
|
+
if (this.feature?.instance) {
|
|
267
|
+
this.attachParent(this.outline.instance, "feature", this.feature.instance);
|
|
268
|
+
}
|
|
269
|
+
if (this.rule?.instance) {
|
|
270
|
+
this.attachParent(this.outline.instance, "rule", this.rule.instance);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (this.scenario?.instance) {
|
|
274
|
+
if (this.feature?.instance) {
|
|
275
|
+
this.attachParent(this.scenario.instance, "feature", this.feature.instance);
|
|
276
|
+
}
|
|
277
|
+
if (this.rule?.instance) {
|
|
278
|
+
this.attachParent(this.scenario.instance, "rule", this.rule.instance);
|
|
279
|
+
}
|
|
280
|
+
if (this.outline?.instance) {
|
|
281
|
+
this.attachParent(this.scenario.instance, "outline", this.outline.instance);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
attachParent(target, property, value) {
|
|
286
|
+
if (property in target && Reflect.get(target, property) === value) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
Object.defineProperty(target, property, {
|
|
290
|
+
value,
|
|
291
|
+
enumerable: false,
|
|
292
|
+
configurable: true,
|
|
293
|
+
writable: false
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// src/create-step-definitions.ts
|
|
299
|
+
function baseCreateStepDefinitions(scenarioCtor, options = {}) {
|
|
300
|
+
const dsl = resolveDsl(options.dsl);
|
|
301
|
+
const keyResolver = options.keyResolver ?? defaultKeyResolver;
|
|
302
|
+
const manager = new ScopeManager({
|
|
303
|
+
scenario: scenarioCtor,
|
|
304
|
+
keyResolver,
|
|
305
|
+
...options.feature ? { feature: options.feature } : {},
|
|
306
|
+
...options.rule ? { rule: options.rule } : {},
|
|
307
|
+
...options.outline ? { outline: options.outline } : {}
|
|
308
|
+
});
|
|
309
|
+
if (Array.isArray(options.expressions) && dsl.defineParameterType) {
|
|
310
|
+
for (const definition of options.expressions) {
|
|
311
|
+
dsl.defineParameterType(definition);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
setupLifecycleHooks(dsl, manager);
|
|
315
|
+
const given = wrapStepRegistrar("Given", dsl, dsl.Given, manager);
|
|
316
|
+
const when = wrapStepRegistrar("When", dsl, dsl.When, manager);
|
|
317
|
+
const then = wrapStepRegistrar("Then", dsl, dsl.Then, manager);
|
|
318
|
+
const and = wrapStepRegistrar("And", dsl, dsl.And ?? dsl.Given, manager);
|
|
319
|
+
const but = wrapStepRegistrar("But", dsl, dsl.But ?? dsl.Given, manager);
|
|
320
|
+
const hooks = {
|
|
321
|
+
BeforeFeature(handler) {
|
|
322
|
+
manager.onEnter("feature", handler);
|
|
323
|
+
},
|
|
324
|
+
AfterFeature(handler) {
|
|
325
|
+
manager.onExit("feature", handler);
|
|
326
|
+
},
|
|
327
|
+
BeforeRule(handler) {
|
|
328
|
+
manager.onEnter("rule", handler);
|
|
329
|
+
},
|
|
330
|
+
AfterRule(handler) {
|
|
331
|
+
manager.onExit("rule", handler);
|
|
332
|
+
},
|
|
333
|
+
BeforeOutline(handler) {
|
|
334
|
+
manager.onEnter("outline", handler);
|
|
335
|
+
},
|
|
336
|
+
AfterOutline(handler) {
|
|
337
|
+
manager.onExit("outline", handler);
|
|
338
|
+
},
|
|
339
|
+
BeforeScenario(handler) {
|
|
340
|
+
manager.onEnter("scenario", handler);
|
|
341
|
+
},
|
|
342
|
+
AfterScenario(handler) {
|
|
343
|
+
manager.onExit("scenario", handler);
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
const flow = createFlowBuilder({
|
|
347
|
+
given,
|
|
348
|
+
when,
|
|
349
|
+
then,
|
|
350
|
+
and,
|
|
351
|
+
but
|
|
352
|
+
});
|
|
353
|
+
return {
|
|
354
|
+
Given: given,
|
|
355
|
+
When: when,
|
|
356
|
+
Then: then,
|
|
357
|
+
And: and,
|
|
358
|
+
But: but,
|
|
359
|
+
hooks,
|
|
360
|
+
flow
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
var createStepDefinitions = Object.assign(
|
|
364
|
+
baseCreateStepDefinitions,
|
|
365
|
+
{
|
|
366
|
+
flow: (scenarioCtor, options) => baseCreateStepDefinitions(scenarioCtor, options).flow
|
|
367
|
+
}
|
|
368
|
+
);
|
|
369
|
+
function resolveDsl(dsl) {
|
|
370
|
+
if (!dsl) {
|
|
371
|
+
throw new errors.AutomationError(
|
|
372
|
+
"Step-definition DSL is required. Pass an explicit dsl option when creating step definitions."
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
return ensureRegistrars(dsl);
|
|
376
|
+
}
|
|
377
|
+
function ensureRegistrars(dsl) {
|
|
378
|
+
if (!dsl.Given || !dsl.When || !dsl.Then) {
|
|
379
|
+
throw new errors.AutomationError("Step DSL must provide Given, When, and Then registrars.");
|
|
380
|
+
}
|
|
381
|
+
return dsl;
|
|
382
|
+
}
|
|
383
|
+
function wrapStepRegistrar(keyword, dsl, registrar, manager) {
|
|
384
|
+
if (!registrar) {
|
|
385
|
+
return () => {
|
|
386
|
+
throw new errors.AutomationError(`Step DSL does not expose a registrar for ${keyword}.`);
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
return (expression, handler) => {
|
|
390
|
+
const wrapped = createStepWrapper(keyword, expression, handler, manager);
|
|
391
|
+
registrar.call(dsl, expression, wrapped);
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
function createStepWrapper(keyword, expression, handler, manager) {
|
|
395
|
+
return async function stepExecution(...args) {
|
|
396
|
+
if (!manager.hasScenario()) {
|
|
397
|
+
const context = resolveRuntimeContext(void 0, this);
|
|
398
|
+
const keys = manager.resolveKeys(context);
|
|
399
|
+
await manager.startScenario(context, keys);
|
|
400
|
+
}
|
|
401
|
+
const { scenario } = manager.getHierarchy();
|
|
402
|
+
try {
|
|
403
|
+
if (expectsThis(handler)) {
|
|
404
|
+
return await handler.apply(scenario, args);
|
|
405
|
+
}
|
|
406
|
+
return await handler(scenario, ...args);
|
|
407
|
+
} catch (error) {
|
|
408
|
+
throw wrapStepError(error, keyword, expression);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function expectsThis(handler) {
|
|
413
|
+
return Boolean(handler.prototype);
|
|
414
|
+
}
|
|
415
|
+
function wrapStepError(error, keyword, expression) {
|
|
416
|
+
if (error instanceof errors.AutomationError) {
|
|
417
|
+
return error;
|
|
418
|
+
}
|
|
419
|
+
const baseMessage = error instanceof Error ? error.message : typeof error === "string" ? error : "Unknown error";
|
|
420
|
+
const message = `Step failed for ${keyword} ${String(expression)}: ${baseMessage}`;
|
|
421
|
+
return new errors.AutomationError(message, {
|
|
422
|
+
cause: error instanceof Error ? error : void 0
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
function resolveRuntimeContext(hookArg, worldValue) {
|
|
426
|
+
if (hookArg && typeof hookArg === "object") {
|
|
427
|
+
return hookArg;
|
|
428
|
+
}
|
|
429
|
+
if (worldValue && typeof worldValue === "object") {
|
|
430
|
+
return worldValue;
|
|
431
|
+
}
|
|
432
|
+
return {};
|
|
433
|
+
}
|
|
434
|
+
function setupLifecycleHooks(dsl, manager) {
|
|
435
|
+
if (dsl.Before) {
|
|
436
|
+
dsl.Before.call(dsl, async function beforeScenario(context) {
|
|
437
|
+
const runtime = resolveRuntimeContext(context, this);
|
|
438
|
+
await manager.startScenario(runtime);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
if (dsl.After) {
|
|
442
|
+
dsl.After.call(dsl, async function afterScenario(context) {
|
|
443
|
+
const runtime = resolveRuntimeContext(context, this);
|
|
444
|
+
await manager.finishScenario(runtime);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
if (dsl.AfterAll) {
|
|
448
|
+
dsl.AfterAll.call(dsl, async function afterAll() {
|
|
449
|
+
const runtime = resolveRuntimeContext(void 0, this);
|
|
450
|
+
await manager.resetAll(runtime);
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
function createFlowBuilder(registrars) {
|
|
455
|
+
const builder = {
|
|
456
|
+
given: (expression) => createFlowRunner(registrars.given, expression, () => builder),
|
|
457
|
+
when: (expression) => createFlowRunner(registrars.when, expression, () => builder),
|
|
458
|
+
then: (expression) => createFlowRunner(registrars.then, expression, () => builder),
|
|
459
|
+
and: (expression) => createFlowRunner(registrars.and, expression, () => builder),
|
|
460
|
+
but: (expression) => createFlowRunner(registrars.but, expression, () => builder)
|
|
461
|
+
};
|
|
462
|
+
return builder;
|
|
463
|
+
}
|
|
464
|
+
function createFlowRunner(registrar, expression, next) {
|
|
465
|
+
return {
|
|
466
|
+
run(handler) {
|
|
467
|
+
registrar(expression, handler);
|
|
468
|
+
return next();
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
var nextScenarioId = createKeyFactory("scenario");
|
|
473
|
+
var defaultKeyResolver = {
|
|
474
|
+
feature(context) {
|
|
475
|
+
return context.gherkinDocument?.feature?.name ?? context.pickle?.uri ?? void 0;
|
|
476
|
+
},
|
|
477
|
+
rule(context) {
|
|
478
|
+
const nodes = context.pickle?.astNodeIds;
|
|
479
|
+
return Array.isArray(nodes) && nodes.length > 1 ? nodes[0] : void 0;
|
|
480
|
+
},
|
|
481
|
+
outline(context) {
|
|
482
|
+
const nodes = context.pickle?.astNodeIds;
|
|
483
|
+
if (Array.isArray(nodes) && nodes.length > 1) {
|
|
484
|
+
return nodes.slice(1).join(":");
|
|
485
|
+
}
|
|
486
|
+
return void 0;
|
|
487
|
+
},
|
|
488
|
+
scenario(context) {
|
|
489
|
+
return context.pickle?.id ?? context.pickle?.name ?? nextScenarioId();
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
function createKeyFactory(prefix) {
|
|
493
|
+
let counter = 0;
|
|
494
|
+
return () => `${prefix}-${++counter}`;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
exports.createStepDefinitions = createStepDefinitions;
|
|
498
|
+
//# sourceMappingURL=out.js.map
|
|
499
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/create-step-definitions.ts","../src/internal/scope-manager.ts"],"names":["AutomationError"],"mappings":";AAAA,SAAS,mBAAAA,wBAAuB;;;ACAhC,SAAS,WAAW,aAAa;AACjC,SAAS,uBAAuB;AAsDzB,IAAM,eAAN,MAML;AAAA,EAsBA,YAA6B,SAAyE;AAAzE;AArB7B,SAAiB,OAAO,IAAI,UAAU;AAOtC,SAAiB,gBAA0E;AAAA,MACzF,SAAS,oBAAI,IAAI;AAAA,MACjB,MAAM,oBAAI,IAAI;AAAA,MACd,SAAS,oBAAI,IAAI;AAAA,MACjB,UAAU,oBAAI,IAAI;AAAA,IACpB;AAEA,SAAiB,eAAwE;AAAA,MACvF,SAAS,oBAAI,IAAI;AAAA,MACjB,MAAM,oBAAI,IAAI;AAAA,MACd,SAAS,oBAAI,IAAI;AAAA,MACjB,UAAU,oBAAI,IAAI;AAAA,IACpB;AAAA,EAEuG;AAAA,EAEvG,eAAkH;AAChH,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,IAAI,gBAAgB,8CAA8C;AAAA,IAC1E;AAEA,WAAO;AAAA,MACL,UAAU,KAAK,SAAS;AAAA,MACxB,SAAU,KAAK,SAAS,YAAY;AAAA,MACpC,MAAO,KAAK,MAAM,YAAY;AAAA,MAC9B,SAAU,KAAK,SAAS,YAAY;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,YAA6B,cAAyC;AACxF,UAAM,UAAU,cAAe,CAAC;AAChC,UAAM,OAAO,gBAAgB,KAAK,YAAY,OAAO;AAErD,UAAM,KAAK,cAAc,MAAM,OAAO;AACtC,UAAM,KAAK,WAAW,MAAM,OAAO;AACnC,UAAM,KAAK,cAAc,MAAM,OAAO;AAEtC,QAAI,KAAK,UAAU;AACjB,YAAM,KAAK,gBAAgB,KAAK;AAAA,IAClC;AAEA,SAAK,WAAW,KAAK;AAAA,MACnB,KAAK,QAAQ;AAAA,MACb,KAAK;AAAA,MACL,KAAK,mBAAmB,UAAU;AAAA,MAClC;AAAA,IACF;AAEA,SAAK,wBAAwB;AAC7B,UAAM,KAAK,aAAa,YAAY,OAAO;AAAA,EAC7C;AAAA,EAEA,MAAM,eAAe,SAA8B;AACjD,UAAM,KAAK,gBAAgB,MAAM,OAAO;AAAA,EAC1C;AAAA,EAEA,MAAM,SAAS,SAA8B;AAC3C,UAAM,KAAK,gBAAgB,MAAM,OAAO;AACxC,UAAM,KAAK,eAAe,OAAO;AACjC,UAAM,KAAK,YAAY,OAAO;AAC9B,UAAM,KAAK,eAAe,OAAO;AAAA,EACnC;AAAA,EAEA,QACE,OACA,SACM;AACN,IAAC,KAAK,cAAc,KAAK,EAA0E,IAAI,OAAO;AAAA,EAChH;AAAA,EAEA,OACE,OACA,SACM;AACN,IAAC,KAAK,aAAa,KAAK,EAA0E,IAAI,OAAO;AAAA,EAC/G;AAAA,EAEA,YAAY,SAAyB;AACnC,UAAM,EAAE,YAAY,IAAI,KAAK;AAC7B,UAAM,SAAoB;AAAA,MACxB,UAAU,YAAY,SAAS,OAAO;AAAA,IACxC;AAEA,UAAM,UAAU,YAAY,UAAU,OAAO;AAC7C,QAAI,SAAS;AACX,aAAO,UAAU;AAAA,IACnB;AAEA,UAAM,OAAO,YAAY,OAAO,OAAO;AACvC,QAAI,MAAM;AACR,aAAO,OAAO;AAAA,IAChB;AAEA,UAAM,UAAU,YAAY,UAAU,OAAO;AAC7C,QAAI,SAAS;AACX,aAAO,UAAU;AAAA,IACnB;AAEA,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,UAAU;AAAA,IACnB;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,cAAuB;AACrB,WAAO,QAAQ,KAAK,QAAQ;AAAA,EAC9B;AAAA,EAEQ,mBAAmB,OAA8B;AACvD,YAAQ,OAAO;AAAA,MACb,KAAK;AACH,eAAO,KAAK;AAAA,MACd,KAAK;AACH,eAAO,KAAK,SAAS,aAAa,KAAK;AAAA,MACzC,KAAK;AACH,eAAO,KAAK,MAAM,aAAa,KAAK,SAAS,aAAa,KAAK;AAAA,MACjE,KAAK;AAAA,MACL;AACE,eAAO,KAAK,SAAS,aAAa,KAAK,MAAM,aAAa,KAAK,SAAS,aAAa,KAAK;AAAA,IAC9F;AAAA,EACF;AAAA,EAEQ,cAAc,MAAiB,SAAoC;AACzE,UAAM,cAAc,KAAK,QAAQ;AACjC,QAAI,CAAC,aAAa;AAChB;AAAA,IACF;AAEA,QAAI,KAAK,WAAW,KAAK,QAAQ,QAAQ,KAAK,SAAS;AACrD;AAAA,IACF;AAEA,WAAO,KAAK,eAAe,aAAa,KAAK,WAAW,WAAW,OAAO;AAAA,EAC5E;AAAA,EAEA,MAAc,WAAW,MAAiB,SAA6B;AACrE,UAAM,WAAW,KAAK,QAAQ;AAC9B,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ,KAAK,KAAK,QAAQ,KAAK,MAAM;AAC5C;AAAA,IACF;AAEA,UAAM,KAAK,YAAY,OAAO;AAE9B,QAAI,CAAC,KAAK,MAAM;AACd;AAAA,IACF;AAEA,SAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA,KAAK;AAAA,MACL,KAAK,mBAAmB,MAAM;AAAA,MAC9B;AAAA,IACF;AACA,SAAK,wBAAwB;AAC7B,UAAM,KAAK,aAAa,QAAQ,OAAO;AAAA,EACzC;AAAA,EAEA,MAAc,cAAc,MAAiB,SAA6B;AACxE,UAAM,cAAc,KAAK,QAAQ;AACjC,QAAI,CAAC,aAAa;AAChB;AAAA,IACF;AAEA,QAAI,KAAK,WAAW,KAAK,QAAQ,QAAQ,KAAK,SAAS;AACrD;AAAA,IACF;AAEA,UAAM,KAAK,eAAe,OAAO;AAEjC,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,SAAK,UAAU,KAAK;AAAA,MAClB;AAAA,MACA,KAAK;AAAA,MACL,KAAK,mBAAmB,SAAS;AAAA,MACjC;AAAA,IACF;AACA,SAAK,wBAAwB;AAC7B,UAAM,KAAK,aAAa,WAAW,OAAO;AAAA,EAC5C;AAAA,EAEA,MAAc,eACZ,MACA,KACA,SACe;AACf,UAAM,KAAK,eAAe,OAAO;AAEjC,SAAK,UAAU,KAAK,iBAAiB,MAAM,KAAK,KAAK,mBAAmB,SAAS,GAAG,OAAO;AAC3F,SAAK,wBAAwB;AAC7B,UAAM,KAAK,aAAa,WAAW,OAAO;AAAA,EAC5C;AAAA,EAEQ,iBACN,MACA,KACA,QACA,SACoB;AACpB,UAAM,YAAY,OAAO,YAAY;AACrC,cAAU,cAAc,MAAM,EAAE,OAAO,MAAM,UAAU,CAAC;AACxD,UAAM,WAAW,UAAU,QAAQ,IAAI;AACvC,WAAO,EAAE,MAAM,KAAK,WAAW,UAAU,QAAQ;AAAA,EACnD;AAAA,EAEA,MAAc,gBAAgB,aAAsB,SAA8B;AAChF,QAAI,CAAC,KAAK,UAAU;AAClB;AAAA,IACF;AAEA,QAAI,aAAa;AACf,YAAM,KAAK,YAAY,YAAY,WAAW,KAAK,SAAS,OAAO;AAAA,IACrE;AAEA,UAAM,KAAK,SAAS,UAAU,QAAQ;AACtC,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,MAAc,eAAe,SAA8B;AACzD,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,UAAM,KAAK,YAAY,WAAW,WAAW,KAAK,QAAQ,OAAO;AACjE,UAAM,KAAK,QAAQ,UAAU,QAAQ;AACrC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAc,YAAY,SAA8B;AACtD,QAAI,CAAC,KAAK,MAAM;AACd;AAAA,IACF;AAEA,UAAM,KAAK,YAAY,QAAQ,WAAW,KAAK,KAAK,OAAO;AAC3D,UAAM,KAAK,KAAK,UAAU,QAAQ;AAClC,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,MAAc,eAAe,SAA8B;AACzD,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AAEA,UAAM,KAAK,YAAY,WAAW,WAAW,KAAK,QAAQ,OAAO;AACjE,UAAM,KAAK,QAAQ,UAAU,QAAQ;AACrC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAc,aAAa,OAAmB,SAA6B;AACzE,UAAM,WAAW,KAAK,cAAc,KAAK;AACzC,QAAI,CAAC,SAAS,MAAM;AAClB;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,cAAc,KAAK;AACxC,eAAW,WAAW,UAAU;AAE9B,YAAM,QAAQ,SAAkB,OAAO;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAc,YAAY,OAAmB,SAA6B;AACxE,UAAM,WAAW,KAAK,aAAa,KAAK;AACxC,QAAI,CAAC,SAAS,MAAM;AAClB;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,cAAc,KAAK;AACxC,eAAW,WAAW,UAAU;AAE9B,YAAM,QAAQ,SAAkB,OAAO;AAAA,IACzC;AAAA,EACF;AAAA,EAEQ,cAAc,OAMpB;AACA,YAAQ,OAAO;AAAA,MACb,KAAK;AACH,YAAI,CAAC,KAAK,SAAS;AACjB,gBAAM,IAAI,gBAAgB,yCAAyC;AAAA,QACrE;AACA,eAAO,EAAE,SAAS,KAAK,QAAQ,SAAS;AAAA,MAC1C,KAAK;AACH,YAAI,CAAC,KAAK,MAAM;AACd,gBAAM,IAAI,gBAAgB,sCAAsC;AAAA,QAClE;AACA,eAAO;AAAA,UACL,SAAU,KAAK,SAAS,YAAY;AAAA,UACpC,MAAM,KAAK,KAAK;AAAA,QAClB;AAAA,MACF,KAAK;AACH,YAAI,CAAC,KAAK,SAAS;AACjB,gBAAM,IAAI,gBAAgB,yCAAyC;AAAA,QACrE;AACA,eAAO;AAAA,UACL,SAAU,KAAK,SAAS,YAAY;AAAA,UACpC,MAAO,KAAK,MAAM,YAAY;AAAA,UAC9B,SAAS,KAAK,QAAQ;AAAA,QACxB;AAAA,MACF,KAAK;AAAA,MACL;AACE,YAAI,CAAC,KAAK,UAAU;AAClB,gBAAM,IAAI,gBAAgB,0CAA0C;AAAA,QACtE;AACA,eAAO;AAAA,UACL,SAAU,KAAK,SAAS,YAAY;AAAA,UACpC,MAAO,KAAK,MAAM,YAAY;AAAA,UAC9B,SAAU,KAAK,SAAS,YAAY;AAAA,UACpC,UAAU,KAAK,SAAS;AAAA,QAC1B;AAAA,IACJ;AAAA,EACF;AAAA,EAEQ,0BAAgC;AACtC,QAAI,KAAK,MAAM,YAAY,KAAK,SAAS,UAAU;AACjD,WAAK,aAAa,KAAK,KAAK,UAAU,WAAW,KAAK,QAAQ,QAAQ;AAAA,IACxE;AAEA,QAAI,KAAK,SAAS,UAAU;AAC1B,UAAI,KAAK,SAAS,UAAU;AAC1B,aAAK,aAAa,KAAK,QAAQ,UAAU,WAAW,KAAK,QAAQ,QAAQ;AAAA,MAC3E;AACA,UAAI,KAAK,MAAM,UAAU;AACvB,aAAK,aAAa,KAAK,QAAQ,UAAU,QAAQ,KAAK,KAAK,QAAQ;AAAA,MACrE;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,UAAU;AAC3B,UAAI,KAAK,SAAS,UAAU;AAC1B,aAAK,aAAa,KAAK,SAAS,UAAU,WAAW,KAAK,QAAQ,QAAQ;AAAA,MAC5E;AACA,UAAI,KAAK,MAAM,UAAU;AACvB,aAAK,aAAa,KAAK,SAAS,UAAU,QAAQ,KAAK,KAAK,QAAQ;AAAA,MACtE;AACA,UAAI,KAAK,SAAS,UAAU;AAC1B,aAAK,aAAa,KAAK,SAAS,UAAU,WAAW,KAAK,QAAQ,QAAQ;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,aAAa,QAAgB,UAAkB,OAAqB;AAC1E,QAAI,YAAY,UAAU,QAAQ,IAAI,QAAQ,QAAQ,MAAM,OAAO;AACjE;AAAA,IACF;AAEA,WAAO,eAAe,QAAQ,UAAU;AAAA,MACtC;AAAA,MACA,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AACF;;;ADzYA,SAAS,0BAOP,cACA,UAA8D,CAAC,GACT;AACtD,QAAM,MAAM,WAAW,QAAQ,GAAG;AAClC,QAAM,cAAe,QAAQ,eAAe;AAE5C,QAAM,UAAU,IAAI,aAAwD;AAAA,IAC1E,UAAU;AAAA,IACV;AAAA,IACA,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;AAAA,IACtD,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC7C,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACxD,CAAC;AAED,MAAI,MAAM,QAAQ,QAAQ,WAAW,KAAK,IAAI,qBAAqB;AACjE,eAAW,cAAc,QAAQ,aAAa;AAC5C,UAAI,oBAAoB,UAAU;AAAA,IACpC;AAAA,EACF;AAEA,sBAAoB,KAAK,OAAO;AAEhC,QAAM,QAAQ,kBAAkB,SAAS,KAAK,IAAI,OAAO,OAAO;AAChE,QAAM,OAAO,kBAAkB,QAAQ,KAAK,IAAI,MAAM,OAAO;AAC7D,QAAM,OAAO,kBAAkB,QAAQ,KAAK,IAAI,MAAM,OAAO;AAC7D,QAAM,MAAM,kBAAkB,OAAO,KAAK,IAAI,OAAO,IAAI,OAAO,OAAO;AACvE,QAAM,MAAM,kBAAkB,OAAO,KAAK,IAAI,OAAO,IAAI,OAAO,OAAO;AAEvE,QAAM,QAA8D;AAAA,IAClE,cAAc,SAAS;AACrB,cAAQ,QAAQ,WAAW,OAAO;AAAA,IACpC;AAAA,IACA,aAAa,SAAS;AACpB,cAAQ,OAAO,WAAW,OAAO;AAAA,IACnC;AAAA,IACA,WAAW,SAAS;AAClB,cAAQ,QAAQ,QAAQ,OAAO;AAAA,IACjC;AAAA,IACA,UAAU,SAAS;AACjB,cAAQ,OAAO,QAAQ,OAAO;AAAA,IAChC;AAAA,IACA,cAAc,SAAS;AACrB,cAAQ,QAAQ,WAAW,OAAO;AAAA,IACpC;AAAA,IACA,aAAa,SAAS;AACpB,cAAQ,OAAO,WAAW,OAAO;AAAA,IACnC;AAAA,IACA,eAAe,SAAS;AACtB,cAAQ,QAAQ,YAAY,OAAO;AAAA,IACrC;AAAA,IACA,cAAc,SAAS;AACrB,cAAQ,OAAO,YAAY,OAAO;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,OAAO,kBAAkB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,wBAAgD,OAAO;AAAA,EAClE;AAAA,EACA;AAAA,IACE,MAAO,CAAC,cAAc,YACpB,0BAA0B,cAAuB,OAAgB,EAAE;AAAA,EACvE;AACF;AAEA,SAAS,WAAW,KAAmC;AACrD,MAAI,CAAC,KAAK;AACR,UAAM,IAAIA;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,iBAAiB,GAAG;AAC7B;AAEA,SAAS,iBAAiB,KAAuB;AAC/C,MAAI,CAAC,IAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAM;AACxC,UAAM,IAAIA,iBAAgB,yDAAyD;AAAA,EACrF;AACA,SAAO;AACT;AAEA,SAAS,kBAOP,SACA,KACA,WACA,SACA;AACA,MAAI,CAAC,WAAW;AACd,WAAO,MAAM;AACX,YAAM,IAAIA,iBAAgB,4CAA4C,OAAO,GAAG;AAAA,IAClF;AAAA,EACF;AAEA,SAAO,CAAC,YAA4B,YAA0B;AAC5D,UAAM,UAAU,kBAAkB,SAAS,YAAY,SAAS,OAAO;AACvE,cAAU,KAAK,KAAK,YAAY,OAAO;AAAA,EACzC;AACF;AAEA,SAAS,kBAOP,SACA,YACA,SACA,SACA;AACA,SAAO,eAAe,iBAAgC,MAAiB;AACrE,QAAI,CAAC,QAAQ,YAAY,GAAG;AAC1B,YAAM,UAAU,sBAA2B,QAAW,IAAI;AAC1D,YAAM,OAAO,QAAQ,YAAY,OAAO;AACxC,YAAM,QAAQ,cAAc,SAAS,IAAI;AAAA,IAC3C;AAEA,UAAM,EAAE,SAAS,IAAI,QAAQ,aAAa;AAE1C,QAAI;AACF,UAAI,YAAY,OAAO,GAAG;AACxB,eAAO,MAAM,QAAQ,MAAM,UAAU,IAAI;AAAA,MAC3C;AAEA,aAAO,MAAM,QAAQ,UAAU,GAAG,IAAI;AAAA,IACxC,SAAS,OAAO;AACd,YAAM,cAAc,OAAO,SAAS,UAAU;AAAA,IAChD;AAAA,EACF;AACF;AAEA,SAAS,YAAY,SAAgC;AACnD,SAAO,QAAS,QAAoC,SAAS;AAC/D;AAEA,SAAS,cAAc,OAAgB,SAAiB,YAA6C;AACnG,MAAI,iBAAiBA,kBAAiB;AACpC,WAAO;AAAA,EACT;AAEA,QAAM,cACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,UAAU,WAAW,QAAQ;AAC/E,QAAM,UAAU,mBAAmB,OAAO,IAAI,OAAO,UAAU,CAAC,KAAK,WAAW;AAEhF,SAAO,IAAIA,iBAAgB,SAAS;AAAA,IAClC,OAAO,iBAAiB,QAAQ,QAAQ;AAAA,EAC1C,CAAC;AACH;AAEA,SAAS,sBAA2B,SAAkB,YAA0B;AAC9E,MAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,WAAO;AAAA,EACT;AACA,MAAI,cAAc,OAAO,eAAe,UAAU;AAChD,WAAO;AAAA,EACT;AACA,SAAO,CAAC;AACV;AAEA,SAAS,oBAMP,KAAc,SAAwE;AACtF,MAAI,IAAI,QAAQ;AACd,QAAI,OAAO,KAAK,KAAK,eAAe,eAA8B,SAAkB;AAClF,YAAM,UAAU,sBAA2B,SAAS,IAAI;AACxD,YAAM,QAAQ,cAAc,OAAO;AAAA,IACrC,CAAC;AAAA,EACH;AAEA,MAAI,IAAI,OAAO;AACb,QAAI,MAAM,KAAK,KAAK,eAAe,cAA6B,SAAkB;AAChF,YAAM,UAAU,sBAA2B,SAAS,IAAI;AACxD,YAAM,QAAQ,eAAe,OAAO;AAAA,IACtC,CAAC;AAAA,EACH;AAEA,MAAI,IAAI,UAAU;AAChB,QAAI,SAAS,KAAK,KAAK,eAAe,WAAwB;AAC5D,YAAM,UAAU,sBAA2B,QAAW,IAAI;AAC1D,YAAM,QAAQ,SAAS,OAAO;AAAA,IAChC,CAAC;AAAA,EACH;AACF;AAEA,SAAS,kBAAkB,YAMP;AAClB,QAAM,UAA2B;AAAA,IAC/B,OAAO,CAAC,eAAe,iBAAiB,WAAW,OAAO,YAAY,MAAM,OAAO;AAAA,IACnF,MAAM,CAAC,eAAe,iBAAiB,WAAW,MAAM,YAAY,MAAM,OAAO;AAAA,IACjF,MAAM,CAAC,eAAe,iBAAiB,WAAW,MAAM,YAAY,MAAM,OAAO;AAAA,IACjF,KAAK,CAAC,eAAe,iBAAiB,WAAW,KAAK,YAAY,MAAM,OAAO;AAAA,IAC/E,KAAK,CAAC,eAAe,iBAAiB,WAAW,KAAK,YAAY,MAAM,OAAO;AAAA,EACjF;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,WACA,YACA,MACA;AACA,SAAO;AAAA,IACL,IAAI,SAAuB;AACzB,gBAAU,YAAY,OAAO;AAC7B,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AACF;AAEA,IAAM,iBAAiB,iBAAiB,UAAU;AAElD,IAAM,qBAA2D;AAAA,EAC/D,QAAQ,SAAS;AACf,WAAO,QAAQ,iBAAiB,SAAS,QAAQ,QAAQ,QAAQ,OAAO;AAAA,EAC1E;AAAA,EACA,KAAK,SAAS;AACZ,UAAM,QAAQ,QAAQ,QAAQ;AAC9B,WAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI;AAAA,EAC/D;AAAA,EACA,QAAQ,SAAS;AACf,UAAM,QAAQ,QAAQ,QAAQ;AAC9B,QAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GAAG;AAC5C,aAAO,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAAA,IAChC;AACA,WAAO;AAAA,EACT;AAAA,EACA,SAAS,SAAS;AAChB,WAAO,QAAQ,QAAQ,MAAM,QAAQ,QAAQ,QAAQ,eAAe;AAAA,EACtE;AACF;AAEA,SAAS,iBAAiB,QAA8B;AACtD,MAAI,UAAU;AACd,SAAO,MAAM,GAAG,MAAM,IAAI,EAAE,OAAO;AACrC","sourcesContent":["import { AutomationError } from \"@autometa/errors\";\nimport type {\n StepSuite,\n StepFactoryOptions,\n StepDsl,\n StepExpression,\n StepCallback,\n HookSuite,\n StepFlowBuilder,\n} from \"./types\";\nimport type { WorldCtor, ScopeKeyResolver, StepRuntimeContext } from \"./types\";\nimport { ScopeManager } from \"./internal/scope-manager\";\n\ninterface FlowCreator {\n <\n TScenario extends object,\n TFeature extends object | undefined = undefined,\n TRule extends object | undefined = undefined,\n TOutline extends object | undefined = undefined,\n Ctx = StepRuntimeContext\n >(\n scenario: WorldCtor<TScenario>,\n options?: StepFactoryOptions<TFeature, TRule, TOutline, Ctx>\n ): StepFlowBuilder;\n}\n\ninterface StepDefinitionsFactory {\n <\n TScenario extends object,\n TFeature extends object | undefined = undefined,\n TRule extends object | undefined = undefined,\n TOutline extends object | undefined = undefined,\n Ctx = StepRuntimeContext\n >(\n scenario: WorldCtor<TScenario>,\n options?: StepFactoryOptions<TFeature, TRule, TOutline, Ctx>\n ): StepSuite<TScenario, TFeature, TRule, TOutline, Ctx>;\n flow: FlowCreator;\n}\n\nfunction baseCreateStepDefinitions<\n TScenario extends object,\n TFeature extends object | undefined = undefined,\n TRule extends object | undefined = undefined,\n TOutline extends object | undefined = undefined,\n Ctx = StepRuntimeContext\n>(\n scenarioCtor: WorldCtor<TScenario>,\n options: StepFactoryOptions<TFeature, TRule, TOutline, Ctx> = {}\n): StepSuite<TScenario, TFeature, TRule, TOutline, Ctx> {\n const dsl = resolveDsl(options.dsl);\n const keyResolver = (options.keyResolver ?? defaultKeyResolver) as ScopeKeyResolver<Ctx>;\n\n const manager = new ScopeManager<TScenario, TFeature, TRule, TOutline, Ctx>({\n scenario: scenarioCtor,\n keyResolver,\n ...(options.feature ? { feature: options.feature } : {}),\n ...(options.rule ? { rule: options.rule } : {}),\n ...(options.outline ? { outline: options.outline } : {}),\n });\n\n if (Array.isArray(options.expressions) && dsl.defineParameterType) {\n for (const definition of options.expressions) {\n dsl.defineParameterType(definition);\n }\n }\n\n setupLifecycleHooks(dsl, manager);\n\n const given = wrapStepRegistrar(\"Given\", dsl, dsl.Given, manager);\n const when = wrapStepRegistrar(\"When\", dsl, dsl.When, manager);\n const then = wrapStepRegistrar(\"Then\", dsl, dsl.Then, manager);\n const and = wrapStepRegistrar(\"And\", dsl, dsl.And ?? dsl.Given, manager);\n const but = wrapStepRegistrar(\"But\", dsl, dsl.But ?? dsl.Given, manager);\n\n const hooks: HookSuite<TScenario, TFeature, TRule, TOutline, Ctx> = {\n BeforeFeature(handler) {\n manager.onEnter(\"feature\", handler);\n },\n AfterFeature(handler) {\n manager.onExit(\"feature\", handler);\n },\n BeforeRule(handler) {\n manager.onEnter(\"rule\", handler);\n },\n AfterRule(handler) {\n manager.onExit(\"rule\", handler);\n },\n BeforeOutline(handler) {\n manager.onEnter(\"outline\", handler);\n },\n AfterOutline(handler) {\n manager.onExit(\"outline\", handler);\n },\n BeforeScenario(handler) {\n manager.onEnter(\"scenario\", handler);\n },\n AfterScenario(handler) {\n manager.onExit(\"scenario\", handler);\n },\n };\n\n const flow = createFlowBuilder({\n given,\n when,\n then,\n and,\n but,\n });\n\n return {\n Given: given,\n When: when,\n Then: then,\n And: and,\n But: but,\n hooks,\n flow,\n } satisfies StepSuite<TScenario, TFeature, TRule, TOutline, Ctx>;\n}\n\nexport const createStepDefinitions: StepDefinitionsFactory = Object.assign(\n baseCreateStepDefinitions as StepDefinitionsFactory,\n {\n flow: ((scenarioCtor, options) =>\n baseCreateStepDefinitions(scenarioCtor as never, options as never).flow) as FlowCreator,\n }\n);\n\nfunction resolveDsl(dsl: StepDsl | undefined): StepDsl {\n if (!dsl) {\n throw new AutomationError(\n \"Step-definition DSL is required. Pass an explicit dsl option when creating step definitions.\"\n );\n }\n\n return ensureRegistrars(dsl);\n}\n\nfunction ensureRegistrars(dsl: StepDsl): StepDsl {\n if (!dsl.Given || !dsl.When || !dsl.Then) {\n throw new AutomationError(\"Step DSL must provide Given, When, and Then registrars.\");\n }\n return dsl;\n}\n\nfunction wrapStepRegistrar<\n TScenario extends object,\n TFeature extends object | undefined,\n TRule extends object | undefined,\n TOutline extends object | undefined,\n Ctx\n>(\n keyword: string,\n dsl: StepDsl,\n registrar: StepDsl[\"Given\"] | undefined,\n manager: ScopeManager<TScenario, TFeature, TRule, TOutline, Ctx>\n) {\n if (!registrar) {\n return () => {\n throw new AutomationError(`Step DSL does not expose a registrar for ${keyword}.`);\n };\n }\n\n return (expression: StepExpression, handler: StepCallback) => {\n const wrapped = createStepWrapper(keyword, expression, handler, manager);\n registrar.call(dsl, expression, wrapped);\n };\n}\n\nfunction createStepWrapper<\n TScenario extends object,\n TFeature extends object | undefined,\n TRule extends object | undefined,\n TOutline extends object | undefined,\n Ctx\n>(\n keyword: string,\n expression: StepExpression,\n handler: StepCallback,\n manager: ScopeManager<TScenario, TFeature, TRule, TOutline, Ctx>\n) {\n return async function stepExecution(this: unknown, ...args: unknown[]) {\n if (!manager.hasScenario()) {\n const context = resolveRuntimeContext<Ctx>(undefined, this);\n const keys = manager.resolveKeys(context);\n await manager.startScenario(context, keys);\n }\n\n const { scenario } = manager.getHierarchy();\n\n try {\n if (expectsThis(handler)) {\n return await handler.apply(scenario, args);\n }\n\n return await handler(scenario, ...args);\n } catch (error) {\n throw wrapStepError(error, keyword, expression);\n }\n };\n}\n\nfunction expectsThis(handler: StepCallback): boolean {\n return Boolean((handler as { prototype?: unknown }).prototype);\n}\n\nfunction wrapStepError(error: unknown, keyword: string, expression: StepExpression): AutomationError {\n if (error instanceof AutomationError) {\n return error;\n }\n\n const baseMessage =\n error instanceof Error ? error.message : typeof error === \"string\" ? error : \"Unknown error\";\n const message = `Step failed for ${keyword} ${String(expression)}: ${baseMessage}`;\n\n return new AutomationError(message, {\n cause: error instanceof Error ? error : undefined,\n });\n}\n\nfunction resolveRuntimeContext<Ctx>(hookArg: unknown, worldValue: unknown): Ctx {\n if (hookArg && typeof hookArg === \"object\") {\n return hookArg as Ctx;\n }\n if (worldValue && typeof worldValue === \"object\") {\n return worldValue as Ctx;\n }\n return {} as Ctx;\n}\n\nfunction setupLifecycleHooks<\n TScenario extends object,\n TFeature extends object | undefined,\n TRule extends object | undefined,\n TOutline extends object | undefined,\n Ctx\n>(dsl: StepDsl, manager: ScopeManager<TScenario, TFeature, TRule, TOutline, Ctx>): void {\n if (dsl.Before) {\n dsl.Before.call(dsl, async function beforeScenario(this: unknown, context: unknown) {\n const runtime = resolveRuntimeContext<Ctx>(context, this);\n await manager.startScenario(runtime);\n });\n }\n\n if (dsl.After) {\n dsl.After.call(dsl, async function afterScenario(this: unknown, context: unknown) {\n const runtime = resolveRuntimeContext<Ctx>(context, this);\n await manager.finishScenario(runtime);\n });\n }\n\n if (dsl.AfterAll) {\n dsl.AfterAll.call(dsl, async function afterAll(this: unknown) {\n const runtime = resolveRuntimeContext<Ctx>(undefined, this);\n await manager.resetAll(runtime);\n });\n }\n}\n\nfunction createFlowBuilder(registrars: {\n readonly given: (expression: StepExpression, handler: StepCallback) => void;\n readonly when: (expression: StepExpression, handler: StepCallback) => void;\n readonly then: (expression: StepExpression, handler: StepCallback) => void;\n readonly and: (expression: StepExpression, handler: StepCallback) => void;\n readonly but: (expression: StepExpression, handler: StepCallback) => void;\n}): StepFlowBuilder {\n const builder: StepFlowBuilder = {\n given: (expression) => createFlowRunner(registrars.given, expression, () => builder),\n when: (expression) => createFlowRunner(registrars.when, expression, () => builder),\n then: (expression) => createFlowRunner(registrars.then, expression, () => builder),\n and: (expression) => createFlowRunner(registrars.and, expression, () => builder),\n but: (expression) => createFlowRunner(registrars.but, expression, () => builder),\n };\n\n return builder;\n}\n\nfunction createFlowRunner(\n registrar: (expression: StepExpression, handler: StepCallback) => void,\n expression: StepExpression,\n next: () => StepFlowBuilder\n) {\n return {\n run(handler: StepCallback) {\n registrar(expression, handler);\n return next();\n },\n };\n}\n\nconst nextScenarioId = createKeyFactory(\"scenario\");\n\nconst defaultKeyResolver: ScopeKeyResolver<StepRuntimeContext> = {\n feature(context) {\n return context.gherkinDocument?.feature?.name ?? context.pickle?.uri ?? undefined;\n },\n rule(context) {\n const nodes = context.pickle?.astNodeIds;\n return Array.isArray(nodes) && nodes.length > 1 ? nodes[0] : undefined;\n },\n outline(context) {\n const nodes = context.pickle?.astNodeIds;\n if (Array.isArray(nodes) && nodes.length > 1) {\n return nodes.slice(1).join(\":\");\n }\n return undefined;\n },\n scenario(context) {\n return context.pickle?.id ?? context.pickle?.name ?? nextScenarioId();\n },\n};\n\nfunction createKeyFactory(prefix: string): () => string {\n let counter = 0;\n return () => `${prefix}-${++counter}`;\n}\n","import { Container, Scope } from \"@autometa/injection\";\nimport { AutomationError } from \"@autometa/errors\";\nimport type {\n HookCallback,\n DefinedWorld,\n OptionalWorld,\n ScopeKeyResolver,\n ScopeKeys,\n ScopePayload,\n StepRuntimeContext,\n WorldCtor,\n WorldHierarchy,\n WorldScope,\n} from \"../types\";\n\ninterface ScopeState<T extends object, C> {\n readonly ctor: WorldCtor<T>;\n readonly container: Container;\n readonly key: string;\n instance: T;\n context: C;\n}\n\ntype EnterHandlers<\n TScenario extends object,\n TFeature extends object | undefined,\n TRule extends object | undefined,\n TOutline extends object | undefined,\n Ctx\n> = {\n [S in WorldScope]: Set<HookCallback<S, TScenario, TFeature, TRule, TOutline, Ctx>>;\n};\n\ntype ExitHandlers<\n TScenario extends object,\n TFeature extends object | undefined,\n TRule extends object | undefined,\n TOutline extends object | undefined,\n Ctx\n> = EnterHandlers<TScenario, TFeature, TRule, TOutline, Ctx>;\n\nexport interface ScopeManagerOptions<\n TScenario extends object,\n TFeature extends object | undefined,\n TRule extends object | undefined,\n TOutline extends object | undefined,\n Ctx = StepRuntimeContext\n> {\n readonly scenario: WorldCtor<TScenario>;\n readonly feature?: WorldCtor<DefinedWorld<TFeature>>;\n readonly rule?: WorldCtor<DefinedWorld<TRule>>;\n readonly outline?: WorldCtor<DefinedWorld<TOutline>>;\n readonly keyResolver: ScopeKeyResolver<Ctx>;\n}\n\nexport class ScopeManager<\n TScenario extends object,\n TFeature extends object | undefined,\n TRule extends object | undefined,\n TOutline extends object | undefined,\n Ctx = StepRuntimeContext\n> {\n private readonly root = new Container();\n\n private feature: ScopeState<DefinedWorld<TFeature>, Ctx> | undefined;\n private rule: ScopeState<DefinedWorld<TRule>, Ctx> | undefined;\n private outline: ScopeState<DefinedWorld<TOutline>, Ctx> | undefined;\n private scenario: ScopeState<TScenario, Ctx> | undefined;\n\n private readonly enterHandlers: EnterHandlers<TScenario, TFeature, TRule, TOutline, Ctx> = {\n feature: new Set(),\n rule: new Set(),\n outline: new Set(),\n scenario: new Set(),\n } as EnterHandlers<TScenario, TFeature, TRule, TOutline, Ctx>;\n\n private readonly exitHandlers: ExitHandlers<TScenario, TFeature, TRule, TOutline, Ctx> = {\n feature: new Set(),\n rule: new Set(),\n outline: new Set(),\n scenario: new Set(),\n } as ExitHandlers<TScenario, TFeature, TRule, TOutline, Ctx>;\n\n constructor(private readonly options: ScopeManagerOptions<TScenario, TFeature, TRule, TOutline, Ctx>) {}\n\n getHierarchy(): WorldHierarchy<TScenario, OptionalWorld<TFeature>, OptionalWorld<TRule>, OptionalWorld<TOutline>> {\n if (!this.scenario) {\n throw new AutomationError(\"Scenario world has not been initialised yet.\");\n }\n\n return {\n scenario: this.scenario.instance,\n feature: (this.feature?.instance ?? undefined) as OptionalWorld<TFeature>,\n rule: (this.rule?.instance ?? undefined) as OptionalWorld<TRule>,\n outline: (this.outline?.instance ?? undefined) as OptionalWorld<TOutline>,\n } satisfies WorldHierarchy<TScenario, OptionalWorld<TFeature>, OptionalWorld<TRule>, OptionalWorld<TOutline>>;\n }\n\n async startScenario(rawContext: Ctx | undefined, explicitKeys?: ScopeKeys): Promise<void> {\n const context = rawContext ?? ({} as Ctx);\n const keys = explicitKeys ?? this.resolveKeys(context);\n\n await this.ensureFeature(keys, context);\n await this.ensureRule(keys, context);\n await this.ensureOutline(keys, context);\n\n if (this.scenario) {\n await this.disposeScenario(false);\n }\n\n this.scenario = this.createScopeState(\n this.options.scenario,\n keys.scenario,\n this.parentContainerFor(\"scenario\"),\n context\n );\n\n this.syncHierarchyReferences();\n await this.triggerEnter(\"scenario\", context);\n }\n\n async finishScenario(context?: Ctx): Promise<void> {\n await this.disposeScenario(true, context);\n }\n\n async resetAll(context?: Ctx): Promise<void> {\n await this.disposeScenario(true, context);\n await this.disposeOutline(context);\n await this.disposeRule(context);\n await this.disposeFeature(context);\n }\n\n onEnter<Scope extends WorldScope>(\n scope: Scope,\n handler: HookCallback<Scope, TScenario, TFeature, TRule, TOutline, Ctx>\n ): void {\n (this.enterHandlers[scope] as Set<HookCallback<Scope, TScenario, TFeature, TRule, TOutline, Ctx>>).add(handler);\n }\n\n onExit<Scope extends WorldScope>(\n scope: Scope,\n handler: HookCallback<Scope, TScenario, TFeature, TRule, TOutline, Ctx>\n ): void {\n (this.exitHandlers[scope] as Set<HookCallback<Scope, TScenario, TFeature, TRule, TOutline, Ctx>>).add(handler);\n }\n\n resolveKeys(context: Ctx): ScopeKeys {\n const { keyResolver } = this.options;\n const result: ScopeKeys = {\n scenario: keyResolver.scenario(context),\n };\n\n const feature = keyResolver.feature?.(context);\n if (feature) {\n result.feature = feature;\n }\n\n const rule = keyResolver.rule?.(context);\n if (rule) {\n result.rule = rule;\n }\n\n const outline = keyResolver.outline?.(context);\n if (outline) {\n result.outline = outline;\n }\n\n if (!result.feature) {\n result.feature = \"feature\";\n }\n\n return result;\n }\n\n hasScenario(): boolean {\n return Boolean(this.scenario);\n }\n\n private parentContainerFor(scope: WorldScope): Container {\n switch (scope) {\n case \"feature\":\n return this.root;\n case \"rule\":\n return this.feature?.container ?? this.root;\n case \"outline\":\n return this.rule?.container ?? this.feature?.container ?? this.root;\n case \"scenario\":\n default:\n return this.outline?.container ?? this.rule?.container ?? this.feature?.container ?? this.root;\n }\n }\n\n private ensureFeature(keys: ScopeKeys, context: Ctx): Promise<void> | void {\n const featureCtor = this.options.feature;\n if (!featureCtor) {\n return;\n }\n\n if (this.feature && this.feature.key === keys.feature) {\n return;\n }\n\n return this.replaceFeature(featureCtor, keys.feature ?? \"feature\", context);\n }\n\n private async ensureRule(keys: ScopeKeys, context: Ctx): Promise<void> {\n const ruleCtor = this.options.rule;\n if (!ruleCtor) {\n return;\n }\n\n if (this.rule && this.rule.key === keys.rule) {\n return;\n }\n\n await this.disposeRule(context);\n\n if (!keys.rule) {\n return;\n }\n\n this.rule = this.createScopeState(\n ruleCtor,\n keys.rule,\n this.parentContainerFor(\"rule\"),\n context\n );\n this.syncHierarchyReferences();\n await this.triggerEnter(\"rule\", context);\n }\n\n private async ensureOutline(keys: ScopeKeys, context: Ctx): Promise<void> {\n const outlineCtor = this.options.outline;\n if (!outlineCtor) {\n return;\n }\n\n if (this.outline && this.outline.key === keys.outline) {\n return;\n }\n\n await this.disposeOutline(context);\n\n if (!keys.outline) {\n return;\n }\n\n this.outline = this.createScopeState(\n outlineCtor,\n keys.outline,\n this.parentContainerFor(\"outline\"),\n context\n );\n this.syncHierarchyReferences();\n await this.triggerEnter(\"outline\", context);\n }\n\n private async replaceFeature(\n ctor: WorldCtor<DefinedWorld<TFeature>>,\n key: string,\n context: Ctx\n ): Promise<void> {\n await this.disposeFeature(context);\n\n this.feature = this.createScopeState(ctor, key, this.parentContainerFor(\"feature\"), context);\n this.syncHierarchyReferences();\n await this.triggerEnter(\"feature\", context);\n }\n\n private createScopeState<T extends object>(\n ctor: WorldCtor<T>,\n key: string,\n parent: Container,\n context: Ctx\n ): ScopeState<T, Ctx> {\n const container = parent.createChild() as Container;\n container.registerClass(ctor, { scope: Scope.SINGLETON });\n const instance = container.resolve(ctor);\n return { ctor, key, container, instance, context } satisfies ScopeState<T, Ctx>;\n }\n\n private async disposeScenario(runHandlers: boolean, context?: Ctx): Promise<void> {\n if (!this.scenario) {\n return;\n }\n\n if (runHandlers) {\n await this.triggerExit(\"scenario\", context ?? this.scenario.context);\n }\n\n await this.scenario.container.dispose();\n this.scenario = undefined;\n }\n\n private async disposeOutline(context?: Ctx): Promise<void> {\n if (!this.outline) {\n return;\n }\n\n await this.triggerExit(\"outline\", context ?? this.outline.context);\n await this.outline.container.dispose();\n this.outline = undefined;\n }\n\n private async disposeRule(context?: Ctx): Promise<void> {\n if (!this.rule) {\n return;\n }\n\n await this.triggerExit(\"rule\", context ?? this.rule.context);\n await this.rule.container.dispose();\n this.rule = undefined;\n }\n\n private async disposeFeature(context?: Ctx): Promise<void> {\n if (!this.feature) {\n return;\n }\n\n await this.triggerExit(\"feature\", context ?? this.feature.context);\n await this.feature.container.dispose();\n this.feature = undefined;\n }\n\n private async triggerEnter(scope: WorldScope, context: Ctx): Promise<void> {\n const handlers = this.enterHandlers[scope];\n if (!handlers.size) {\n return;\n }\n\n const payload = this.createPayload(scope);\n for (const handler of handlers) {\n // eslint-disable-next-line no-await-in-loop\n await handler(payload as never, context);\n }\n }\n\n private async triggerExit(scope: WorldScope, context: Ctx): Promise<void> {\n const handlers = this.exitHandlers[scope];\n if (!handlers.size) {\n return;\n }\n\n const payload = this.createPayload(scope);\n for (const handler of handlers) {\n // eslint-disable-next-line no-await-in-loop\n await handler(payload as never, context);\n }\n }\n\n private createPayload(scope: WorldScope): ScopePayload<\n typeof scope,\n TScenario,\n OptionalWorld<TFeature>,\n OptionalWorld<TRule>,\n OptionalWorld<TOutline>\n > {\n switch (scope) {\n case \"feature\":\n if (!this.feature) {\n throw new AutomationError(\"Feature world has not been initialised.\");\n }\n return { feature: this.feature.instance } as never;\n case \"rule\":\n if (!this.rule) {\n throw new AutomationError(\"Rule world has not been initialised.\");\n }\n return {\n feature: (this.feature?.instance ?? undefined) as OptionalWorld<TFeature>,\n rule: this.rule.instance,\n } as never;\n case \"outline\":\n if (!this.outline) {\n throw new AutomationError(\"Outline world has not been initialised.\");\n }\n return {\n feature: (this.feature?.instance ?? undefined) as OptionalWorld<TFeature>,\n rule: (this.rule?.instance ?? undefined) as OptionalWorld<TRule>,\n outline: this.outline.instance,\n } as never;\n case \"scenario\":\n default:\n if (!this.scenario) {\n throw new AutomationError(\"Scenario world has not been initialised.\");\n }\n return {\n feature: (this.feature?.instance ?? undefined) as OptionalWorld<TFeature>,\n rule: (this.rule?.instance ?? undefined) as OptionalWorld<TRule>,\n outline: (this.outline?.instance ?? undefined) as OptionalWorld<TOutline>,\n scenario: this.scenario.instance,\n } as never;\n }\n }\n\n private syncHierarchyReferences(): void {\n if (this.rule?.instance && this.feature?.instance) {\n this.attachParent(this.rule.instance, \"feature\", this.feature.instance);\n }\n\n if (this.outline?.instance) {\n if (this.feature?.instance) {\n this.attachParent(this.outline.instance, \"feature\", this.feature.instance);\n }\n if (this.rule?.instance) {\n this.attachParent(this.outline.instance, \"rule\", this.rule.instance);\n }\n }\n\n if (this.scenario?.instance) {\n if (this.feature?.instance) {\n this.attachParent(this.scenario.instance, \"feature\", this.feature.instance);\n }\n if (this.rule?.instance) {\n this.attachParent(this.scenario.instance, \"rule\", this.rule.instance);\n }\n if (this.outline?.instance) {\n this.attachParent(this.scenario.instance, \"outline\", this.outline.instance);\n }\n }\n }\n\n private attachParent(target: object, property: string, value: object): void {\n if (property in target && Reflect.get(target, property) === value) {\n return;\n }\n\n Object.defineProperty(target, property, {\n value,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n }\n}\n"]}
|