@autometa/runner 0.6.4 → 1.0.0-rc.1
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 +2 -121
- package/dist/bindings/create-bindings-ts.d.ts +46 -0
- package/dist/bindings/index.d.ts +1 -0
- package/dist/builder/create-runner-builder.d.ts +149 -0
- package/dist/core/parameter-registry.d.ts +16 -0
- package/dist/core/runner-context.d.ts +27 -0
- package/dist/cucumber-runner.d.ts +9 -0
- package/dist/current.d.ts +5 -0
- package/dist/decorators/create-runner-decorators.d.ts +55 -0
- package/dist/dsl/create-decorator-runner.d.ts +19 -0
- package/dist/dsl/create-global-runner.d.ts +9 -0
- package/dist/dsl/create-runner.d.ts +82 -0
- package/dist/dsl/decorator-shared.d.ts +12 -0
- package/dist/global.d.ts +14 -0
- package/dist/index.cjs +2212 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +22 -674
- package/dist/index.js +2064 -456
- package/dist/index.js.map +1 -1
- package/dist/runtime/coordinate-runner-feature.d.ts +20 -0
- package/dist/tokens.d.ts +1 -0
- package/package.json +29 -34
- package/.eslintignore +0 -3
- package/.eslintrc.cjs +0 -4
- package/.turbo/turbo-lint$colon$fix.log +0 -4
- package/.turbo/turbo-prettify.log +0 -0
- package/.turbo/turbo-test.log +0 -12
- package/CHANGELOG.md +0 -1274
- package/dist/esm/index.js +0 -515
- package/dist/esm/index.js.map +0 -1
- package/dist/index.d.cts +0 -674
- package/tsup.config.ts +0 -14
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2212 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var executor = require('@autometa/executor');
|
|
6
|
+
var cucumberExpressions$1 = require('@autometa/cucumber-expressions');
|
|
7
|
+
var scopes = require('@autometa/scopes');
|
|
8
|
+
var cucumberExpressions = require('@cucumber/cucumber-expressions');
|
|
9
|
+
var assertions = require('@autometa/assertions');
|
|
10
|
+
var injection = require('@autometa/injection');
|
|
11
|
+
var coordinator = require('@autometa/coordinator');
|
|
12
|
+
|
|
13
|
+
var __accessCheck = (obj, member, msg) => {
|
|
14
|
+
if (!member.has(obj))
|
|
15
|
+
throw TypeError("Cannot " + msg);
|
|
16
|
+
};
|
|
17
|
+
var __privateGet = (obj, member, getter) => {
|
|
18
|
+
__accessCheck(obj, member, "read from private field");
|
|
19
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
20
|
+
};
|
|
21
|
+
var __privateAdd = (obj, member, value) => {
|
|
22
|
+
if (member.has(obj))
|
|
23
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
24
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
25
|
+
};
|
|
26
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
27
|
+
__accessCheck(obj, member, "write to private field");
|
|
28
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
29
|
+
return value;
|
|
30
|
+
};
|
|
31
|
+
var _registry;
|
|
32
|
+
var ParameterRegistryAdapter = class {
|
|
33
|
+
constructor(options = {}) {
|
|
34
|
+
__privateAdd(this, _registry, void 0);
|
|
35
|
+
__privateSet(this, _registry, options.registry ?? new cucumberExpressions.ParameterTypeRegistry());
|
|
36
|
+
}
|
|
37
|
+
get registry() {
|
|
38
|
+
return __privateGet(this, _registry);
|
|
39
|
+
}
|
|
40
|
+
get parameterTypes() {
|
|
41
|
+
return __privateGet(this, _registry).parameterTypes;
|
|
42
|
+
}
|
|
43
|
+
lookupByTypeName(name) {
|
|
44
|
+
return __privateGet(this, _registry).lookupByTypeName(name);
|
|
45
|
+
}
|
|
46
|
+
lookupByRegexp(parameterTypeRegexp, expressionRegexp, text) {
|
|
47
|
+
return __privateGet(this, _registry).lookupByRegexp(parameterTypeRegexp, expressionRegexp, text);
|
|
48
|
+
}
|
|
49
|
+
defineParameterType(definition) {
|
|
50
|
+
const parameter = definition;
|
|
51
|
+
__privateGet(this, _registry).defineParameterType(parameter);
|
|
52
|
+
return parameter;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
_registry = new WeakMap();
|
|
56
|
+
function createParameterRegistryAdapter(options) {
|
|
57
|
+
return new ParameterRegistryAdapter(options);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/core/runner-context.ts
|
|
61
|
+
var RunnerContext = class _RunnerContext {
|
|
62
|
+
constructor(options = {}) {
|
|
63
|
+
this.registryAdapter = options.parameterRegistry ? createParameterRegistryAdapter({ registry: options.parameterRegistry }) : createParameterRegistryAdapter();
|
|
64
|
+
this.defineParameterTypeFn = cucumberExpressions$1.createParameterTypes(
|
|
65
|
+
options.parameterTypesOptions
|
|
66
|
+
);
|
|
67
|
+
this.registerDefaultParameterTypesFn = cucumberExpressions$1.createDefaultParameterTypes(
|
|
68
|
+
options.parameterTypesOptions
|
|
69
|
+
);
|
|
70
|
+
const scopeOptions = _RunnerContext.extractScopeOptions(options);
|
|
71
|
+
this.scopesInternal = scopes.createScopes({
|
|
72
|
+
...scopeOptions,
|
|
73
|
+
parameterRegistry: this.registryAdapter
|
|
74
|
+
});
|
|
75
|
+
if (options.registerDefaultParameterTypes !== false) {
|
|
76
|
+
this.registerDefaultParameterTypes();
|
|
77
|
+
}
|
|
78
|
+
if (options.parameterTypes && options.parameterTypes.length > 0) {
|
|
79
|
+
this.defineParameterTypes(...options.parameterTypes);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
get scopes() {
|
|
83
|
+
return this.scopesInternal;
|
|
84
|
+
}
|
|
85
|
+
get parameterRegistry() {
|
|
86
|
+
return this.registryAdapter.registry;
|
|
87
|
+
}
|
|
88
|
+
get parameterRegistryAdapter() {
|
|
89
|
+
return this.registryAdapter;
|
|
90
|
+
}
|
|
91
|
+
get plan() {
|
|
92
|
+
return this.scopesInternal.plan();
|
|
93
|
+
}
|
|
94
|
+
defineParameterType(definition) {
|
|
95
|
+
return this.defineParameterTypeFn(this.parameterRegistry, definition);
|
|
96
|
+
}
|
|
97
|
+
defineParameterTypes(...definitions) {
|
|
98
|
+
this.defineParameterTypeFn.many(this.parameterRegistry, ...definitions);
|
|
99
|
+
return this.parameterRegistry;
|
|
100
|
+
}
|
|
101
|
+
registerDefaultParameterTypes() {
|
|
102
|
+
return this.registerDefaultParameterTypesFn(this.parameterRegistry);
|
|
103
|
+
}
|
|
104
|
+
lookupParameterType(name) {
|
|
105
|
+
return this.parameterRegistry.lookupByTypeName(name);
|
|
106
|
+
}
|
|
107
|
+
static extractScopeOptions(options) {
|
|
108
|
+
const {
|
|
109
|
+
parameterRegistry: _parameterRegistry,
|
|
110
|
+
parameterTypes: _parameterTypes,
|
|
111
|
+
parameterTypesOptions: _parameterTypesOptions,
|
|
112
|
+
registerDefaultParameterTypes: _registerDefaultParameterTypes,
|
|
113
|
+
...scopeOptions
|
|
114
|
+
} = options;
|
|
115
|
+
return scopeOptions;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// src/dsl/create-runner.ts
|
|
120
|
+
var hookWrapperCache = /* @__PURE__ */ new WeakMap();
|
|
121
|
+
function wrapHook(hook) {
|
|
122
|
+
if (typeof hook !== "function") {
|
|
123
|
+
throw new TypeError("Hook DSL must be a function");
|
|
124
|
+
}
|
|
125
|
+
const cached = hookWrapperCache.get(hook);
|
|
126
|
+
if (cached) {
|
|
127
|
+
return cached;
|
|
128
|
+
}
|
|
129
|
+
const callable = (first, second, third) => {
|
|
130
|
+
if (typeof first === "string") {
|
|
131
|
+
return hook(first, second, third);
|
|
132
|
+
}
|
|
133
|
+
return hook(first, second);
|
|
134
|
+
};
|
|
135
|
+
hookWrapperCache.set(hook, callable);
|
|
136
|
+
const assignVariant = (variant, source) => {
|
|
137
|
+
if (typeof source === "function") {
|
|
138
|
+
callable[variant] = wrapHook(
|
|
139
|
+
source
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
assignVariant("skip", hook.skip);
|
|
144
|
+
assignVariant("only", hook.only);
|
|
145
|
+
assignVariant("failing", hook.failing);
|
|
146
|
+
assignVariant("concurrent", hook.concurrent);
|
|
147
|
+
return callable;
|
|
148
|
+
}
|
|
149
|
+
function wrapStepHandler(handler) {
|
|
150
|
+
return (world, ...args) => {
|
|
151
|
+
const runtime = executor.createStepRuntime(world);
|
|
152
|
+
const withRuntime = handler;
|
|
153
|
+
const withoutRuntime = handler;
|
|
154
|
+
const paramLength = typeof handler === "function" ? handler.length : 0;
|
|
155
|
+
const expectsRuntime = paramLength > args.length + 1;
|
|
156
|
+
const invocationArgs = expectsRuntime ? [...args, runtime, world] : [...args, world];
|
|
157
|
+
const callable = expectsRuntime ? withRuntime : withoutRuntime;
|
|
158
|
+
return Reflect.apply(callable, world, invocationArgs);
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function enhanceStepDsl(dsl) {
|
|
162
|
+
const cache = /* @__PURE__ */ new Map();
|
|
163
|
+
const convert = (source) => {
|
|
164
|
+
const existing = cache.get(source);
|
|
165
|
+
if (existing) {
|
|
166
|
+
return existing;
|
|
167
|
+
}
|
|
168
|
+
const invoke = (expression, handler, options) => source(
|
|
169
|
+
expression,
|
|
170
|
+
wrapStepHandler(handler),
|
|
171
|
+
options
|
|
172
|
+
);
|
|
173
|
+
cache.set(source, invoke);
|
|
174
|
+
invoke.skip = convert(source.skip);
|
|
175
|
+
invoke.only = convert(source.only);
|
|
176
|
+
invoke.failing = convert(source.failing);
|
|
177
|
+
invoke.concurrent = convert(source.concurrent);
|
|
178
|
+
invoke.tags = (...inputs) => convert(source.tags(...inputs));
|
|
179
|
+
return invoke;
|
|
180
|
+
};
|
|
181
|
+
return convert(dsl);
|
|
182
|
+
}
|
|
183
|
+
function createRunner(options = {}) {
|
|
184
|
+
const context = new RunnerContext(options);
|
|
185
|
+
const scopes = context.scopes;
|
|
186
|
+
const given = enhanceStepDsl(scopes.given);
|
|
187
|
+
const when = enhanceStepDsl(scopes.when);
|
|
188
|
+
const then = enhanceStepDsl(scopes.then);
|
|
189
|
+
const and = enhanceStepDsl(scopes.and);
|
|
190
|
+
const but = enhanceStepDsl(scopes.but);
|
|
191
|
+
const defineParameterTypesFromList = (definitions) => context.defineParameterTypes(...definitions);
|
|
192
|
+
const beforeFeatureHook = wrapHook(scopes.beforeFeature);
|
|
193
|
+
const afterFeatureHook = wrapHook(scopes.afterFeature);
|
|
194
|
+
const beforeRuleHook = wrapHook(scopes.beforeRule);
|
|
195
|
+
const afterRuleHook = wrapHook(scopes.afterRule);
|
|
196
|
+
const beforeScenarioHook = wrapHook(scopes.beforeScenario);
|
|
197
|
+
const afterScenarioHook = wrapHook(scopes.afterScenario);
|
|
198
|
+
const beforeScenarioOutlineHook = wrapHook(scopes.beforeScenarioOutline);
|
|
199
|
+
const afterScenarioOutlineHook = wrapHook(scopes.afterScenarioOutline);
|
|
200
|
+
const beforeStepHook = wrapHook(scopes.beforeStep);
|
|
201
|
+
const afterStepHook = wrapHook(scopes.afterStep);
|
|
202
|
+
const environment = {
|
|
203
|
+
context,
|
|
204
|
+
parameterRegistry: context.parameterRegistry,
|
|
205
|
+
getPlan: () => context.plan,
|
|
206
|
+
defineParameterType: (definition) => context.defineParameterType(definition),
|
|
207
|
+
defineParameterTypes: (...definitions) => context.defineParameterTypes(...definitions),
|
|
208
|
+
defineParameterTypesFromList,
|
|
209
|
+
registerDefaultParameterTypes: () => context.registerDefaultParameterTypes(),
|
|
210
|
+
lookupParameterType: (name) => context.lookupParameterType(name),
|
|
211
|
+
feature: scopes.feature,
|
|
212
|
+
rule: scopes.rule,
|
|
213
|
+
scenario: scopes.scenario,
|
|
214
|
+
scenarioOutline: scopes.scenarioOutline,
|
|
215
|
+
given,
|
|
216
|
+
when,
|
|
217
|
+
then,
|
|
218
|
+
and,
|
|
219
|
+
but,
|
|
220
|
+
beforeFeature: beforeFeatureHook,
|
|
221
|
+
afterFeature: afterFeatureHook,
|
|
222
|
+
beforeRule: beforeRuleHook,
|
|
223
|
+
afterRule: afterRuleHook,
|
|
224
|
+
beforeScenario: beforeScenarioHook,
|
|
225
|
+
afterScenario: afterScenarioHook,
|
|
226
|
+
beforeScenarioOutline: beforeScenarioOutlineHook,
|
|
227
|
+
afterScenarioOutline: afterScenarioOutlineHook,
|
|
228
|
+
beforeStep: beforeStepHook,
|
|
229
|
+
afterStep: afterStepHook,
|
|
230
|
+
Given: given,
|
|
231
|
+
When: when,
|
|
232
|
+
Then: then,
|
|
233
|
+
And: and,
|
|
234
|
+
But: but,
|
|
235
|
+
plan: scopes.plan,
|
|
236
|
+
BeforeFeature: beforeFeatureHook,
|
|
237
|
+
AfterFeature: afterFeatureHook,
|
|
238
|
+
BeforeRule: beforeRuleHook,
|
|
239
|
+
AfterRule: afterRuleHook,
|
|
240
|
+
BeforeScenario: beforeScenarioHook,
|
|
241
|
+
AfterScenario: afterScenarioHook,
|
|
242
|
+
BeforeScenarioOutline: beforeScenarioOutlineHook,
|
|
243
|
+
AfterScenarioOutline: afterScenarioOutlineHook,
|
|
244
|
+
BeforeStep: beforeStepHook,
|
|
245
|
+
AfterStep: afterStepHook
|
|
246
|
+
};
|
|
247
|
+
return environment;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/dsl/create-global-runner.ts
|
|
251
|
+
function createGlobalRunner(initialOptions) {
|
|
252
|
+
let lastOptions = initialOptions;
|
|
253
|
+
function instantiate(options) {
|
|
254
|
+
if (options) {
|
|
255
|
+
lastOptions = options;
|
|
256
|
+
return createRunner(options);
|
|
257
|
+
}
|
|
258
|
+
if (lastOptions) {
|
|
259
|
+
return createRunner(lastOptions);
|
|
260
|
+
}
|
|
261
|
+
return createRunner();
|
|
262
|
+
}
|
|
263
|
+
let current = instantiate(initialOptions);
|
|
264
|
+
const target = {
|
|
265
|
+
reset(options) {
|
|
266
|
+
current = instantiate(options);
|
|
267
|
+
return current;
|
|
268
|
+
},
|
|
269
|
+
useEnvironment(environment) {
|
|
270
|
+
current = environment;
|
|
271
|
+
return current;
|
|
272
|
+
},
|
|
273
|
+
getEnvironment() {
|
|
274
|
+
return current;
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
const forwardedKeys = /* @__PURE__ */ new Set([
|
|
278
|
+
"reset",
|
|
279
|
+
"useEnvironment",
|
|
280
|
+
"getEnvironment"
|
|
281
|
+
]);
|
|
282
|
+
return new Proxy(target, {
|
|
283
|
+
get(obj, prop, receiver) {
|
|
284
|
+
if (forwardedKeys.has(prop)) {
|
|
285
|
+
return Reflect.get(obj, prop, receiver);
|
|
286
|
+
}
|
|
287
|
+
const value = current[prop];
|
|
288
|
+
if (typeof value === "function") {
|
|
289
|
+
return value.bind(current);
|
|
290
|
+
}
|
|
291
|
+
return value;
|
|
292
|
+
},
|
|
293
|
+
has(_, prop) {
|
|
294
|
+
if (forwardedKeys.has(prop)) {
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
return prop in current;
|
|
298
|
+
},
|
|
299
|
+
ownKeys() {
|
|
300
|
+
const forwardable = Array.from(forwardedKeys).filter(
|
|
301
|
+
(key) => typeof key === "string" || typeof key === "symbol"
|
|
302
|
+
);
|
|
303
|
+
const keys = /* @__PURE__ */ new Set([
|
|
304
|
+
...Reflect.ownKeys(current),
|
|
305
|
+
...forwardable
|
|
306
|
+
]);
|
|
307
|
+
return Array.from(keys);
|
|
308
|
+
},
|
|
309
|
+
getOwnPropertyDescriptor(obj, prop) {
|
|
310
|
+
if (forwardedKeys.has(prop)) {
|
|
311
|
+
return {
|
|
312
|
+
configurable: true,
|
|
313
|
+
enumerable: false,
|
|
314
|
+
value: Reflect.get(obj, prop)
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
return Object.getOwnPropertyDescriptor(current, prop);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
function createDecoratorRunner(options = {}) {
|
|
322
|
+
const context = new RunnerContext(options);
|
|
323
|
+
const registry = new scopes.DecoratorScopeRegistry();
|
|
324
|
+
const scopeOptions = RunnerContext.extractScopeOptions(options);
|
|
325
|
+
return {
|
|
326
|
+
feature(token, descriptor) {
|
|
327
|
+
registry.registerFeature(token, descriptor);
|
|
328
|
+
},
|
|
329
|
+
rule(featureToken, token, descriptor) {
|
|
330
|
+
registry.registerRule(featureToken, token, descriptor);
|
|
331
|
+
},
|
|
332
|
+
scenario(token, descriptor, scenarioContext) {
|
|
333
|
+
registry.registerScenario(token, descriptor, scenarioContext);
|
|
334
|
+
},
|
|
335
|
+
step(scenarioToken, keyword, expression, handler, options2) {
|
|
336
|
+
registry.registerStep(scenarioToken, {
|
|
337
|
+
keyword,
|
|
338
|
+
expression,
|
|
339
|
+
handler,
|
|
340
|
+
...options2 ? { options: options2 } : {}
|
|
341
|
+
});
|
|
342
|
+
},
|
|
343
|
+
hook(scopeToken, type, handler, description, options2) {
|
|
344
|
+
registry.registerHook(scopeToken, {
|
|
345
|
+
type,
|
|
346
|
+
handler,
|
|
347
|
+
...description ? { description } : {},
|
|
348
|
+
...options2 ? { options: options2 } : {}
|
|
349
|
+
});
|
|
350
|
+
},
|
|
351
|
+
context,
|
|
352
|
+
buildPlan() {
|
|
353
|
+
return registry.build(
|
|
354
|
+
createScopeOptions(scopeOptions, context.parameterRegistryAdapter)
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
function createScopeOptions(opts, parameterRegistry) {
|
|
360
|
+
return {
|
|
361
|
+
...opts,
|
|
362
|
+
parameterRegistry
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/decorators/create-runner-decorators.ts
|
|
367
|
+
function createRunnerDecorators(environment) {
|
|
368
|
+
const stepMetadata = /* @__PURE__ */ new WeakMap();
|
|
369
|
+
const hookMetadata = /* @__PURE__ */ new WeakMap();
|
|
370
|
+
const scenarioRecords = /* @__PURE__ */ new WeakMap();
|
|
371
|
+
const pendingScenarioData = /* @__PURE__ */ new WeakMap();
|
|
372
|
+
const ruleRecords = /* @__PURE__ */ new WeakMap();
|
|
373
|
+
const pendingRuleData = /* @__PURE__ */ new WeakMap();
|
|
374
|
+
const featureHooks = /* @__PURE__ */ new WeakMap();
|
|
375
|
+
function getOrCreateRecordMap(constructor) {
|
|
376
|
+
let records = scenarioRecords.get(constructor);
|
|
377
|
+
if (!records) {
|
|
378
|
+
records = /* @__PURE__ */ new Map();
|
|
379
|
+
scenarioRecords.set(constructor, records);
|
|
380
|
+
}
|
|
381
|
+
return records;
|
|
382
|
+
}
|
|
383
|
+
function getOrCreatePending(constructor) {
|
|
384
|
+
let pending = pendingScenarioData.get(constructor);
|
|
385
|
+
if (!pending) {
|
|
386
|
+
pending = /* @__PURE__ */ new Map();
|
|
387
|
+
pendingScenarioData.set(constructor, pending);
|
|
388
|
+
}
|
|
389
|
+
return pending;
|
|
390
|
+
}
|
|
391
|
+
function getOrCreateRuleRecordMap(constructor) {
|
|
392
|
+
let records = ruleRecords.get(constructor);
|
|
393
|
+
if (!records) {
|
|
394
|
+
records = /* @__PURE__ */ new Map();
|
|
395
|
+
ruleRecords.set(constructor, records);
|
|
396
|
+
}
|
|
397
|
+
return records;
|
|
398
|
+
}
|
|
399
|
+
function getOrCreateRulePending(constructor) {
|
|
400
|
+
let pending = pendingRuleData.get(constructor);
|
|
401
|
+
if (!pending) {
|
|
402
|
+
pending = /* @__PURE__ */ new Map();
|
|
403
|
+
pendingRuleData.set(constructor, pending);
|
|
404
|
+
}
|
|
405
|
+
return pending;
|
|
406
|
+
}
|
|
407
|
+
function addStepAssociation(constructor, scenarioKey, stepKey) {
|
|
408
|
+
const records = scenarioRecords.get(constructor);
|
|
409
|
+
const record = records?.get(scenarioKey);
|
|
410
|
+
if (record) {
|
|
411
|
+
record.steps.add(stepKey);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
const pending = getOrCreatePending(constructor);
|
|
415
|
+
let entry = pending.get(scenarioKey);
|
|
416
|
+
if (!entry) {
|
|
417
|
+
entry = { steps: /* @__PURE__ */ new Set(), hooks: [] };
|
|
418
|
+
pending.set(scenarioKey, entry);
|
|
419
|
+
}
|
|
420
|
+
entry.steps.add(stepKey);
|
|
421
|
+
}
|
|
422
|
+
function addHookAssociation(constructor, scenarioKey, hook) {
|
|
423
|
+
const records = scenarioRecords.get(constructor);
|
|
424
|
+
const record = records?.get(scenarioKey);
|
|
425
|
+
if (record) {
|
|
426
|
+
record.hooks.push(hook);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const pending = getOrCreatePending(constructor);
|
|
430
|
+
let entry = pending.get(scenarioKey);
|
|
431
|
+
if (!entry) {
|
|
432
|
+
entry = { steps: /* @__PURE__ */ new Set(), hooks: [] };
|
|
433
|
+
pending.set(scenarioKey, entry);
|
|
434
|
+
}
|
|
435
|
+
entry.hooks.push(hook);
|
|
436
|
+
}
|
|
437
|
+
function addRuleScenarioAssociation(constructor, ruleKey, scenarioKey) {
|
|
438
|
+
const records = ruleRecords.get(constructor);
|
|
439
|
+
const record = records?.get(ruleKey);
|
|
440
|
+
if (record) {
|
|
441
|
+
record.scenarios.add(scenarioKey);
|
|
442
|
+
return record.token;
|
|
443
|
+
}
|
|
444
|
+
const pending = getOrCreateRulePending(constructor);
|
|
445
|
+
let entry = pending.get(ruleKey);
|
|
446
|
+
if (!entry) {
|
|
447
|
+
entry = { scenarios: /* @__PURE__ */ new Set(), hooks: [] };
|
|
448
|
+
pending.set(ruleKey, entry);
|
|
449
|
+
}
|
|
450
|
+
entry.scenarios.add(scenarioKey);
|
|
451
|
+
return void 0;
|
|
452
|
+
}
|
|
453
|
+
function addRuleHookAssociation(constructor, ruleKey, hook) {
|
|
454
|
+
const records = ruleRecords.get(constructor);
|
|
455
|
+
const record = records?.get(ruleKey);
|
|
456
|
+
if (record) {
|
|
457
|
+
record.hooks.push(hook);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
const pending = getOrCreateRulePending(constructor);
|
|
461
|
+
let entry = pending.get(ruleKey);
|
|
462
|
+
if (!entry) {
|
|
463
|
+
entry = { scenarios: /* @__PURE__ */ new Set(), hooks: [] };
|
|
464
|
+
pending.set(ruleKey, entry);
|
|
465
|
+
}
|
|
466
|
+
entry.hooks.push(hook);
|
|
467
|
+
}
|
|
468
|
+
function recordFeatureHook(constructor, hook) {
|
|
469
|
+
const hooks = featureHooks.get(constructor);
|
|
470
|
+
if (hooks) {
|
|
471
|
+
hooks.push(hook);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
featureHooks.set(constructor, [hook]);
|
|
475
|
+
}
|
|
476
|
+
function recordStepMetadata(target, propertyKey, metadata) {
|
|
477
|
+
let map = stepMetadata.get(target);
|
|
478
|
+
if (!map) {
|
|
479
|
+
map = /* @__PURE__ */ new Map();
|
|
480
|
+
stepMetadata.set(target, map);
|
|
481
|
+
}
|
|
482
|
+
map.set(propertyKey, metadata);
|
|
483
|
+
}
|
|
484
|
+
function recordHookMetadata(target, propertyKey, metadata) {
|
|
485
|
+
let map = hookMetadata.get(target);
|
|
486
|
+
if (!map) {
|
|
487
|
+
map = /* @__PURE__ */ new Map();
|
|
488
|
+
hookMetadata.set(target, map);
|
|
489
|
+
}
|
|
490
|
+
map.set(propertyKey, metadata);
|
|
491
|
+
}
|
|
492
|
+
function getStepMetadata(target, propertyKey) {
|
|
493
|
+
return stepMetadata.get(target)?.get(propertyKey);
|
|
494
|
+
}
|
|
495
|
+
function getHookMetadata(target, propertyKey) {
|
|
496
|
+
return hookMetadata.get(target)?.get(propertyKey);
|
|
497
|
+
}
|
|
498
|
+
function normalizeSteps(value) {
|
|
499
|
+
return value ? new Set(value) : /* @__PURE__ */ new Set();
|
|
500
|
+
}
|
|
501
|
+
function isReadonlyArray(value) {
|
|
502
|
+
return Array.isArray(value);
|
|
503
|
+
}
|
|
504
|
+
function toArray(input) {
|
|
505
|
+
return isReadonlyArray(input) ? input : [input];
|
|
506
|
+
}
|
|
507
|
+
function buildStepOptions(options) {
|
|
508
|
+
const candidate = {};
|
|
509
|
+
if (options.tags) {
|
|
510
|
+
candidate.tags = [...options.tags];
|
|
511
|
+
}
|
|
512
|
+
if (options.timeout !== void 0) {
|
|
513
|
+
candidate.timeout = options.timeout;
|
|
514
|
+
}
|
|
515
|
+
if (options.mode) {
|
|
516
|
+
candidate.mode = options.mode;
|
|
517
|
+
}
|
|
518
|
+
if (options.data) {
|
|
519
|
+
candidate.data = { ...options.data };
|
|
520
|
+
}
|
|
521
|
+
return Object.keys(candidate).length > 0 ? candidate : void 0;
|
|
522
|
+
}
|
|
523
|
+
function buildHookOptions(options) {
|
|
524
|
+
const candidate = {};
|
|
525
|
+
if (options.tags) {
|
|
526
|
+
candidate.tags = [...options.tags];
|
|
527
|
+
}
|
|
528
|
+
if (options.timeout !== void 0) {
|
|
529
|
+
candidate.timeout = options.timeout;
|
|
530
|
+
}
|
|
531
|
+
if (options.order !== void 0) {
|
|
532
|
+
candidate.order = options.order;
|
|
533
|
+
}
|
|
534
|
+
if (options.mode) {
|
|
535
|
+
candidate.mode = options.mode;
|
|
536
|
+
}
|
|
537
|
+
if (options.data) {
|
|
538
|
+
candidate.data = { ...options.data };
|
|
539
|
+
}
|
|
540
|
+
return Object.keys(candidate).length > 0 ? candidate : void 0;
|
|
541
|
+
}
|
|
542
|
+
function normalizeTagInputs(inputs) {
|
|
543
|
+
if (inputs.length === 0) {
|
|
544
|
+
return [];
|
|
545
|
+
}
|
|
546
|
+
const tags = [];
|
|
547
|
+
for (const input of inputs) {
|
|
548
|
+
if (typeof input === "string") {
|
|
549
|
+
if (input.length > 0) {
|
|
550
|
+
tags.push(input);
|
|
551
|
+
}
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
if (Array.isArray(input)) {
|
|
555
|
+
for (const tag of input) {
|
|
556
|
+
if (typeof tag === "string" && tag.length > 0) {
|
|
557
|
+
tags.push(tag);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return tags.length > 0 ? Array.from(new Set(tags)) : [];
|
|
563
|
+
}
|
|
564
|
+
function mergeStepOptions(base, extras) {
|
|
565
|
+
if (!base && !extras) {
|
|
566
|
+
return void 0;
|
|
567
|
+
}
|
|
568
|
+
const mergedTags = [
|
|
569
|
+
...base?.tags ?? [],
|
|
570
|
+
...extras?.tags ?? []
|
|
571
|
+
];
|
|
572
|
+
const timeout = extras?.timeout ?? base?.timeout;
|
|
573
|
+
const mode = extras?.mode ?? base?.mode;
|
|
574
|
+
const data = {
|
|
575
|
+
...base?.data ?? {},
|
|
576
|
+
...extras?.data ?? {}
|
|
577
|
+
};
|
|
578
|
+
const tagsResult = mergedTags.length > 0 ? Array.from(new Set(mergedTags)) : void 0;
|
|
579
|
+
const hasData = Object.keys(data).length > 0;
|
|
580
|
+
if (!tagsResult && timeout === void 0 && mode === void 0 && !hasData) {
|
|
581
|
+
return void 0;
|
|
582
|
+
}
|
|
583
|
+
return {
|
|
584
|
+
...tagsResult ? { tags: tagsResult } : {},
|
|
585
|
+
...timeout !== void 0 ? { timeout } : {},
|
|
586
|
+
...mode !== void 0 ? { mode } : {},
|
|
587
|
+
...hasData ? { data } : {}
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
function applyExecutionModeToStepOptions(mode, options) {
|
|
591
|
+
if (!options) {
|
|
592
|
+
return mode === "default" ? void 0 : { mode };
|
|
593
|
+
}
|
|
594
|
+
return mode !== "default" ? { ...options, mode } : { ...options };
|
|
595
|
+
}
|
|
596
|
+
function clonePendingOption(pending) {
|
|
597
|
+
if (typeof pending === "boolean" || typeof pending === "string") {
|
|
598
|
+
return pending;
|
|
599
|
+
}
|
|
600
|
+
const reason = pending.reason;
|
|
601
|
+
return reason !== void 0 ? { reason } : {};
|
|
602
|
+
}
|
|
603
|
+
function cloneScopeOptions(options) {
|
|
604
|
+
const {
|
|
605
|
+
tags,
|
|
606
|
+
description,
|
|
607
|
+
timeout,
|
|
608
|
+
mode,
|
|
609
|
+
source,
|
|
610
|
+
data,
|
|
611
|
+
examples,
|
|
612
|
+
pending
|
|
613
|
+
} = options;
|
|
614
|
+
const cloned = {
|
|
615
|
+
...tags ? { tags: [...tags] } : {},
|
|
616
|
+
...description !== void 0 ? { description } : {},
|
|
617
|
+
...timeout !== void 0 ? {
|
|
618
|
+
timeout: typeof timeout === "number" ? timeout : { ...timeout }
|
|
619
|
+
} : {},
|
|
620
|
+
...mode !== void 0 ? { mode } : {},
|
|
621
|
+
...source ? { source: { ...source } } : {},
|
|
622
|
+
...data ? { data: { ...data } } : {},
|
|
623
|
+
...examples ? {
|
|
624
|
+
examples: examples.map((example) => ({
|
|
625
|
+
...example,
|
|
626
|
+
...example.tags ? { tags: [...example.tags] } : {},
|
|
627
|
+
table: example.table.map((row) => [...row])
|
|
628
|
+
}))
|
|
629
|
+
} : {}
|
|
630
|
+
};
|
|
631
|
+
if (pending !== void 0) {
|
|
632
|
+
cloned.pending = clonePendingOption(pending);
|
|
633
|
+
}
|
|
634
|
+
return cloned;
|
|
635
|
+
}
|
|
636
|
+
function Feature(options = {}) {
|
|
637
|
+
return (target) => {
|
|
638
|
+
const constructor = target;
|
|
639
|
+
const descriptor = {
|
|
640
|
+
name: options.name ?? constructor.name ?? "Feature",
|
|
641
|
+
...cloneScopeOptions(options)
|
|
642
|
+
};
|
|
643
|
+
environment.feature(constructor, descriptor);
|
|
644
|
+
const featureHookRefs = featureHooks.get(constructor);
|
|
645
|
+
if (featureHookRefs) {
|
|
646
|
+
for (const hook of featureHookRefs) {
|
|
647
|
+
const metadata = getHookMetadata(constructor.prototype, hook.propertyKey) ?? getHookMetadata(constructor, hook.propertyKey);
|
|
648
|
+
if (!metadata) {
|
|
649
|
+
throw new Error(
|
|
650
|
+
`Hook metadata missing for ${String(hook.propertyKey)} on feature ${descriptor.name}`
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
environment.hook(
|
|
654
|
+
constructor,
|
|
655
|
+
hook.type,
|
|
656
|
+
metadata.handler,
|
|
657
|
+
hook.description,
|
|
658
|
+
hook.options ?? metadata.options
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
featureHooks.delete(constructor);
|
|
662
|
+
}
|
|
663
|
+
const rules = ruleRecords.get(constructor);
|
|
664
|
+
if (rules) {
|
|
665
|
+
for (const [ruleKey, ruleRecord] of rules.entries()) {
|
|
666
|
+
environment.rule(constructor, ruleRecord.token, ruleRecord.descriptor);
|
|
667
|
+
const hooks = ruleRecord.hooks;
|
|
668
|
+
for (const hook of hooks) {
|
|
669
|
+
const metadata = getHookMetadata(constructor.prototype, hook.propertyKey) ?? getHookMetadata(constructor, hook.propertyKey);
|
|
670
|
+
if (!metadata) {
|
|
671
|
+
throw new Error(
|
|
672
|
+
`Hook metadata missing for ${String(hook.propertyKey)} on rule ${String(ruleKey)} of feature ${descriptor.name}`
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
environment.hook(
|
|
676
|
+
ruleRecord.token,
|
|
677
|
+
hook.type,
|
|
678
|
+
metadata.handler,
|
|
679
|
+
hook.description,
|
|
680
|
+
hook.options ?? metadata.options
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
const records = scenarioRecords.get(constructor);
|
|
686
|
+
if (records) {
|
|
687
|
+
for (const [scenarioKey, record] of records.entries()) {
|
|
688
|
+
if (record.ruleKey) {
|
|
689
|
+
const ruleRecord = rules?.get(record.ruleKey);
|
|
690
|
+
if (!ruleRecord) {
|
|
691
|
+
throw new Error(
|
|
692
|
+
`Scenario ${record.descriptor.name} references unknown rule ${String(record.ruleKey)}`
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
record.ruleToken = record.ruleToken ?? ruleRecord.token;
|
|
696
|
+
ruleRecord.scenarios.add(scenarioKey);
|
|
697
|
+
}
|
|
698
|
+
environment.scenario(record.token, record.descriptor, {
|
|
699
|
+
feature: constructor,
|
|
700
|
+
...record.ruleToken ? { rule: record.ruleToken } : {}
|
|
701
|
+
});
|
|
702
|
+
for (const stepKey of record.steps) {
|
|
703
|
+
const metadata = getStepMetadata(constructor.prototype, stepKey) ?? getStepMetadata(constructor, stepKey);
|
|
704
|
+
if (!metadata) {
|
|
705
|
+
throw new Error(
|
|
706
|
+
`Step metadata missing for ${String(stepKey)} on feature ${descriptor.name}`
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
environment.step(
|
|
710
|
+
record.token,
|
|
711
|
+
metadata.keyword,
|
|
712
|
+
metadata.expression,
|
|
713
|
+
metadata.handler,
|
|
714
|
+
metadata.options
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
for (const hook of record.hooks) {
|
|
718
|
+
const metadata = getHookMetadata(constructor.prototype, hook.propertyKey) ?? getHookMetadata(constructor, hook.propertyKey);
|
|
719
|
+
if (!metadata) {
|
|
720
|
+
throw new Error(
|
|
721
|
+
`Hook metadata missing for ${String(hook.propertyKey)} on feature ${descriptor.name}`
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
environment.hook(
|
|
725
|
+
record.token,
|
|
726
|
+
hook.type,
|
|
727
|
+
metadata.handler,
|
|
728
|
+
hook.description,
|
|
729
|
+
hook.options ?? metadata.options
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
scenarioRecords.delete(constructor);
|
|
734
|
+
}
|
|
735
|
+
ruleRecords.delete(constructor);
|
|
736
|
+
pendingRuleData.delete(constructor);
|
|
737
|
+
pendingScenarioData.delete(constructor);
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
function Rule(options) {
|
|
741
|
+
return (target, propertyKey) => {
|
|
742
|
+
const constructor = resolveConstructor(target);
|
|
743
|
+
const descriptor = {
|
|
744
|
+
name: options.name,
|
|
745
|
+
...cloneScopeOptions(options)
|
|
746
|
+
};
|
|
747
|
+
const records = getOrCreateRuleRecordMap(constructor);
|
|
748
|
+
if (records.has(propertyKey)) {
|
|
749
|
+
throw new Error(`Rule ${String(propertyKey)} already registered on feature ${constructor.name}`);
|
|
750
|
+
}
|
|
751
|
+
const token = Symbol(`rule:${String(propertyKey)}`);
|
|
752
|
+
const record = {
|
|
753
|
+
token,
|
|
754
|
+
descriptor,
|
|
755
|
+
hooks: [],
|
|
756
|
+
scenarios: /* @__PURE__ */ new Set()
|
|
757
|
+
};
|
|
758
|
+
const pending = pendingRuleData.get(constructor)?.get(propertyKey);
|
|
759
|
+
if (pending) {
|
|
760
|
+
for (const scenarioKey of pending.scenarios) {
|
|
761
|
+
record.scenarios.add(scenarioKey);
|
|
762
|
+
}
|
|
763
|
+
record.hooks.push(...pending.hooks);
|
|
764
|
+
pendingRuleData.get(constructor)?.delete(propertyKey);
|
|
765
|
+
}
|
|
766
|
+
records.set(propertyKey, record);
|
|
767
|
+
const scenarios = scenarioRecords.get(constructor);
|
|
768
|
+
if (scenarios) {
|
|
769
|
+
for (const scenarioKey of record.scenarios) {
|
|
770
|
+
const scenarioRecord = scenarios.get(scenarioKey);
|
|
771
|
+
if (scenarioRecord) {
|
|
772
|
+
scenarioRecord.ruleToken = token;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
function Scenario(options) {
|
|
779
|
+
return (target, propertyKey) => {
|
|
780
|
+
const constructor = resolveConstructor(target);
|
|
781
|
+
const records = getOrCreateRecordMap(constructor);
|
|
782
|
+
const descriptor = {
|
|
783
|
+
name: options.name,
|
|
784
|
+
kind: options.kind ?? "scenario",
|
|
785
|
+
...cloneScopeOptions(options)
|
|
786
|
+
};
|
|
787
|
+
const token = Symbol(`scenario:${String(propertyKey)}`);
|
|
788
|
+
const steps = normalizeSteps(options.steps);
|
|
789
|
+
const hooks = [];
|
|
790
|
+
const ruleKey = options.rule;
|
|
791
|
+
let ruleToken;
|
|
792
|
+
if (ruleKey !== void 0) {
|
|
793
|
+
ruleToken = addRuleScenarioAssociation(constructor, ruleKey, propertyKey);
|
|
794
|
+
}
|
|
795
|
+
const pending = pendingScenarioData.get(constructor)?.get(propertyKey);
|
|
796
|
+
if (pending) {
|
|
797
|
+
for (const stepKey of pending.steps) {
|
|
798
|
+
steps.add(stepKey);
|
|
799
|
+
}
|
|
800
|
+
hooks.push(...pending.hooks);
|
|
801
|
+
pendingScenarioData.get(constructor)?.delete(propertyKey);
|
|
802
|
+
}
|
|
803
|
+
const record = {
|
|
804
|
+
token,
|
|
805
|
+
descriptor,
|
|
806
|
+
steps,
|
|
807
|
+
hooks,
|
|
808
|
+
...ruleKey !== void 0 ? { ruleKey } : {},
|
|
809
|
+
...ruleToken ? { ruleToken } : {}
|
|
810
|
+
};
|
|
811
|
+
records.set(propertyKey, record);
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
function createStepDecorator(keyword) {
|
|
815
|
+
const factoryCache = /* @__PURE__ */ new Map();
|
|
816
|
+
const getCachedFactory = (mode, inheritedOptions) => {
|
|
817
|
+
const cacheForOptions = factoryCache.get(inheritedOptions);
|
|
818
|
+
return cacheForOptions?.get(mode);
|
|
819
|
+
};
|
|
820
|
+
const storeFactory = (mode, inheritedOptions, factory) => {
|
|
821
|
+
let cacheForOptions = factoryCache.get(inheritedOptions);
|
|
822
|
+
if (!cacheForOptions) {
|
|
823
|
+
cacheForOptions = /* @__PURE__ */ new Map();
|
|
824
|
+
factoryCache.set(inheritedOptions, cacheForOptions);
|
|
825
|
+
}
|
|
826
|
+
cacheForOptions.set(mode, factory);
|
|
827
|
+
};
|
|
828
|
+
const buildFactory = (mode, inheritedOptions) => {
|
|
829
|
+
const cached = getCachedFactory(mode, inheritedOptions);
|
|
830
|
+
if (cached) {
|
|
831
|
+
return cached;
|
|
832
|
+
}
|
|
833
|
+
const decorator = (expression, options) => {
|
|
834
|
+
if (!options || !options.scenario) {
|
|
835
|
+
throw new Error("Step decorator requires a scenario property key");
|
|
836
|
+
}
|
|
837
|
+
const scenarioRefs = toArray(options.scenario);
|
|
838
|
+
const explicitOptions = buildStepOptions(options);
|
|
839
|
+
const baseWithMode = mergeStepOptions(
|
|
840
|
+
inheritedOptions,
|
|
841
|
+
applyExecutionModeToStepOptions(mode)
|
|
842
|
+
);
|
|
843
|
+
const mergedOptions = mergeStepOptions(baseWithMode, explicitOptions);
|
|
844
|
+
const finalOptions = applyExecutionModeToStepOptions(mode, mergedOptions);
|
|
845
|
+
return (target, propertyKey, descriptor) => {
|
|
846
|
+
const handler = descriptor?.value;
|
|
847
|
+
if (typeof handler !== "function") {
|
|
848
|
+
throw new Error(
|
|
849
|
+
`Step decorator can only be applied to methods. ${String(propertyKey)} is not a function.`
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
recordStepMetadata(target, propertyKey, {
|
|
853
|
+
keyword,
|
|
854
|
+
expression,
|
|
855
|
+
handler,
|
|
856
|
+
...finalOptions ? { options: finalOptions } : {}
|
|
857
|
+
});
|
|
858
|
+
const constructor = resolveConstructor(target);
|
|
859
|
+
for (const scenarioKey of scenarioRefs) {
|
|
860
|
+
addStepAssociation(constructor, scenarioKey, propertyKey);
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
};
|
|
864
|
+
storeFactory(mode, inheritedOptions, decorator);
|
|
865
|
+
decorator.tags = (...inputs) => {
|
|
866
|
+
const normalizedTags = normalizeTagInputs(inputs);
|
|
867
|
+
if (normalizedTags.length === 0) {
|
|
868
|
+
return decorator;
|
|
869
|
+
}
|
|
870
|
+
const tagOptions = {
|
|
871
|
+
tags: normalizedTags
|
|
872
|
+
};
|
|
873
|
+
const merged = mergeStepOptions(inheritedOptions, tagOptions);
|
|
874
|
+
return buildFactory(mode, merged);
|
|
875
|
+
};
|
|
876
|
+
decorator.skip = mode === "skip" ? decorator : buildFactory("skip", inheritedOptions);
|
|
877
|
+
decorator.only = mode === "only" ? decorator : buildFactory("only", inheritedOptions);
|
|
878
|
+
decorator.failing = mode === "failing" ? decorator : buildFactory("failing", inheritedOptions);
|
|
879
|
+
decorator.concurrent = mode === "concurrent" ? decorator : buildFactory("concurrent", inheritedOptions);
|
|
880
|
+
return decorator;
|
|
881
|
+
};
|
|
882
|
+
return buildFactory("default");
|
|
883
|
+
}
|
|
884
|
+
function createScenarioHookDecorator(type) {
|
|
885
|
+
return (options) => {
|
|
886
|
+
if (!options || !options.scenario) {
|
|
887
|
+
throw new Error("Hook decorator requires a scenario property key");
|
|
888
|
+
}
|
|
889
|
+
const scenarioRefs = toArray(options.scenario);
|
|
890
|
+
const hookOptions = buildHookOptions(options);
|
|
891
|
+
const description = options.description;
|
|
892
|
+
return (target, propertyKey, descriptor) => {
|
|
893
|
+
const handler = descriptor?.value;
|
|
894
|
+
if (typeof handler !== "function") {
|
|
895
|
+
throw new Error(
|
|
896
|
+
`Hook decorator can only be applied to methods. ${String(propertyKey)} is not a function.`
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
recordHookMetadata(target, propertyKey, {
|
|
900
|
+
handler,
|
|
901
|
+
...hookOptions ? { options: hookOptions } : {}
|
|
902
|
+
});
|
|
903
|
+
const constructor = resolveConstructor(target);
|
|
904
|
+
const hookRef = {
|
|
905
|
+
propertyKey,
|
|
906
|
+
type,
|
|
907
|
+
...description ? { description } : {},
|
|
908
|
+
...hookOptions ? { options: hookOptions } : {}
|
|
909
|
+
};
|
|
910
|
+
for (const scenarioKey of scenarioRefs) {
|
|
911
|
+
addHookAssociation(constructor, scenarioKey, hookRef);
|
|
912
|
+
}
|
|
913
|
+
};
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
function createRuleHookDecorator(type) {
|
|
917
|
+
return (options) => {
|
|
918
|
+
if (!options || !options.rule) {
|
|
919
|
+
throw new Error("Rule hook decorator requires a rule property key");
|
|
920
|
+
}
|
|
921
|
+
const ruleRefs = toArray(options.rule);
|
|
922
|
+
const hookOptions = buildHookOptions(options);
|
|
923
|
+
const description = options.description;
|
|
924
|
+
return (target, propertyKey, descriptor) => {
|
|
925
|
+
const handler = descriptor?.value;
|
|
926
|
+
if (typeof handler !== "function") {
|
|
927
|
+
throw new Error(
|
|
928
|
+
`Hook decorator can only be applied to methods. ${String(propertyKey)} is not a function.`
|
|
929
|
+
);
|
|
930
|
+
}
|
|
931
|
+
recordHookMetadata(target, propertyKey, {
|
|
932
|
+
handler,
|
|
933
|
+
...hookOptions ? { options: hookOptions } : {}
|
|
934
|
+
});
|
|
935
|
+
const constructor = resolveConstructor(target);
|
|
936
|
+
const hookRef = {
|
|
937
|
+
propertyKey,
|
|
938
|
+
type,
|
|
939
|
+
...description ? { description } : {},
|
|
940
|
+
...hookOptions ? { options: hookOptions } : {}
|
|
941
|
+
};
|
|
942
|
+
for (const ruleKey of ruleRefs) {
|
|
943
|
+
addRuleHookAssociation(constructor, ruleKey, hookRef);
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
function createFeatureHookDecorator(type) {
|
|
949
|
+
return (options = {}) => {
|
|
950
|
+
const hookOptions = buildHookOptions(options);
|
|
951
|
+
const description = options.description;
|
|
952
|
+
return (target, propertyKey, descriptor) => {
|
|
953
|
+
const handler = descriptor?.value;
|
|
954
|
+
if (typeof handler !== "function") {
|
|
955
|
+
throw new Error(
|
|
956
|
+
`Hook decorator can only be applied to methods. ${String(propertyKey)} is not a function.`
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
recordHookMetadata(target, propertyKey, {
|
|
960
|
+
handler,
|
|
961
|
+
...hookOptions ? { options: hookOptions } : {}
|
|
962
|
+
});
|
|
963
|
+
const constructor = resolveConstructor(target);
|
|
964
|
+
const hookRef = {
|
|
965
|
+
propertyKey,
|
|
966
|
+
type,
|
|
967
|
+
...description ? { description } : {},
|
|
968
|
+
...hookOptions ? { options: hookOptions } : {}
|
|
969
|
+
};
|
|
970
|
+
recordFeatureHook(constructor, hookRef);
|
|
971
|
+
};
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
function resolveConstructor(target) {
|
|
975
|
+
const ctor = target.constructor;
|
|
976
|
+
if (typeof ctor !== "function") {
|
|
977
|
+
throw new Error("Decorated target does not expose a constructor");
|
|
978
|
+
}
|
|
979
|
+
return ctor;
|
|
980
|
+
}
|
|
981
|
+
return {
|
|
982
|
+
Feature,
|
|
983
|
+
Rule,
|
|
984
|
+
Scenario,
|
|
985
|
+
Given: createStepDecorator("Given"),
|
|
986
|
+
When: createStepDecorator("When"),
|
|
987
|
+
Then: createStepDecorator("Then"),
|
|
988
|
+
And: createStepDecorator("And"),
|
|
989
|
+
But: createStepDecorator("But"),
|
|
990
|
+
BeforeFeature: createFeatureHookDecorator("beforeFeature"),
|
|
991
|
+
AfterFeature: createFeatureHookDecorator("afterFeature"),
|
|
992
|
+
BeforeRule: createRuleHookDecorator("beforeRule"),
|
|
993
|
+
AfterRule: createRuleHookDecorator("afterRule"),
|
|
994
|
+
BeforeScenario: createScenarioHookDecorator("beforeScenario"),
|
|
995
|
+
AfterScenario: createScenarioHookDecorator("afterScenario"),
|
|
996
|
+
BeforeScenarioOutline: createScenarioHookDecorator("beforeScenarioOutline"),
|
|
997
|
+
AfterScenarioOutline: createScenarioHookDecorator("afterScenarioOutline")
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
var WORLD_TOKEN = injection.createToken(
|
|
1001
|
+
"@autometa/runner/world"
|
|
1002
|
+
);
|
|
1003
|
+
|
|
1004
|
+
// src/bindings/create-bindings-ts.ts
|
|
1005
|
+
var BINDING_METADATA_KEY = Symbol("autometa:binding");
|
|
1006
|
+
var INJECT_PARAM_KEY = "autometa:inject_param";
|
|
1007
|
+
function createBindingsTS(stepsEnvironment) {
|
|
1008
|
+
if (typeof Reflect === "undefined" || typeof Reflect.getMetadata !== "function") {
|
|
1009
|
+
throw new Error(
|
|
1010
|
+
"bindingsTS() requires reflect-metadata. Add `import 'reflect-metadata'` at the top of your step-definitions file."
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
const globalContainer = injection.createContainer();
|
|
1014
|
+
const { Inject, LazyInject } = injection.createDecorators(globalContainer);
|
|
1015
|
+
const { Given: GivenFn, When: WhenFn, Then: ThenFn, And: AndFn, But: BothFn } = stepsEnvironment;
|
|
1016
|
+
const instanceCache = /* @__PURE__ */ new WeakMap();
|
|
1017
|
+
const containerCache = /* @__PURE__ */ new WeakMap();
|
|
1018
|
+
function getScenarioContainer(world) {
|
|
1019
|
+
const worldObj = world;
|
|
1020
|
+
let container = containerCache.get(worldObj);
|
|
1021
|
+
if (!container) {
|
|
1022
|
+
container = globalContainer.createChild();
|
|
1023
|
+
container.registerValue(WORLD_TOKEN, world);
|
|
1024
|
+
containerCache.set(worldObj, container);
|
|
1025
|
+
}
|
|
1026
|
+
return container;
|
|
1027
|
+
}
|
|
1028
|
+
function getStepInstance(BindingClass, world) {
|
|
1029
|
+
const worldObj = world;
|
|
1030
|
+
let cache = instanceCache.get(worldObj);
|
|
1031
|
+
if (!cache) {
|
|
1032
|
+
cache = /* @__PURE__ */ new Map();
|
|
1033
|
+
instanceCache.set(worldObj, cache);
|
|
1034
|
+
}
|
|
1035
|
+
let instance = cache.get(BindingClass);
|
|
1036
|
+
if (instance) {
|
|
1037
|
+
return instance;
|
|
1038
|
+
}
|
|
1039
|
+
const container = getScenarioContainer(world);
|
|
1040
|
+
instance = container.resolve(BindingClass);
|
|
1041
|
+
cache.set(BindingClass, instance);
|
|
1042
|
+
return instance;
|
|
1043
|
+
}
|
|
1044
|
+
function getBindingMetadata(target) {
|
|
1045
|
+
let metadata = Reflect.getMetadata(BINDING_METADATA_KEY, target);
|
|
1046
|
+
if (!metadata) {
|
|
1047
|
+
metadata = { steps: [] };
|
|
1048
|
+
Reflect.defineMetadata(BINDING_METADATA_KEY, metadata, target);
|
|
1049
|
+
}
|
|
1050
|
+
return metadata;
|
|
1051
|
+
}
|
|
1052
|
+
function getBindingSteps(target) {
|
|
1053
|
+
const proto = target.prototype;
|
|
1054
|
+
return Reflect.getMetadata(BINDING_METADATA_KEY, target) ?? (proto ? Reflect.getMetadata(BINDING_METADATA_KEY, proto) : void 0);
|
|
1055
|
+
}
|
|
1056
|
+
function registerBindingClass(BindingClass) {
|
|
1057
|
+
const metadata = getBindingSteps(BindingClass);
|
|
1058
|
+
if (!metadata) {
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
for (const step of metadata.steps) {
|
|
1062
|
+
const handler = (...args) => {
|
|
1063
|
+
const world = args[args.length - 1];
|
|
1064
|
+
const stepArgs = args.slice(0, -1);
|
|
1065
|
+
const instance = getStepInstance(BindingClass, world);
|
|
1066
|
+
const method = instance[step.propertyKey];
|
|
1067
|
+
if (typeof method !== "function") {
|
|
1068
|
+
throw new Error(`Step method ${String(step.propertyKey)} is not a function`);
|
|
1069
|
+
}
|
|
1070
|
+
return method.apply(instance, stepArgs);
|
|
1071
|
+
};
|
|
1072
|
+
switch (step.keyword) {
|
|
1073
|
+
case "Given":
|
|
1074
|
+
GivenFn(step.expression, handler);
|
|
1075
|
+
break;
|
|
1076
|
+
case "When":
|
|
1077
|
+
WhenFn(step.expression, handler);
|
|
1078
|
+
break;
|
|
1079
|
+
case "Then":
|
|
1080
|
+
ThenFn(step.expression, handler);
|
|
1081
|
+
break;
|
|
1082
|
+
case "And":
|
|
1083
|
+
AndFn(step.expression, handler);
|
|
1084
|
+
break;
|
|
1085
|
+
case "But":
|
|
1086
|
+
BothFn(step.expression, handler);
|
|
1087
|
+
break;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
function Binding() {
|
|
1092
|
+
return (target) => {
|
|
1093
|
+
const existing = Reflect.getMetadata(BINDING_METADATA_KEY, target.prototype);
|
|
1094
|
+
if (existing) {
|
|
1095
|
+
Reflect.defineMetadata(BINDING_METADATA_KEY, existing, target);
|
|
1096
|
+
}
|
|
1097
|
+
const paramTokens = Reflect.getMetadata(INJECT_PARAM_KEY, target);
|
|
1098
|
+
const deps = [];
|
|
1099
|
+
if (paramTokens) {
|
|
1100
|
+
const maxIndex = Math.max(...paramTokens.keys());
|
|
1101
|
+
for (let i = 0; i <= maxIndex; i++) {
|
|
1102
|
+
const token = paramTokens.get(i);
|
|
1103
|
+
if (token) {
|
|
1104
|
+
deps[i] = token;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
globalContainer.registerClass(target, {
|
|
1109
|
+
scope: injection.Scope.TRANSIENT,
|
|
1110
|
+
deps
|
|
1111
|
+
});
|
|
1112
|
+
registerBindingClass(target);
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
function createStepDecorator(keyword) {
|
|
1116
|
+
return (expression) => {
|
|
1117
|
+
return (target, propertyKey, _descriptor) => {
|
|
1118
|
+
const metadata = getBindingMetadata(target);
|
|
1119
|
+
metadata.steps.push({
|
|
1120
|
+
propertyKey,
|
|
1121
|
+
keyword,
|
|
1122
|
+
expression
|
|
1123
|
+
});
|
|
1124
|
+
};
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
function Injectable(options) {
|
|
1128
|
+
return (target) => {
|
|
1129
|
+
globalContainer.registerClass(target, {
|
|
1130
|
+
scope: options?.scope ?? injection.Scope.TRANSIENT
|
|
1131
|
+
});
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
return {
|
|
1135
|
+
Binding,
|
|
1136
|
+
Given: createStepDecorator("Given"),
|
|
1137
|
+
When: createStepDecorator("When"),
|
|
1138
|
+
Then: createStepDecorator("Then"),
|
|
1139
|
+
And: createStepDecorator("And"),
|
|
1140
|
+
But: createStepDecorator("But"),
|
|
1141
|
+
Injectable,
|
|
1142
|
+
Inject,
|
|
1143
|
+
LazyInject,
|
|
1144
|
+
container: globalContainer
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
function coordinateRunnerFeature(options) {
|
|
1148
|
+
const {
|
|
1149
|
+
environment,
|
|
1150
|
+
feature,
|
|
1151
|
+
config,
|
|
1152
|
+
runtime,
|
|
1153
|
+
plan,
|
|
1154
|
+
adapterFactory,
|
|
1155
|
+
planBuilder,
|
|
1156
|
+
registerPlan,
|
|
1157
|
+
featureScope,
|
|
1158
|
+
hookLogger
|
|
1159
|
+
} = options;
|
|
1160
|
+
const scopePlan = plan ?? environment.getPlan();
|
|
1161
|
+
return coordinator.coordinateFeature({
|
|
1162
|
+
feature,
|
|
1163
|
+
scopePlan,
|
|
1164
|
+
config,
|
|
1165
|
+
...runtime ? { runtime } : {},
|
|
1166
|
+
...adapterFactory ? { adapterFactory } : {},
|
|
1167
|
+
...planBuilder ? { planBuilder } : {},
|
|
1168
|
+
...registerPlan ? { registerPlan } : {},
|
|
1169
|
+
...featureScope ? { featureScope } : {},
|
|
1170
|
+
...hookLogger ? { hookLogger } : {}
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// src/builder/create-runner-builder.ts
|
|
1175
|
+
function normalizeWorldFactory(factory) {
|
|
1176
|
+
const callable = factory;
|
|
1177
|
+
if (callable.length >= 1) {
|
|
1178
|
+
return factory;
|
|
1179
|
+
}
|
|
1180
|
+
return async (_context) => await callable();
|
|
1181
|
+
}
|
|
1182
|
+
var WORLD_INHERIT_KEYS = Symbol("autometa.runner.world.inherit");
|
|
1183
|
+
var STEPS_ENVIRONMENT_META = Symbol.for(
|
|
1184
|
+
"autometa.runner.steps.environment.meta"
|
|
1185
|
+
);
|
|
1186
|
+
var App = {
|
|
1187
|
+
compositionRoot(ctor, options) {
|
|
1188
|
+
return async (context) => {
|
|
1189
|
+
const { setup, ...registration } = options ?? {};
|
|
1190
|
+
if (setup) {
|
|
1191
|
+
await setup(context);
|
|
1192
|
+
}
|
|
1193
|
+
const registered = context.getRegisteredApp?.();
|
|
1194
|
+
if (registered !== void 0) {
|
|
1195
|
+
return registered;
|
|
1196
|
+
}
|
|
1197
|
+
const container = context.container;
|
|
1198
|
+
if (typeof container.isRegistered === "function" && container.isRegistered(ctor)) {
|
|
1199
|
+
return context.resolve(ctor);
|
|
1200
|
+
}
|
|
1201
|
+
return context.registerApp(
|
|
1202
|
+
ctor,
|
|
1203
|
+
registration
|
|
1204
|
+
);
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
};
|
|
1208
|
+
function createRunnerBuilder(initial) {
|
|
1209
|
+
const state = initializeState(initial);
|
|
1210
|
+
return new RunnerBuilderImpl(state);
|
|
1211
|
+
}
|
|
1212
|
+
var RunnerBuilderImpl = class _RunnerBuilderImpl {
|
|
1213
|
+
constructor(state) {
|
|
1214
|
+
this.state = state;
|
|
1215
|
+
}
|
|
1216
|
+
fork() {
|
|
1217
|
+
const next = cloneBuilderState(this.state);
|
|
1218
|
+
return new _RunnerBuilderImpl(next);
|
|
1219
|
+
}
|
|
1220
|
+
derivable() {
|
|
1221
|
+
if (!this.state.derivedBuilders) {
|
|
1222
|
+
this.state.derivedBuilders = /* @__PURE__ */ new Map();
|
|
1223
|
+
}
|
|
1224
|
+
return this;
|
|
1225
|
+
}
|
|
1226
|
+
group(key) {
|
|
1227
|
+
const trimmed = key.trim();
|
|
1228
|
+
if (!trimmed) {
|
|
1229
|
+
throw new Error("group key must be a non-empty string");
|
|
1230
|
+
}
|
|
1231
|
+
if (!this.state.derivedBuilders) {
|
|
1232
|
+
this.state.derivedBuilders = /* @__PURE__ */ new Map();
|
|
1233
|
+
}
|
|
1234
|
+
const existing = this.state.derivedBuilders.get(trimmed);
|
|
1235
|
+
if (existing) {
|
|
1236
|
+
return new _RunnerBuilderImpl(existing);
|
|
1237
|
+
}
|
|
1238
|
+
const derived = cloneBuilderState(this.state);
|
|
1239
|
+
derived.stepsEnvironmentMeta = { kind: "group", group: trimmed };
|
|
1240
|
+
this.state.derivedBuilders.set(trimmed, derived);
|
|
1241
|
+
return new _RunnerBuilderImpl(derived);
|
|
1242
|
+
}
|
|
1243
|
+
extendWorld(value) {
|
|
1244
|
+
const baseFactory = this.state.worldFactory;
|
|
1245
|
+
const extensionFactory = typeof value === "function" ? normalizeWorldFactory(
|
|
1246
|
+
value
|
|
1247
|
+
) : value ? createDefaultsWorldFactory(ensureWorldDefaults(value)) : async () => ({});
|
|
1248
|
+
const baseInheritance = getWorldInheritance(baseFactory);
|
|
1249
|
+
const extensionInheritance = getWorldInheritance(extensionFactory);
|
|
1250
|
+
const inheritance = baseInheritance || extensionInheritance ? /* @__PURE__ */ new Set([
|
|
1251
|
+
...baseInheritance ? Array.from(baseInheritance) : [],
|
|
1252
|
+
...extensionInheritance ? Array.from(extensionInheritance) : []
|
|
1253
|
+
]) : void 0;
|
|
1254
|
+
const merged = async (context) => {
|
|
1255
|
+
const base = baseFactory ? await baseFactory(context) : {};
|
|
1256
|
+
const extension = await extensionFactory(
|
|
1257
|
+
context
|
|
1258
|
+
);
|
|
1259
|
+
const baseObj = ensureWorldObject(base);
|
|
1260
|
+
const extObj = ensureWorldObject(extension);
|
|
1261
|
+
return { ...baseObj, ...extObj };
|
|
1262
|
+
};
|
|
1263
|
+
if (inheritance && inheritance.size > 0) {
|
|
1264
|
+
Object.defineProperty(merged, WORLD_INHERIT_KEYS, {
|
|
1265
|
+
value: inheritance,
|
|
1266
|
+
writable: false,
|
|
1267
|
+
enumerable: false,
|
|
1268
|
+
configurable: false
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
this.state.worldFactory = merged;
|
|
1272
|
+
delete this.state.ensureFactory;
|
|
1273
|
+
invalidateCaches(this.state);
|
|
1274
|
+
return new _RunnerBuilderImpl(this.state);
|
|
1275
|
+
}
|
|
1276
|
+
extendApp(app) {
|
|
1277
|
+
const next = normalizeAppFactory(app);
|
|
1278
|
+
const previous = this.state.appFactory;
|
|
1279
|
+
const chained = async (context) => {
|
|
1280
|
+
let currentApp;
|
|
1281
|
+
const readRegisteredApp = () => {
|
|
1282
|
+
const anyContext = context;
|
|
1283
|
+
return typeof anyContext.getRegisteredApp === "function" ? anyContext.getRegisteredApp() : void 0;
|
|
1284
|
+
};
|
|
1285
|
+
const updateWorldApp = (value) => {
|
|
1286
|
+
if (!value) {
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
const world = context.world;
|
|
1290
|
+
if (world && typeof world === "object") {
|
|
1291
|
+
world.app = value;
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
if (previous) {
|
|
1295
|
+
const result = await previous(context);
|
|
1296
|
+
currentApp = result ?? readRegisteredApp();
|
|
1297
|
+
updateWorldApp(currentApp);
|
|
1298
|
+
}
|
|
1299
|
+
const nextResult = await next(context);
|
|
1300
|
+
const nextApp = nextResult ?? readRegisteredApp();
|
|
1301
|
+
if (nextApp !== void 0) {
|
|
1302
|
+
currentApp = nextApp;
|
|
1303
|
+
updateWorldApp(currentApp);
|
|
1304
|
+
}
|
|
1305
|
+
return currentApp;
|
|
1306
|
+
};
|
|
1307
|
+
this.state.appFactory = chained;
|
|
1308
|
+
delete this.state.ensureFactory;
|
|
1309
|
+
invalidateCaches(this.state);
|
|
1310
|
+
return new _RunnerBuilderImpl(this.state);
|
|
1311
|
+
}
|
|
1312
|
+
configure(update) {
|
|
1313
|
+
if (typeof update === "function") {
|
|
1314
|
+
const current = collectCurrentOptions(this.state);
|
|
1315
|
+
const merged = update(current);
|
|
1316
|
+
applyOptions(this.state, merged);
|
|
1317
|
+
return new _RunnerBuilderImpl(
|
|
1318
|
+
this.state
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
applyOptions(this.state, update);
|
|
1322
|
+
return new _RunnerBuilderImpl(
|
|
1323
|
+
this.state
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1326
|
+
expressionMap() {
|
|
1327
|
+
return new _RunnerBuilderImpl(
|
|
1328
|
+
this.state
|
|
1329
|
+
);
|
|
1330
|
+
}
|
|
1331
|
+
withWorld(value) {
|
|
1332
|
+
if (typeof value === "function") {
|
|
1333
|
+
this.state.worldFactory = normalizeWorldFactory(
|
|
1334
|
+
value
|
|
1335
|
+
);
|
|
1336
|
+
} else if (value) {
|
|
1337
|
+
const validated = ensureWorldDefaults(value);
|
|
1338
|
+
this.state.worldFactory = createDefaultsWorldFactory(validated);
|
|
1339
|
+
} else {
|
|
1340
|
+
this.state.worldFactory = async (_context) => ({});
|
|
1341
|
+
}
|
|
1342
|
+
delete this.state.ensureFactory;
|
|
1343
|
+
invalidateCaches(this.state);
|
|
1344
|
+
return new _RunnerBuilderImpl(this.state);
|
|
1345
|
+
}
|
|
1346
|
+
app(app) {
|
|
1347
|
+
this.state.appFactory = normalizeAppFactory(app);
|
|
1348
|
+
delete this.state.ensureFactory;
|
|
1349
|
+
invalidateCaches(this.state);
|
|
1350
|
+
return new _RunnerBuilderImpl(this.state);
|
|
1351
|
+
}
|
|
1352
|
+
assertions(setup) {
|
|
1353
|
+
this.state.ensureFactory = setup(assertions.ensure);
|
|
1354
|
+
invalidateCaches(this.state);
|
|
1355
|
+
return new _RunnerBuilderImpl(
|
|
1356
|
+
this.state
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
assertionPlugins(plugins) {
|
|
1360
|
+
return this.assertions(
|
|
1361
|
+
(ensureInvoke) => {
|
|
1362
|
+
const factory = assertions.createEnsureFactory(
|
|
1363
|
+
ensureInvoke,
|
|
1364
|
+
plugins
|
|
1365
|
+
);
|
|
1366
|
+
return createImplicitEnsureProxy(factory);
|
|
1367
|
+
}
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1370
|
+
parameterTypes(definitions) {
|
|
1371
|
+
const current = this.state.options.parameterTypes ?? [];
|
|
1372
|
+
this.state.options.parameterTypes = [
|
|
1373
|
+
...current,
|
|
1374
|
+
...definitions
|
|
1375
|
+
];
|
|
1376
|
+
invalidateCaches(this.state);
|
|
1377
|
+
return new _RunnerBuilderImpl(this.state);
|
|
1378
|
+
}
|
|
1379
|
+
steps() {
|
|
1380
|
+
return ensureSteps(this.state);
|
|
1381
|
+
}
|
|
1382
|
+
decorators() {
|
|
1383
|
+
return ensureDecorators(this.state);
|
|
1384
|
+
}
|
|
1385
|
+
bindingsTS() {
|
|
1386
|
+
return ensureBindingsTS(this.state);
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
function initializeState(initial) {
|
|
1390
|
+
if (!initial) {
|
|
1391
|
+
return {
|
|
1392
|
+
options: {},
|
|
1393
|
+
stepsEnvironmentMeta: { kind: "root" }
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
const { worldFactory, ...rest } = initial;
|
|
1397
|
+
const state = {
|
|
1398
|
+
options: { ...rest },
|
|
1399
|
+
stepsEnvironmentMeta: { kind: "root" }
|
|
1400
|
+
};
|
|
1401
|
+
if (worldFactory) {
|
|
1402
|
+
state.worldFactory = normalizeWorldFactory(
|
|
1403
|
+
worldFactory
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
return state;
|
|
1407
|
+
}
|
|
1408
|
+
function cloneBuilderState(source) {
|
|
1409
|
+
const next = {
|
|
1410
|
+
options: cloneWithFallback(source.options)
|
|
1411
|
+
};
|
|
1412
|
+
if (source.stepsEnvironmentMeta) {
|
|
1413
|
+
next.stepsEnvironmentMeta = source.stepsEnvironmentMeta;
|
|
1414
|
+
}
|
|
1415
|
+
if (source.worldFactory) {
|
|
1416
|
+
next.worldFactory = source.worldFactory;
|
|
1417
|
+
}
|
|
1418
|
+
if (source.appFactory) {
|
|
1419
|
+
next.appFactory = source.appFactory;
|
|
1420
|
+
}
|
|
1421
|
+
if (source.ensureFactory) {
|
|
1422
|
+
next.ensureFactory = source.ensureFactory;
|
|
1423
|
+
}
|
|
1424
|
+
return next;
|
|
1425
|
+
}
|
|
1426
|
+
function collectCurrentOptions(state) {
|
|
1427
|
+
const options = {
|
|
1428
|
+
...state.options
|
|
1429
|
+
};
|
|
1430
|
+
if (state.worldFactory) {
|
|
1431
|
+
options.worldFactory = state.worldFactory;
|
|
1432
|
+
}
|
|
1433
|
+
return options;
|
|
1434
|
+
}
|
|
1435
|
+
function applyOptions(state, options) {
|
|
1436
|
+
const { worldFactory, ...rest } = options;
|
|
1437
|
+
state.options = {
|
|
1438
|
+
...state.options,
|
|
1439
|
+
...rest
|
|
1440
|
+
};
|
|
1441
|
+
if ("worldFactory" in options) {
|
|
1442
|
+
if (worldFactory) {
|
|
1443
|
+
state.worldFactory = normalizeWorldFactory(
|
|
1444
|
+
worldFactory
|
|
1445
|
+
);
|
|
1446
|
+
} else {
|
|
1447
|
+
delete state.worldFactory;
|
|
1448
|
+
}
|
|
1449
|
+
delete state.ensureFactory;
|
|
1450
|
+
}
|
|
1451
|
+
invalidateCaches(state);
|
|
1452
|
+
}
|
|
1453
|
+
function normalizeAppFactory(app) {
|
|
1454
|
+
if (typeof app === "function") {
|
|
1455
|
+
if (app.length > 0) {
|
|
1456
|
+
return async (context) => await app(
|
|
1457
|
+
context
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
return async () => await app();
|
|
1461
|
+
}
|
|
1462
|
+
return async () => app;
|
|
1463
|
+
}
|
|
1464
|
+
function createDefaultsWorldFactory(defaults) {
|
|
1465
|
+
const inheritance = extractWorldInheritance(defaults);
|
|
1466
|
+
const snapshot = cloneDefaults(defaults);
|
|
1467
|
+
const factory = async () => cloneDefaults(snapshot);
|
|
1468
|
+
if (inheritance.size > 0) {
|
|
1469
|
+
Object.defineProperty(factory, WORLD_INHERIT_KEYS, {
|
|
1470
|
+
value: inheritance,
|
|
1471
|
+
writable: false,
|
|
1472
|
+
enumerable: false,
|
|
1473
|
+
configurable: false
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
return factory;
|
|
1477
|
+
}
|
|
1478
|
+
function ensureWorldDefaults(value) {
|
|
1479
|
+
if (!value || typeof value !== "object") {
|
|
1480
|
+
throw new TypeError(
|
|
1481
|
+
"withWorld defaults must be a non-null object"
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
return value;
|
|
1485
|
+
}
|
|
1486
|
+
function cloneDefaults(defaults) {
|
|
1487
|
+
const structuredCloneFn = globalThis.structuredClone;
|
|
1488
|
+
if (structuredCloneFn) {
|
|
1489
|
+
try {
|
|
1490
|
+
return structuredCloneFn(defaults);
|
|
1491
|
+
} catch {
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
return cloneWithFallback(defaults);
|
|
1495
|
+
}
|
|
1496
|
+
function extractWorldInheritance(defaults) {
|
|
1497
|
+
const inherit = defaults[WORLD_INHERIT_KEYS];
|
|
1498
|
+
if (!inherit || inherit.length === 0) {
|
|
1499
|
+
return /* @__PURE__ */ new Set();
|
|
1500
|
+
}
|
|
1501
|
+
const inheritance = new Set(inherit);
|
|
1502
|
+
return inheritance;
|
|
1503
|
+
}
|
|
1504
|
+
function getWorldInheritance(factory) {
|
|
1505
|
+
if (!factory) {
|
|
1506
|
+
return void 0;
|
|
1507
|
+
}
|
|
1508
|
+
const withMetadata = factory;
|
|
1509
|
+
return withMetadata[WORLD_INHERIT_KEYS];
|
|
1510
|
+
}
|
|
1511
|
+
function cloneWithFallback(value) {
|
|
1512
|
+
if (Array.isArray(value)) {
|
|
1513
|
+
return value.map((item) => cloneWithFallback(item));
|
|
1514
|
+
}
|
|
1515
|
+
if (value instanceof Map) {
|
|
1516
|
+
return new Map(
|
|
1517
|
+
Array.from(value.entries(), ([key, entry]) => [key, cloneWithFallback(entry)])
|
|
1518
|
+
);
|
|
1519
|
+
}
|
|
1520
|
+
if (value instanceof Set) {
|
|
1521
|
+
return new Set(Array.from(value.values(), (entry) => cloneWithFallback(entry)));
|
|
1522
|
+
}
|
|
1523
|
+
if (value && typeof value === "object") {
|
|
1524
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1525
|
+
if (prototype === Object.prototype || prototype === null) {
|
|
1526
|
+
const result = {};
|
|
1527
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1528
|
+
result[key] = cloneWithFallback(entry);
|
|
1529
|
+
}
|
|
1530
|
+
return result;
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
return value;
|
|
1534
|
+
}
|
|
1535
|
+
function invalidateCaches(state) {
|
|
1536
|
+
delete state.stepsCache;
|
|
1537
|
+
delete state.decoratorsCache;
|
|
1538
|
+
delete state.bindingsTSCache;
|
|
1539
|
+
}
|
|
1540
|
+
function ensureSteps(state) {
|
|
1541
|
+
let cache = state.stepsCache;
|
|
1542
|
+
if (!cache) {
|
|
1543
|
+
const options = buildRunnerOptions(state, { includeParameterTypes: true });
|
|
1544
|
+
const environment = createRunner(options);
|
|
1545
|
+
const globals = createGlobalRunner();
|
|
1546
|
+
globals.useEnvironment(environment);
|
|
1547
|
+
const ensureFactory = resolveEnsureFactory(state);
|
|
1548
|
+
const surface = attachStepsHelpers(
|
|
1549
|
+
state,
|
|
1550
|
+
environment,
|
|
1551
|
+
globals,
|
|
1552
|
+
ensureFactory
|
|
1553
|
+
);
|
|
1554
|
+
try {
|
|
1555
|
+
Object.defineProperty(surface, STEPS_ENVIRONMENT_META, {
|
|
1556
|
+
value: state.stepsEnvironmentMeta ?? { kind: "root" },
|
|
1557
|
+
writable: false,
|
|
1558
|
+
enumerable: false,
|
|
1559
|
+
configurable: false
|
|
1560
|
+
});
|
|
1561
|
+
} catch {
|
|
1562
|
+
}
|
|
1563
|
+
cache = {
|
|
1564
|
+
environment,
|
|
1565
|
+
globals,
|
|
1566
|
+
surface,
|
|
1567
|
+
ensureFactory
|
|
1568
|
+
};
|
|
1569
|
+
state.stepsCache = cache;
|
|
1570
|
+
}
|
|
1571
|
+
return cache.surface;
|
|
1572
|
+
}
|
|
1573
|
+
function ensureDecorators(state) {
|
|
1574
|
+
let cache = state.decoratorsCache;
|
|
1575
|
+
if (!cache) {
|
|
1576
|
+
const steps = ensureSteps(state);
|
|
1577
|
+
const options = buildRunnerOptions(state, {
|
|
1578
|
+
includeParameterTypes: false
|
|
1579
|
+
});
|
|
1580
|
+
const decoratorOptions = {
|
|
1581
|
+
...options,
|
|
1582
|
+
parameterRegistry: steps.parameterRegistry,
|
|
1583
|
+
registerDefaultParameterTypes: false
|
|
1584
|
+
};
|
|
1585
|
+
const environment = createDecoratorRunner(decoratorOptions);
|
|
1586
|
+
const decorators = createRunnerDecorators(environment);
|
|
1587
|
+
const surface = attachDecoratorEnvironment(decorators, environment);
|
|
1588
|
+
cache = {
|
|
1589
|
+
environment,
|
|
1590
|
+
surface
|
|
1591
|
+
};
|
|
1592
|
+
state.decoratorsCache = cache;
|
|
1593
|
+
}
|
|
1594
|
+
return cache.surface;
|
|
1595
|
+
}
|
|
1596
|
+
function ensureBindingsTS(state) {
|
|
1597
|
+
let cache = state.bindingsTSCache;
|
|
1598
|
+
if (!cache) {
|
|
1599
|
+
const stepsEnv = ensureSteps(state);
|
|
1600
|
+
const surface = createBindingsTS(stepsEnv);
|
|
1601
|
+
cache = {
|
|
1602
|
+
surface
|
|
1603
|
+
};
|
|
1604
|
+
state.bindingsTSCache = cache;
|
|
1605
|
+
}
|
|
1606
|
+
return cache.surface;
|
|
1607
|
+
}
|
|
1608
|
+
function buildRunnerOptions(state, options) {
|
|
1609
|
+
const includeParameterTypes = options?.includeParameterTypes ?? true;
|
|
1610
|
+
const base = {
|
|
1611
|
+
...state.options
|
|
1612
|
+
};
|
|
1613
|
+
if (!includeParameterTypes && "parameterTypes" in base) {
|
|
1614
|
+
delete base.parameterTypes;
|
|
1615
|
+
}
|
|
1616
|
+
const featureRegistry = ensureFeatureRegistry(state);
|
|
1617
|
+
const worldFactory = composeWorldFactory(
|
|
1618
|
+
state.worldFactory,
|
|
1619
|
+
state.appFactory,
|
|
1620
|
+
featureRegistry
|
|
1621
|
+
);
|
|
1622
|
+
if (worldFactory) {
|
|
1623
|
+
base.worldFactory = worldFactory;
|
|
1624
|
+
} else if ("worldFactory" in base) {
|
|
1625
|
+
delete base.worldFactory;
|
|
1626
|
+
}
|
|
1627
|
+
return base;
|
|
1628
|
+
}
|
|
1629
|
+
function composeWorldFactory(baseFactory, appFactory, featureRegistry) {
|
|
1630
|
+
if (!baseFactory && !appFactory && !featureRegistry) {
|
|
1631
|
+
return void 0;
|
|
1632
|
+
}
|
|
1633
|
+
const factory = baseFactory ?? (async (_context) => ({}));
|
|
1634
|
+
const inheritance = getWorldInheritance(baseFactory);
|
|
1635
|
+
return async (context) => {
|
|
1636
|
+
const container = injection.createContainer();
|
|
1637
|
+
const world = await factory(context);
|
|
1638
|
+
const asObject = ensureWorldObject(world);
|
|
1639
|
+
const parentObject = context.parent !== void 0 ? ensureWorldObject(context.parent) : void 0;
|
|
1640
|
+
const mergedWorld = parentObject !== void 0 ? mergeWorldWithParent(asObject, parentObject, inheritance) : asObject;
|
|
1641
|
+
attachWorldAncestors(mergedWorld, parentObject);
|
|
1642
|
+
attachFeatureRegistry(mergedWorld, featureRegistry);
|
|
1643
|
+
attachContainer(mergedWorld, container);
|
|
1644
|
+
attachRuntime(mergedWorld);
|
|
1645
|
+
attachWorldToJson(mergedWorld);
|
|
1646
|
+
container.registerValue(WORLD_TOKEN, mergedWorld, {
|
|
1647
|
+
scope: injection.Scope.SCENARIO
|
|
1648
|
+
});
|
|
1649
|
+
if (appFactory) {
|
|
1650
|
+
const resolvedAppFactory = appFactory;
|
|
1651
|
+
const composer = createAppFactoryContext(container, mergedWorld);
|
|
1652
|
+
const appResult = await resolvedAppFactory(composer);
|
|
1653
|
+
const app = appResult ?? composer.getRegisteredApp();
|
|
1654
|
+
if (app === void 0) {
|
|
1655
|
+
throw new Error(
|
|
1656
|
+
"App factory did not return an application instance. Use return or registerApp to provide one."
|
|
1657
|
+
);
|
|
1658
|
+
}
|
|
1659
|
+
mergedWorld.app = app;
|
|
1660
|
+
}
|
|
1661
|
+
return mergedWorld;
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
function attachStepsHelpers(state, environment, globals, ensureFactory) {
|
|
1665
|
+
if (!("globals" in environment)) {
|
|
1666
|
+
Object.defineProperty(environment, "globals", {
|
|
1667
|
+
value: globals,
|
|
1668
|
+
enumerable: true,
|
|
1669
|
+
configurable: true
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
if (!("coordinateFeature" in environment)) {
|
|
1673
|
+
Object.defineProperty(environment, "coordinateFeature", {
|
|
1674
|
+
value: (options) => {
|
|
1675
|
+
const registry = ensureFeatureRegistry(state);
|
|
1676
|
+
if (options.feature) {
|
|
1677
|
+
registry.remember(options.feature);
|
|
1678
|
+
}
|
|
1679
|
+
return coordinateRunnerFeature({
|
|
1680
|
+
environment,
|
|
1681
|
+
...options
|
|
1682
|
+
});
|
|
1683
|
+
},
|
|
1684
|
+
enumerable: true,
|
|
1685
|
+
configurable: true
|
|
1686
|
+
});
|
|
1687
|
+
}
|
|
1688
|
+
if (!("ensure" in environment)) {
|
|
1689
|
+
Object.defineProperty(environment, "ensure", {
|
|
1690
|
+
value: ensureFactory,
|
|
1691
|
+
enumerable: true,
|
|
1692
|
+
configurable: true
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1695
|
+
return environment;
|
|
1696
|
+
}
|
|
1697
|
+
function resolveEnsureFactory(state) {
|
|
1698
|
+
if (state.ensureFactory) {
|
|
1699
|
+
return state.ensureFactory;
|
|
1700
|
+
}
|
|
1701
|
+
const factory = assertions.createDefaultEnsureFactory();
|
|
1702
|
+
const proxy = createImplicitEnsureProxy(factory);
|
|
1703
|
+
state.ensureFactory = proxy;
|
|
1704
|
+
return proxy;
|
|
1705
|
+
}
|
|
1706
|
+
function attachDecoratorEnvironment(decorators, environment) {
|
|
1707
|
+
if (!("environment" in decorators)) {
|
|
1708
|
+
Object.defineProperty(decorators, "environment", {
|
|
1709
|
+
value: environment,
|
|
1710
|
+
enumerable: true,
|
|
1711
|
+
configurable: true
|
|
1712
|
+
});
|
|
1713
|
+
}
|
|
1714
|
+
return decorators;
|
|
1715
|
+
}
|
|
1716
|
+
function ensureWorldObject(world) {
|
|
1717
|
+
if (world && typeof world === "object") {
|
|
1718
|
+
return world;
|
|
1719
|
+
}
|
|
1720
|
+
return {};
|
|
1721
|
+
}
|
|
1722
|
+
function attachContainer(world, container) {
|
|
1723
|
+
const descriptor = {
|
|
1724
|
+
value: container,
|
|
1725
|
+
configurable: true,
|
|
1726
|
+
enumerable: false,
|
|
1727
|
+
writable: false
|
|
1728
|
+
};
|
|
1729
|
+
if (!Reflect.has(world, "di")) {
|
|
1730
|
+
Object.defineProperty(world, "di", descriptor);
|
|
1731
|
+
}
|
|
1732
|
+
if (!Reflect.has(world, "container")) {
|
|
1733
|
+
Object.defineProperty(world, "container", descriptor);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
function createAppFactoryContext(container, world) {
|
|
1737
|
+
let registeredApp;
|
|
1738
|
+
function withScenarioScope(options) {
|
|
1739
|
+
return {
|
|
1740
|
+
scope: options?.scope ?? injection.Scope.SCENARIO,
|
|
1741
|
+
...options?.tags ? { tags: [...options.tags] } : {},
|
|
1742
|
+
...options?.deps ? { deps: [...options.deps] } : {},
|
|
1743
|
+
...options?.props ? { props: options.props } : {}
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
const context = {
|
|
1747
|
+
container,
|
|
1748
|
+
world,
|
|
1749
|
+
getRegisteredApp() {
|
|
1750
|
+
return registeredApp;
|
|
1751
|
+
},
|
|
1752
|
+
registerClass(target, options) {
|
|
1753
|
+
const { scope, tags, deps, inject } = options ?? {};
|
|
1754
|
+
let propsMap;
|
|
1755
|
+
if (inject) {
|
|
1756
|
+
const keys = Reflect.ownKeys(inject);
|
|
1757
|
+
if (keys.length > 0) {
|
|
1758
|
+
const entries = [];
|
|
1759
|
+
for (const key of keys) {
|
|
1760
|
+
const descriptor = inject[key];
|
|
1761
|
+
if (!descriptor) {
|
|
1762
|
+
continue;
|
|
1763
|
+
}
|
|
1764
|
+
entries.push([key, descriptor]);
|
|
1765
|
+
}
|
|
1766
|
+
if (entries.length > 0) {
|
|
1767
|
+
propsMap = Object.fromEntries(entries.map(([key, descriptor]) => {
|
|
1768
|
+
if (typeof descriptor === "object" && "token" in descriptor) {
|
|
1769
|
+
return [key, {
|
|
1770
|
+
token: descriptor.token,
|
|
1771
|
+
...descriptor.lazy ? { lazy: descriptor.lazy } : {}
|
|
1772
|
+
}];
|
|
1773
|
+
}
|
|
1774
|
+
return [key, descriptor];
|
|
1775
|
+
}));
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
const registration = {
|
|
1780
|
+
scope: scope ?? injection.Scope.SCENARIO,
|
|
1781
|
+
...tags ? { tags: [...tags] } : {},
|
|
1782
|
+
...deps ? { deps: [...deps] } : {},
|
|
1783
|
+
...propsMap ? { props: propsMap } : {}
|
|
1784
|
+
};
|
|
1785
|
+
container.registerClass(target, registration);
|
|
1786
|
+
return context;
|
|
1787
|
+
},
|
|
1788
|
+
registerValue(identifier, value, options) {
|
|
1789
|
+
container.registerValue(identifier, value, withScenarioScope(options));
|
|
1790
|
+
return context;
|
|
1791
|
+
},
|
|
1792
|
+
registerFactory(identifier, factory, options) {
|
|
1793
|
+
container.registerFactory(identifier, factory, withScenarioScope(options));
|
|
1794
|
+
return context;
|
|
1795
|
+
},
|
|
1796
|
+
registerToken(token, target, options) {
|
|
1797
|
+
container.registerToken(token, target, withScenarioScope(options));
|
|
1798
|
+
return context;
|
|
1799
|
+
},
|
|
1800
|
+
async registerApp(target, options) {
|
|
1801
|
+
context.registerClass(target, options);
|
|
1802
|
+
const instance = container.resolve(target);
|
|
1803
|
+
registeredApp = instance;
|
|
1804
|
+
if (options?.configure) {
|
|
1805
|
+
await options.configure(instance, context);
|
|
1806
|
+
}
|
|
1807
|
+
return instance;
|
|
1808
|
+
},
|
|
1809
|
+
resolve(identifier) {
|
|
1810
|
+
return container.resolve(identifier);
|
|
1811
|
+
}
|
|
1812
|
+
};
|
|
1813
|
+
return context;
|
|
1814
|
+
}
|
|
1815
|
+
function attachRuntime(world) {
|
|
1816
|
+
if (Reflect.has(world, "runtime")) {
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
Object.defineProperty(world, "runtime", {
|
|
1820
|
+
get() {
|
|
1821
|
+
return executor.createStepRuntime(this);
|
|
1822
|
+
},
|
|
1823
|
+
enumerable: false,
|
|
1824
|
+
configurable: true
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
var WORLD_JSON_EXCLUDE_KEYS = /* @__PURE__ */ new Set([
|
|
1828
|
+
"app",
|
|
1829
|
+
"di",
|
|
1830
|
+
"container",
|
|
1831
|
+
"runtime",
|
|
1832
|
+
"ancestors"
|
|
1833
|
+
]);
|
|
1834
|
+
function attachWorldToJson(world) {
|
|
1835
|
+
if (Reflect.has(world, "toJSON")) {
|
|
1836
|
+
return;
|
|
1837
|
+
}
|
|
1838
|
+
Object.defineProperty(world, "toJSON", {
|
|
1839
|
+
value: () => {
|
|
1840
|
+
const stack = /* @__PURE__ */ new WeakSet();
|
|
1841
|
+
return toJsonSafeValue(world, 8, stack);
|
|
1842
|
+
},
|
|
1843
|
+
enumerable: false,
|
|
1844
|
+
configurable: true,
|
|
1845
|
+
writable: true
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1848
|
+
function toJsonSafeValue(value, depth, stack) {
|
|
1849
|
+
if (value === null) {
|
|
1850
|
+
return null;
|
|
1851
|
+
}
|
|
1852
|
+
switch (typeof value) {
|
|
1853
|
+
case "boolean":
|
|
1854
|
+
case "number":
|
|
1855
|
+
case "string":
|
|
1856
|
+
return value;
|
|
1857
|
+
case "bigint":
|
|
1858
|
+
return value.toString();
|
|
1859
|
+
case "undefined":
|
|
1860
|
+
return "[undefined]";
|
|
1861
|
+
case "symbol":
|
|
1862
|
+
return value.toString();
|
|
1863
|
+
case "function":
|
|
1864
|
+
return "[Function]";
|
|
1865
|
+
case "object":
|
|
1866
|
+
break;
|
|
1867
|
+
default:
|
|
1868
|
+
return String(value);
|
|
1869
|
+
}
|
|
1870
|
+
if (depth <= 0) {
|
|
1871
|
+
return "[MaxDepth]";
|
|
1872
|
+
}
|
|
1873
|
+
const obj = value;
|
|
1874
|
+
if (stack.has(obj)) {
|
|
1875
|
+
return "[Circular]";
|
|
1876
|
+
}
|
|
1877
|
+
if (Array.isArray(obj)) {
|
|
1878
|
+
stack.add(obj);
|
|
1879
|
+
try {
|
|
1880
|
+
return obj.map((entry) => toJsonSafeValue(entry, depth - 1, stack));
|
|
1881
|
+
} finally {
|
|
1882
|
+
stack.delete(obj);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
if (obj instanceof Date) {
|
|
1886
|
+
return obj.toISOString();
|
|
1887
|
+
}
|
|
1888
|
+
if (obj instanceof Error) {
|
|
1889
|
+
return {
|
|
1890
|
+
name: obj.name,
|
|
1891
|
+
message: obj.message,
|
|
1892
|
+
stack: obj.stack ?? ""
|
|
1893
|
+
};
|
|
1894
|
+
}
|
|
1895
|
+
if (obj instanceof Map) {
|
|
1896
|
+
stack.add(obj);
|
|
1897
|
+
try {
|
|
1898
|
+
return {
|
|
1899
|
+
"[Map]": Array.from(obj.entries()).map(([key, entry]) => ({
|
|
1900
|
+
key: toJsonSafeValue(key, depth - 1, stack),
|
|
1901
|
+
value: toJsonSafeValue(entry, depth - 1, stack)
|
|
1902
|
+
}))
|
|
1903
|
+
};
|
|
1904
|
+
} finally {
|
|
1905
|
+
stack.delete(obj);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
if (obj instanceof Set) {
|
|
1909
|
+
stack.add(obj);
|
|
1910
|
+
try {
|
|
1911
|
+
return { "[Set]": Array.from(obj.values()).map((entry) => toJsonSafeValue(entry, depth - 1, stack)) };
|
|
1912
|
+
} finally {
|
|
1913
|
+
stack.delete(obj);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
stack.add(obj);
|
|
1917
|
+
try {
|
|
1918
|
+
const record = obj;
|
|
1919
|
+
const result = {};
|
|
1920
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
1921
|
+
if (WORLD_JSON_EXCLUDE_KEYS.has(key)) {
|
|
1922
|
+
continue;
|
|
1923
|
+
}
|
|
1924
|
+
result[key] = toJsonSafeValue(entry, depth - 1, stack);
|
|
1925
|
+
}
|
|
1926
|
+
return result;
|
|
1927
|
+
} finally {
|
|
1928
|
+
stack.delete(obj);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
function attachFeatureRegistry(world, featureRegistry) {
|
|
1932
|
+
if (!featureRegistry) {
|
|
1933
|
+
return;
|
|
1934
|
+
}
|
|
1935
|
+
world.features = featureRegistry.snapshot();
|
|
1936
|
+
}
|
|
1937
|
+
var PARENT_WORLD_EXCLUDE_KEYS = /* @__PURE__ */ new Set([
|
|
1938
|
+
"di",
|
|
1939
|
+
"container",
|
|
1940
|
+
"runtime",
|
|
1941
|
+
"app",
|
|
1942
|
+
"ancestors"
|
|
1943
|
+
]);
|
|
1944
|
+
function mergeWorldWithParent(child, parent, inheritance) {
|
|
1945
|
+
if (!parent || !inheritance || inheritance.size === 0) {
|
|
1946
|
+
return child;
|
|
1947
|
+
}
|
|
1948
|
+
for (const key of inheritance) {
|
|
1949
|
+
if (PARENT_WORLD_EXCLUDE_KEYS.has(key)) {
|
|
1950
|
+
continue;
|
|
1951
|
+
}
|
|
1952
|
+
if (!Reflect.has(parent, key)) {
|
|
1953
|
+
continue;
|
|
1954
|
+
}
|
|
1955
|
+
const descriptor = Object.getOwnPropertyDescriptor(parent, key);
|
|
1956
|
+
if (descriptor) {
|
|
1957
|
+
Object.defineProperty(child, key, descriptor);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
return child;
|
|
1961
|
+
}
|
|
1962
|
+
function attachWorldAncestors(world, parent) {
|
|
1963
|
+
const parentAncestors = parent && Reflect.has(parent, "ancestors") ? parent.ancestors : void 0;
|
|
1964
|
+
const lineage = parent ? [
|
|
1965
|
+
parent,
|
|
1966
|
+
...Array.isArray(parentAncestors) ? parentAncestors : []
|
|
1967
|
+
] : [];
|
|
1968
|
+
Object.defineProperty(world, "ancestors", {
|
|
1969
|
+
value: lineage,
|
|
1970
|
+
writable: false,
|
|
1971
|
+
enumerable: false,
|
|
1972
|
+
configurable: true
|
|
1973
|
+
});
|
|
1974
|
+
}
|
|
1975
|
+
function ensureFeatureRegistry(state) {
|
|
1976
|
+
if (!state.featureRegistry) {
|
|
1977
|
+
state.featureRegistry = createFeatureRegistry();
|
|
1978
|
+
}
|
|
1979
|
+
return state.featureRegistry;
|
|
1980
|
+
}
|
|
1981
|
+
function createFeatureRegistry() {
|
|
1982
|
+
const byId = /* @__PURE__ */ new Map();
|
|
1983
|
+
return {
|
|
1984
|
+
remember(feature) {
|
|
1985
|
+
const id = feature.uri ?? feature.name;
|
|
1986
|
+
if (!id || byId.has(id)) {
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1989
|
+
byId.set(id, feature);
|
|
1990
|
+
},
|
|
1991
|
+
snapshot() {
|
|
1992
|
+
return Array.from(byId.values());
|
|
1993
|
+
}
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
function createImplicitEnsureProxy(factory) {
|
|
1997
|
+
return new Proxy(factory, {
|
|
1998
|
+
get(target, prop, receiver) {
|
|
1999
|
+
if (prop === "world") {
|
|
2000
|
+
return executor.tryGetWorld();
|
|
2001
|
+
}
|
|
2002
|
+
const world = executor.tryGetWorld();
|
|
2003
|
+
if (world) {
|
|
2004
|
+
const facade = factory(world);
|
|
2005
|
+
return Reflect.get(facade, prop, receiver);
|
|
2006
|
+
}
|
|
2007
|
+
return Reflect.get(target, prop, receiver);
|
|
2008
|
+
},
|
|
2009
|
+
apply(target, _thisArg, args) {
|
|
2010
|
+
const [arg, options] = args;
|
|
2011
|
+
const world = executor.tryGetWorld();
|
|
2012
|
+
if (world) {
|
|
2013
|
+
if (arg === world) {
|
|
2014
|
+
return factory(world);
|
|
2015
|
+
}
|
|
2016
|
+
const facade = factory(world);
|
|
2017
|
+
return facade(arg, options);
|
|
2018
|
+
}
|
|
2019
|
+
return factory(arg);
|
|
2020
|
+
}
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
// src/current.ts
|
|
2025
|
+
var stepsErrorMessage = "Runner steps surface has not been configured. Call setCurrentRunnerSteps() before accessing the shared runner surface.";
|
|
2026
|
+
var currentSteps;
|
|
2027
|
+
function setCurrentRunnerSteps(steps) {
|
|
2028
|
+
currentSteps = steps;
|
|
2029
|
+
}
|
|
2030
|
+
function getCurrentRunnerSteps() {
|
|
2031
|
+
if (!currentSteps) {
|
|
2032
|
+
throw new Error(stepsErrorMessage);
|
|
2033
|
+
}
|
|
2034
|
+
return currentSteps;
|
|
2035
|
+
}
|
|
2036
|
+
function clearCurrentRunnerSteps() {
|
|
2037
|
+
currentSteps = void 0;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
// src/global.ts
|
|
2041
|
+
var runnerInstance;
|
|
2042
|
+
function instantiateRunner(options) {
|
|
2043
|
+
return createGlobalRunner(options);
|
|
2044
|
+
}
|
|
2045
|
+
function requireConfigured(action) {
|
|
2046
|
+
if (!runnerInstance) {
|
|
2047
|
+
throw new Error(
|
|
2048
|
+
`Global runner has not been configured. ${action}`
|
|
2049
|
+
);
|
|
2050
|
+
}
|
|
2051
|
+
return runnerInstance;
|
|
2052
|
+
}
|
|
2053
|
+
function getGlobalRunner(options) {
|
|
2054
|
+
if (!runnerInstance) {
|
|
2055
|
+
runnerInstance = instantiateRunner(options);
|
|
2056
|
+
}
|
|
2057
|
+
return runnerInstance;
|
|
2058
|
+
}
|
|
2059
|
+
function configureGlobalRunner(options) {
|
|
2060
|
+
runnerInstance = instantiateRunner(options);
|
|
2061
|
+
return runnerInstance;
|
|
2062
|
+
}
|
|
2063
|
+
function resetGlobalRunner(options) {
|
|
2064
|
+
runnerInstance = instantiateRunner(options);
|
|
2065
|
+
return runnerInstance;
|
|
2066
|
+
}
|
|
2067
|
+
function disposeGlobalRunner() {
|
|
2068
|
+
runnerInstance = void 0;
|
|
2069
|
+
}
|
|
2070
|
+
function useGlobalRunnerEnvironment(environment) {
|
|
2071
|
+
const runner = requireConfigured(
|
|
2072
|
+
"Call configureGlobalRunner() before injecting environments."
|
|
2073
|
+
);
|
|
2074
|
+
return runner.useEnvironment(environment);
|
|
2075
|
+
}
|
|
2076
|
+
function getGlobalRunnerEnvironment() {
|
|
2077
|
+
const runner = requireConfigured(
|
|
2078
|
+
"Call configureGlobalRunner() before reading environments."
|
|
2079
|
+
);
|
|
2080
|
+
return runner.getEnvironment();
|
|
2081
|
+
}
|
|
2082
|
+
function getConfiguredGlobalRunner() {
|
|
2083
|
+
return requireConfigured(
|
|
2084
|
+
"Call configureGlobalRunner() before accessing runner APIs."
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
// src/cucumber-runner.ts
|
|
2089
|
+
var CucumberRunner = class {
|
|
2090
|
+
static builder(initial) {
|
|
2091
|
+
return createRunnerBuilder(initial);
|
|
2092
|
+
}
|
|
2093
|
+
static setSteps(steps) {
|
|
2094
|
+
setCurrentRunnerSteps(steps);
|
|
2095
|
+
}
|
|
2096
|
+
static steps() {
|
|
2097
|
+
return getCurrentRunnerSteps();
|
|
2098
|
+
}
|
|
2099
|
+
static clearSteps() {
|
|
2100
|
+
clearCurrentRunnerSteps();
|
|
2101
|
+
}
|
|
2102
|
+
};
|
|
2103
|
+
|
|
2104
|
+
Object.defineProperty(exports, 'Pending', {
|
|
2105
|
+
enumerable: true,
|
|
2106
|
+
get: function () { return executor.Pending; }
|
|
2107
|
+
});
|
|
2108
|
+
Object.defineProperty(exports, 'ScenarioPendingError', {
|
|
2109
|
+
enumerable: true,
|
|
2110
|
+
get: function () { return executor.ScenarioPendingError; }
|
|
2111
|
+
});
|
|
2112
|
+
Object.defineProperty(exports, 'ToDo', {
|
|
2113
|
+
enumerable: true,
|
|
2114
|
+
get: function () { return executor.ToDo; }
|
|
2115
|
+
});
|
|
2116
|
+
Object.defineProperty(exports, 'clearStepDocstring', {
|
|
2117
|
+
enumerable: true,
|
|
2118
|
+
get: function () { return executor.clearStepDocstring; }
|
|
2119
|
+
});
|
|
2120
|
+
Object.defineProperty(exports, 'clearStepTable', {
|
|
2121
|
+
enumerable: true,
|
|
2122
|
+
get: function () { return executor.clearStepTable; }
|
|
2123
|
+
});
|
|
2124
|
+
Object.defineProperty(exports, 'configureStepDocstrings', {
|
|
2125
|
+
enumerable: true,
|
|
2126
|
+
get: function () { return executor.configureStepDocstrings; }
|
|
2127
|
+
});
|
|
2128
|
+
Object.defineProperty(exports, 'configureStepTables', {
|
|
2129
|
+
enumerable: true,
|
|
2130
|
+
get: function () { return executor.configureStepTables; }
|
|
2131
|
+
});
|
|
2132
|
+
Object.defineProperty(exports, 'consumeDocstring', {
|
|
2133
|
+
enumerable: true,
|
|
2134
|
+
get: function () { return executor.consumeDocstring; }
|
|
2135
|
+
});
|
|
2136
|
+
Object.defineProperty(exports, 'consumeTable', {
|
|
2137
|
+
enumerable: true,
|
|
2138
|
+
get: function () { return executor.consumeTable; }
|
|
2139
|
+
});
|
|
2140
|
+
Object.defineProperty(exports, 'getDocstring', {
|
|
2141
|
+
enumerable: true,
|
|
2142
|
+
get: function () { return executor.getDocstring; }
|
|
2143
|
+
});
|
|
2144
|
+
Object.defineProperty(exports, 'getDocstringInfo', {
|
|
2145
|
+
enumerable: true,
|
|
2146
|
+
get: function () { return executor.getDocstringInfo; }
|
|
2147
|
+
});
|
|
2148
|
+
Object.defineProperty(exports, 'getDocstringMediaType', {
|
|
2149
|
+
enumerable: true,
|
|
2150
|
+
get: function () { return executor.getDocstringMediaType; }
|
|
2151
|
+
});
|
|
2152
|
+
Object.defineProperty(exports, 'getRawTable', {
|
|
2153
|
+
enumerable: true,
|
|
2154
|
+
get: function () { return executor.getRawTable; }
|
|
2155
|
+
});
|
|
2156
|
+
Object.defineProperty(exports, 'getTable', {
|
|
2157
|
+
enumerable: true,
|
|
2158
|
+
get: function () { return executor.getTable; }
|
|
2159
|
+
});
|
|
2160
|
+
Object.defineProperty(exports, 'isScenarioPendingError', {
|
|
2161
|
+
enumerable: true,
|
|
2162
|
+
get: function () { return executor.isScenarioPendingError; }
|
|
2163
|
+
});
|
|
2164
|
+
Object.defineProperty(exports, 'markScenarioPending', {
|
|
2165
|
+
enumerable: true,
|
|
2166
|
+
get: function () { return executor.markScenarioPending; }
|
|
2167
|
+
});
|
|
2168
|
+
Object.defineProperty(exports, 'resetStepDocstringConfig', {
|
|
2169
|
+
enumerable: true,
|
|
2170
|
+
get: function () { return executor.resetStepDocstringConfig; }
|
|
2171
|
+
});
|
|
2172
|
+
Object.defineProperty(exports, 'resetStepTableConfig', {
|
|
2173
|
+
enumerable: true,
|
|
2174
|
+
get: function () { return executor.resetStepTableConfig; }
|
|
2175
|
+
});
|
|
2176
|
+
Object.defineProperty(exports, 'setStepDocstring', {
|
|
2177
|
+
enumerable: true,
|
|
2178
|
+
get: function () { return executor.setStepDocstring; }
|
|
2179
|
+
});
|
|
2180
|
+
Object.defineProperty(exports, 'setStepDocstringInfo', {
|
|
2181
|
+
enumerable: true,
|
|
2182
|
+
get: function () { return executor.setStepDocstringInfo; }
|
|
2183
|
+
});
|
|
2184
|
+
Object.defineProperty(exports, 'setStepTable', {
|
|
2185
|
+
enumerable: true,
|
|
2186
|
+
get: function () { return executor.setStepTable; }
|
|
2187
|
+
});
|
|
2188
|
+
exports.App = App;
|
|
2189
|
+
exports.CucumberRunner = CucumberRunner;
|
|
2190
|
+
exports.ParameterRegistryAdapter = ParameterRegistryAdapter;
|
|
2191
|
+
exports.RunnerContext = RunnerContext;
|
|
2192
|
+
exports.STEPS_ENVIRONMENT_META = STEPS_ENVIRONMENT_META;
|
|
2193
|
+
exports.WORLD_INHERIT_KEYS = WORLD_INHERIT_KEYS;
|
|
2194
|
+
exports.WORLD_TOKEN = WORLD_TOKEN;
|
|
2195
|
+
exports.clearCurrentRunnerSteps = clearCurrentRunnerSteps;
|
|
2196
|
+
exports.configureGlobalRunner = configureGlobalRunner;
|
|
2197
|
+
exports.coordinateRunnerFeature = coordinateRunnerFeature;
|
|
2198
|
+
exports.createDecoratorRunner = createDecoratorRunner;
|
|
2199
|
+
exports.createGlobalRunner = createGlobalRunner;
|
|
2200
|
+
exports.createParameterRegistryAdapter = createParameterRegistryAdapter;
|
|
2201
|
+
exports.createRunner = createRunner;
|
|
2202
|
+
exports.default = createRunner;
|
|
2203
|
+
exports.disposeGlobalRunner = disposeGlobalRunner;
|
|
2204
|
+
exports.getConfiguredGlobalRunner = getConfiguredGlobalRunner;
|
|
2205
|
+
exports.getCurrentRunnerSteps = getCurrentRunnerSteps;
|
|
2206
|
+
exports.getGlobalRunner = getGlobalRunner;
|
|
2207
|
+
exports.getGlobalRunnerEnvironment = getGlobalRunnerEnvironment;
|
|
2208
|
+
exports.resetGlobalRunner = resetGlobalRunner;
|
|
2209
|
+
exports.setCurrentRunnerSteps = setCurrentRunnerSteps;
|
|
2210
|
+
exports.useGlobalRunnerEnvironment = useGlobalRunnerEnvironment;
|
|
2211
|
+
//# sourceMappingURL=out.js.map
|
|
2212
|
+
//# sourceMappingURL=index.cjs.map
|