racejar 1.2.14 → 1.3.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/dist/_chunks-cjs/compile-feature.cjs +101 -0
- package/dist/_chunks-cjs/compile-feature.cjs.map +1 -0
- package/dist/_chunks-dts/step-definitions.d.cts +44 -0
- package/dist/_chunks-dts/step-definitions.d.ts +44 -0
- package/dist/_chunks-es/compile-feature.js +88 -0
- package/dist/_chunks-es/compile-feature.js.map +1 -0
- package/dist/index.cjs +36 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +44 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/jest/index.cjs +29 -0
- package/dist/jest/index.cjs.map +1 -0
- package/dist/jest/index.d.cts +17 -0
- package/dist/jest/index.d.ts +17 -0
- package/dist/jest/index.js +30 -0
- package/dist/jest/index.js.map +1 -0
- package/dist/playwright/index.cjs +39 -0
- package/dist/playwright/index.cjs.map +1 -0
- package/dist/playwright/index.d.cts +25 -0
- package/dist/playwright/index.d.ts +25 -0
- package/dist/playwright/index.js +40 -0
- package/dist/playwright/index.js.map +1 -0
- package/dist/vitest/index.cjs +29 -0
- package/dist/vitest/index.cjs.map +1 -0
- package/dist/vitest/index.d.cts +17 -0
- package/dist/vitest/index.d.ts +17 -0
- package/dist/vitest/index.js +30 -0
- package/dist/vitest/index.js.map +1 -0
- package/package.json +39 -16
- package/src/compile-feature.ts +3 -3
- package/CHANGELOG.md +0 -150
- package/example/vitest.hello-herman.test.ts +0 -37
- package/example/vitest.hooks.test.ts +0 -49
- package/example-playwright/playwright-homepage.test.ts +0 -35
- package/tsconfig.json +0 -7
- package/vitest.config.ts +0 -15
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var cucumberExpressions = require("@cucumber/cucumber-expressions"), Gherkin = require("@cucumber/gherkin"), Messages = require("@cucumber/messages");
|
|
3
|
+
function _interopNamespaceCompat(e) {
|
|
4
|
+
if (e && typeof e == "object" && "default" in e) return e;
|
|
5
|
+
var n = /* @__PURE__ */ Object.create(null);
|
|
6
|
+
return e && Object.keys(e).forEach(function(k) {
|
|
7
|
+
if (k !== "default") {
|
|
8
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
9
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
10
|
+
enumerable: !0,
|
|
11
|
+
get: function() {
|
|
12
|
+
return e[k];
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}), n.default = e, Object.freeze(n);
|
|
17
|
+
}
|
|
18
|
+
var Gherkin__namespace = /* @__PURE__ */ _interopNamespaceCompat(Gherkin), Messages__namespace = /* @__PURE__ */ _interopNamespaceCompat(Messages);
|
|
19
|
+
function compileFeature({
|
|
20
|
+
featureText,
|
|
21
|
+
hooks,
|
|
22
|
+
stepDefinitions,
|
|
23
|
+
parameterTypes
|
|
24
|
+
}) {
|
|
25
|
+
const uuidFn = Messages__namespace.IdGenerator.uuid(), builder = new Gherkin__namespace.AstBuilder(uuidFn), matcher = new Gherkin__namespace.GherkinClassicTokenMatcher(), gherkinDocument = new Gherkin__namespace.Parser(builder, matcher).parse(featureText), pickles = Gherkin__namespace.compile(
|
|
26
|
+
gherkinDocument,
|
|
27
|
+
(gherkinDocument.feature?.name ?? "").replace(" ", "-"),
|
|
28
|
+
uuidFn
|
|
29
|
+
), parameterTypeRegistry = new cucumberExpressions.ParameterTypeRegistry();
|
|
30
|
+
if (parameterTypes && parameterTypes.forEach((parameterType) => {
|
|
31
|
+
parameterTypeRegistry.defineParameterType(parameterType);
|
|
32
|
+
}), !gherkinDocument.feature)
|
|
33
|
+
throw new Error("No feature found");
|
|
34
|
+
const stepImplementations = stepDefinitions.map((stepDefinition) => {
|
|
35
|
+
const expression = new cucumberExpressions.CucumberExpression(
|
|
36
|
+
stepDefinition.text,
|
|
37
|
+
parameterTypeRegistry
|
|
38
|
+
);
|
|
39
|
+
return {
|
|
40
|
+
type: stepDefinition.type,
|
|
41
|
+
text: stepDefinition.text,
|
|
42
|
+
expression,
|
|
43
|
+
callback: stepDefinition.callback
|
|
44
|
+
};
|
|
45
|
+
}), skippedFeature = gherkinDocument.feature.tags.some(
|
|
46
|
+
(tag) => tag.name === "@skip"
|
|
47
|
+
), onlyFeature = gherkinDocument.feature.tags.some(
|
|
48
|
+
(tag) => tag.name === "@only"
|
|
49
|
+
);
|
|
50
|
+
if (skippedFeature && onlyFeature)
|
|
51
|
+
throw new Error("Feature cannot have both @skip and @only tags");
|
|
52
|
+
let context = {};
|
|
53
|
+
const scenarios = pickles.map((pickle) => {
|
|
54
|
+
const skippedPickle = pickle.tags.some((tag) => tag.name === "@skip"), onlyPickle = pickle.tags.some((tag) => tag.name === "@only");
|
|
55
|
+
context = {};
|
|
56
|
+
const steps = pickle.steps.map((step) => {
|
|
57
|
+
const matchingSteps = stepImplementations.filter((stepImplementation) => stepImplementation.type === step.type).flatMap((stepImplementation) => {
|
|
58
|
+
const args2 = stepImplementation.expression.match(step.text);
|
|
59
|
+
return args2 ? [
|
|
60
|
+
{
|
|
61
|
+
...stepImplementation,
|
|
62
|
+
args: args2
|
|
63
|
+
}
|
|
64
|
+
] : [];
|
|
65
|
+
}), matchingStep = matchingSteps[0];
|
|
66
|
+
if (!matchingStep)
|
|
67
|
+
throw new Error(`No implementation found for step: ${step.text}`);
|
|
68
|
+
if (matchingSteps.length > 1)
|
|
69
|
+
throw new Error(`Multiple implementations found for step: ${step.text}`);
|
|
70
|
+
const args = matchingStep.args.map((arg) => arg.getValue(matchingStep));
|
|
71
|
+
return step.argument?.dataTable && args.push(
|
|
72
|
+
step.argument.dataTable.rows.map(
|
|
73
|
+
(row) => row.cells.map((cell) => cell.value)
|
|
74
|
+
)
|
|
75
|
+
), step.argument?.docString && args.push(step.argument.docString.content), (stepContext) => matchingStep.callback(
|
|
76
|
+
Object.assign(context, stepContext),
|
|
77
|
+
args[0],
|
|
78
|
+
args[1],
|
|
79
|
+
args[2]
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
name: pickle.name,
|
|
84
|
+
tag: skippedFeature || skippedPickle ? "skip" : onlyPickle ? "only" : void 0,
|
|
85
|
+
steps
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
tag: skippedFeature ? "skip" : onlyFeature ? "only" : void 0,
|
|
90
|
+
name: gherkinDocument.feature.name,
|
|
91
|
+
scenarios,
|
|
92
|
+
beforeHooks: (hooks ?? []).filter((hook) => hook.type === "Before").map(
|
|
93
|
+
(hook) => (stepContext) => hook.callback(Object.assign(context, stepContext))
|
|
94
|
+
),
|
|
95
|
+
afterHooks: (hooks ?? []).filter((hook) => hook.type === "After").map(
|
|
96
|
+
(hook) => (stepContext) => hook.callback(Object.assign(context, stepContext))
|
|
97
|
+
)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
exports.compileFeature = compileFeature;
|
|
101
|
+
//# sourceMappingURL=compile-feature.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-feature.cjs","sources":["../../src/compile-feature.ts"],"sourcesContent":["import type {ParameterType} from '@cucumber/cucumber-expressions'\nimport {\n CucumberExpression,\n ParameterTypeRegistry,\n} from '@cucumber/cucumber-expressions'\nimport * as Gherkin from '@cucumber/gherkin'\nimport * as Messages from '@cucumber/messages'\nimport type {Hook} from './hooks'\nimport type {StepDefinition} from './step-definitions'\n\n/**\n * @public\n */\nexport type CompiledFeature<TStepContext extends Record<string, any> = object> =\n {\n name: string\n tag: 'only' | 'skip' | undefined\n scenarios: Array<{\n name: string\n tag: 'only' | 'skip' | undefined\n steps: Array<(stepContext?: TStepContext) => Promise<void> | void>\n }>\n beforeHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>\n afterHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>\n }\n\n/**\n * @public\n */\nexport function compileFeature<\n TContext extends Record<string, any> = object,\n TStepContext extends Record<string, any> = object,\n>({\n featureText,\n hooks,\n stepDefinitions,\n parameterTypes,\n}: {\n featureText: string\n hooks?: Array<Hook<TStepContext>>\n stepDefinitions: Array<StepDefinition<TContext, any, any, any>>\n parameterTypes?: Array<ParameterType<unknown>>\n}): CompiledFeature<TStepContext> {\n const uuidFn = Messages.IdGenerator.uuid()\n const builder = new Gherkin.AstBuilder(uuidFn)\n const matcher = new Gherkin.GherkinClassicTokenMatcher()\n const parser = new Gherkin.Parser(builder, matcher)\n\n const gherkinDocument = parser.parse(featureText)\n const pickles = Gherkin.compile(\n gherkinDocument,\n (gherkinDocument.feature?.name ?? '').replace(' ', '-'),\n uuidFn,\n )\n\n const parameterTypeRegistry = new ParameterTypeRegistry()\n if (parameterTypes) {\n parameterTypes.forEach((parameterType) => {\n parameterTypeRegistry.defineParameterType(parameterType)\n })\n }\n\n if (!gherkinDocument.feature) {\n throw new Error('No feature found')\n }\n\n const stepImplementations = stepDefinitions.map((stepDefinition) => {\n const expression = new CucumberExpression(\n stepDefinition.text,\n parameterTypeRegistry,\n )\n\n return {\n type: stepDefinition.type,\n text: stepDefinition.text,\n expression,\n callback: stepDefinition.callback,\n }\n })\n\n const skippedFeature = gherkinDocument.feature.tags.some(\n (tag) => tag.name === '@skip',\n )\n const onlyFeature = gherkinDocument.feature.tags.some(\n (tag) => tag.name === '@only',\n )\n\n if (skippedFeature && onlyFeature) {\n throw new Error('Feature cannot have both @skip and @only tags')\n }\n\n let context = {} as TContext\n\n const scenarios = pickles.map((pickle) => {\n const skippedPickle = pickle.tags.some((tag) => tag.name === '@skip')\n const onlyPickle = pickle.tags.some((tag) => tag.name === '@only')\n context = {} as TContext\n\n const steps = pickle.steps.map((step) => {\n const matchingSteps = stepImplementations\n .filter((stepImplementation) => stepImplementation.type === step.type)\n .flatMap((stepImplementation) => {\n const args = stepImplementation.expression.match(step.text)\n\n if (args) {\n return [\n {\n ...stepImplementation,\n args,\n },\n ]\n }\n\n return []\n })\n\n const matchingStep = matchingSteps[0]\n\n if (!matchingStep) {\n throw new Error(`No implementation found for step: ${step.text}`)\n }\n\n if (matchingSteps.length > 1) {\n throw new Error(`Multiple implementations found for step: ${step.text}`)\n }\n\n const args = matchingStep.args.map((arg) => arg.getValue(matchingStep))\n if (step.argument?.dataTable) {\n args.push(\n step.argument.dataTable.rows.map((row) =>\n row.cells.map((cell) => cell.value),\n ),\n )\n }\n if (step.argument?.docString) {\n args.push(step.argument.docString.content)\n }\n\n return (stepContext: TStepContext | undefined) =>\n matchingStep.callback(\n Object.assign(context, stepContext),\n args[0],\n args[1],\n args[2],\n )\n })\n\n return {\n name: pickle.name,\n tag: skippedFeature\n ? ('skip' as const)\n : skippedPickle\n ? ('skip' as const)\n : onlyPickle\n ? ('only' as const)\n : undefined,\n steps,\n }\n })\n\n return {\n tag: skippedFeature ? 'skip' : onlyFeature ? 'only' : undefined,\n name: gherkinDocument.feature.name,\n scenarios,\n beforeHooks: (hooks ?? [])\n .filter((hook) => hook.type === 'Before')\n .map(\n (hook) => (stepContext: TStepContext | undefined) =>\n hook.callback(Object.assign(context, stepContext)),\n ),\n afterHooks: (hooks ?? [])\n .filter((hook) => hook.type === 'After')\n .map(\n (hook) => (stepContext: TStepContext | undefined) =>\n hook.callback(Object.assign(context, stepContext)),\n ),\n }\n}\n"],"names":["Messages","Gherkin","ParameterTypeRegistry","CucumberExpression","args"],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @public
|
|
3
|
+
*/
|
|
4
|
+
type Hook<TContext extends Record<string, any> = object> = {
|
|
5
|
+
type: 'Before' | 'After';
|
|
6
|
+
callback: HookCallback<TContext>;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
type HookCallback<TContext extends Record<string, any> = object> = (context: TContext) => Promise<void> | void;
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
declare function Before<TContext extends Record<string, any> = object>(callback: HookCallback<TContext>): Hook<TContext>;
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
declare function After<TContext extends Record<string, any> = object>(callback: HookCallback<TContext>): Hook<TContext>;
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
type StepDefinitionCallback<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined> = TParamA extends undefined ? (context: TContext) => Promise<void> | void : TParamB extends undefined ? (context: TContext, paramA: TParamA) => Promise<void> | void : TParamC extends undefined ? (context: TContext, paramA: TParamA, paramB: TParamB) => Promise<void> | void : (context: TContext, paramA: TParamA, paramB: TParamB, paramC: TParamC) => Promise<void> | void;
|
|
24
|
+
/**
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
type StepDefinition<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined> = {
|
|
28
|
+
type: 'Context' | 'Action' | 'Outcome';
|
|
29
|
+
text: string;
|
|
30
|
+
callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
declare function Given<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined>(text: string, callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>): StepDefinition<TContext, TParamA, TParamB, TParamC>;
|
|
36
|
+
/**
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
declare function When<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined>(text: string, callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>): StepDefinition<TContext, TParamA, TParamB, TParamC>;
|
|
40
|
+
/**
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
declare function Then<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined>(text: string, callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>): StepDefinition<TContext, TParamA, TParamB, TParamC>;
|
|
44
|
+
export { After, Before, Given, Hook, HookCallback, StepDefinition, StepDefinitionCallback, Then, When };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @public
|
|
3
|
+
*/
|
|
4
|
+
type Hook<TContext extends Record<string, any> = object> = {
|
|
5
|
+
type: 'Before' | 'After';
|
|
6
|
+
callback: HookCallback<TContext>;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
type HookCallback<TContext extends Record<string, any> = object> = (context: TContext) => Promise<void> | void;
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
declare function Before<TContext extends Record<string, any> = object>(callback: HookCallback<TContext>): Hook<TContext>;
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
declare function After<TContext extends Record<string, any> = object>(callback: HookCallback<TContext>): Hook<TContext>;
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
type StepDefinitionCallback<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined> = TParamA extends undefined ? (context: TContext) => Promise<void> | void : TParamB extends undefined ? (context: TContext, paramA: TParamA) => Promise<void> | void : TParamC extends undefined ? (context: TContext, paramA: TParamA, paramB: TParamB) => Promise<void> | void : (context: TContext, paramA: TParamA, paramB: TParamB, paramC: TParamC) => Promise<void> | void;
|
|
24
|
+
/**
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
type StepDefinition<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined> = {
|
|
28
|
+
type: 'Context' | 'Action' | 'Outcome';
|
|
29
|
+
text: string;
|
|
30
|
+
callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
declare function Given<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined>(text: string, callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>): StepDefinition<TContext, TParamA, TParamB, TParamC>;
|
|
36
|
+
/**
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
declare function When<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined>(text: string, callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>): StepDefinition<TContext, TParamA, TParamB, TParamC>;
|
|
40
|
+
/**
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
declare function Then<TContext extends Record<string, any> = object, TParamA = undefined, TParamB = undefined, TParamC = undefined>(text: string, callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>): StepDefinition<TContext, TParamA, TParamB, TParamC>;
|
|
44
|
+
export { After, Before, Given, Hook, HookCallback, StepDefinition, StepDefinitionCallback, Then, When };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { ParameterTypeRegistry, CucumberExpression } from "@cucumber/cucumber-expressions";
|
|
2
|
+
import * as Gherkin from "@cucumber/gherkin";
|
|
3
|
+
import * as Messages from "@cucumber/messages";
|
|
4
|
+
function compileFeature({
|
|
5
|
+
featureText,
|
|
6
|
+
hooks,
|
|
7
|
+
stepDefinitions,
|
|
8
|
+
parameterTypes
|
|
9
|
+
}) {
|
|
10
|
+
const uuidFn = Messages.IdGenerator.uuid(), builder = new Gherkin.AstBuilder(uuidFn), matcher = new Gherkin.GherkinClassicTokenMatcher(), gherkinDocument = new Gherkin.Parser(builder, matcher).parse(featureText), pickles = Gherkin.compile(
|
|
11
|
+
gherkinDocument,
|
|
12
|
+
(gherkinDocument.feature?.name ?? "").replace(" ", "-"),
|
|
13
|
+
uuidFn
|
|
14
|
+
), parameterTypeRegistry = new ParameterTypeRegistry();
|
|
15
|
+
if (parameterTypes && parameterTypes.forEach((parameterType) => {
|
|
16
|
+
parameterTypeRegistry.defineParameterType(parameterType);
|
|
17
|
+
}), !gherkinDocument.feature)
|
|
18
|
+
throw new Error("No feature found");
|
|
19
|
+
const stepImplementations = stepDefinitions.map((stepDefinition) => {
|
|
20
|
+
const expression = new CucumberExpression(
|
|
21
|
+
stepDefinition.text,
|
|
22
|
+
parameterTypeRegistry
|
|
23
|
+
);
|
|
24
|
+
return {
|
|
25
|
+
type: stepDefinition.type,
|
|
26
|
+
text: stepDefinition.text,
|
|
27
|
+
expression,
|
|
28
|
+
callback: stepDefinition.callback
|
|
29
|
+
};
|
|
30
|
+
}), skippedFeature = gherkinDocument.feature.tags.some(
|
|
31
|
+
(tag) => tag.name === "@skip"
|
|
32
|
+
), onlyFeature = gherkinDocument.feature.tags.some(
|
|
33
|
+
(tag) => tag.name === "@only"
|
|
34
|
+
);
|
|
35
|
+
if (skippedFeature && onlyFeature)
|
|
36
|
+
throw new Error("Feature cannot have both @skip and @only tags");
|
|
37
|
+
let context = {};
|
|
38
|
+
const scenarios = pickles.map((pickle) => {
|
|
39
|
+
const skippedPickle = pickle.tags.some((tag) => tag.name === "@skip"), onlyPickle = pickle.tags.some((tag) => tag.name === "@only");
|
|
40
|
+
context = {};
|
|
41
|
+
const steps = pickle.steps.map((step) => {
|
|
42
|
+
const matchingSteps = stepImplementations.filter((stepImplementation) => stepImplementation.type === step.type).flatMap((stepImplementation) => {
|
|
43
|
+
const args2 = stepImplementation.expression.match(step.text);
|
|
44
|
+
return args2 ? [
|
|
45
|
+
{
|
|
46
|
+
...stepImplementation,
|
|
47
|
+
args: args2
|
|
48
|
+
}
|
|
49
|
+
] : [];
|
|
50
|
+
}), matchingStep = matchingSteps[0];
|
|
51
|
+
if (!matchingStep)
|
|
52
|
+
throw new Error(`No implementation found for step: ${step.text}`);
|
|
53
|
+
if (matchingSteps.length > 1)
|
|
54
|
+
throw new Error(`Multiple implementations found for step: ${step.text}`);
|
|
55
|
+
const args = matchingStep.args.map((arg) => arg.getValue(matchingStep));
|
|
56
|
+
return step.argument?.dataTable && args.push(
|
|
57
|
+
step.argument.dataTable.rows.map(
|
|
58
|
+
(row) => row.cells.map((cell) => cell.value)
|
|
59
|
+
)
|
|
60
|
+
), step.argument?.docString && args.push(step.argument.docString.content), (stepContext) => matchingStep.callback(
|
|
61
|
+
Object.assign(context, stepContext),
|
|
62
|
+
args[0],
|
|
63
|
+
args[1],
|
|
64
|
+
args[2]
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
name: pickle.name,
|
|
69
|
+
tag: skippedFeature || skippedPickle ? "skip" : onlyPickle ? "only" : void 0,
|
|
70
|
+
steps
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
return {
|
|
74
|
+
tag: skippedFeature ? "skip" : onlyFeature ? "only" : void 0,
|
|
75
|
+
name: gherkinDocument.feature.name,
|
|
76
|
+
scenarios,
|
|
77
|
+
beforeHooks: (hooks ?? []).filter((hook) => hook.type === "Before").map(
|
|
78
|
+
(hook) => (stepContext) => hook.callback(Object.assign(context, stepContext))
|
|
79
|
+
),
|
|
80
|
+
afterHooks: (hooks ?? []).filter((hook) => hook.type === "After").map(
|
|
81
|
+
(hook) => (stepContext) => hook.callback(Object.assign(context, stepContext))
|
|
82
|
+
)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
compileFeature
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=compile-feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-feature.js","sources":["../../src/compile-feature.ts"],"sourcesContent":["import type {ParameterType} from '@cucumber/cucumber-expressions'\nimport {\n CucumberExpression,\n ParameterTypeRegistry,\n} from '@cucumber/cucumber-expressions'\nimport * as Gherkin from '@cucumber/gherkin'\nimport * as Messages from '@cucumber/messages'\nimport type {Hook} from './hooks'\nimport type {StepDefinition} from './step-definitions'\n\n/**\n * @public\n */\nexport type CompiledFeature<TStepContext extends Record<string, any> = object> =\n {\n name: string\n tag: 'only' | 'skip' | undefined\n scenarios: Array<{\n name: string\n tag: 'only' | 'skip' | undefined\n steps: Array<(stepContext?: TStepContext) => Promise<void> | void>\n }>\n beforeHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>\n afterHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>\n }\n\n/**\n * @public\n */\nexport function compileFeature<\n TContext extends Record<string, any> = object,\n TStepContext extends Record<string, any> = object,\n>({\n featureText,\n hooks,\n stepDefinitions,\n parameterTypes,\n}: {\n featureText: string\n hooks?: Array<Hook<TStepContext>>\n stepDefinitions: Array<StepDefinition<TContext, any, any, any>>\n parameterTypes?: Array<ParameterType<unknown>>\n}): CompiledFeature<TStepContext> {\n const uuidFn = Messages.IdGenerator.uuid()\n const builder = new Gherkin.AstBuilder(uuidFn)\n const matcher = new Gherkin.GherkinClassicTokenMatcher()\n const parser = new Gherkin.Parser(builder, matcher)\n\n const gherkinDocument = parser.parse(featureText)\n const pickles = Gherkin.compile(\n gherkinDocument,\n (gherkinDocument.feature?.name ?? '').replace(' ', '-'),\n uuidFn,\n )\n\n const parameterTypeRegistry = new ParameterTypeRegistry()\n if (parameterTypes) {\n parameterTypes.forEach((parameterType) => {\n parameterTypeRegistry.defineParameterType(parameterType)\n })\n }\n\n if (!gherkinDocument.feature) {\n throw new Error('No feature found')\n }\n\n const stepImplementations = stepDefinitions.map((stepDefinition) => {\n const expression = new CucumberExpression(\n stepDefinition.text,\n parameterTypeRegistry,\n )\n\n return {\n type: stepDefinition.type,\n text: stepDefinition.text,\n expression,\n callback: stepDefinition.callback,\n }\n })\n\n const skippedFeature = gherkinDocument.feature.tags.some(\n (tag) => tag.name === '@skip',\n )\n const onlyFeature = gherkinDocument.feature.tags.some(\n (tag) => tag.name === '@only',\n )\n\n if (skippedFeature && onlyFeature) {\n throw new Error('Feature cannot have both @skip and @only tags')\n }\n\n let context = {} as TContext\n\n const scenarios = pickles.map((pickle) => {\n const skippedPickle = pickle.tags.some((tag) => tag.name === '@skip')\n const onlyPickle = pickle.tags.some((tag) => tag.name === '@only')\n context = {} as TContext\n\n const steps = pickle.steps.map((step) => {\n const matchingSteps = stepImplementations\n .filter((stepImplementation) => stepImplementation.type === step.type)\n .flatMap((stepImplementation) => {\n const args = stepImplementation.expression.match(step.text)\n\n if (args) {\n return [\n {\n ...stepImplementation,\n args,\n },\n ]\n }\n\n return []\n })\n\n const matchingStep = matchingSteps[0]\n\n if (!matchingStep) {\n throw new Error(`No implementation found for step: ${step.text}`)\n }\n\n if (matchingSteps.length > 1) {\n throw new Error(`Multiple implementations found for step: ${step.text}`)\n }\n\n const args = matchingStep.args.map((arg) => arg.getValue(matchingStep))\n if (step.argument?.dataTable) {\n args.push(\n step.argument.dataTable.rows.map((row) =>\n row.cells.map((cell) => cell.value),\n ),\n )\n }\n if (step.argument?.docString) {\n args.push(step.argument.docString.content)\n }\n\n return (stepContext: TStepContext | undefined) =>\n matchingStep.callback(\n Object.assign(context, stepContext),\n args[0],\n args[1],\n args[2],\n )\n })\n\n return {\n name: pickle.name,\n tag: skippedFeature\n ? ('skip' as const)\n : skippedPickle\n ? ('skip' as const)\n : onlyPickle\n ? ('only' as const)\n : undefined,\n steps,\n }\n })\n\n return {\n tag: skippedFeature ? 'skip' : onlyFeature ? 'only' : undefined,\n name: gherkinDocument.feature.name,\n scenarios,\n beforeHooks: (hooks ?? [])\n .filter((hook) => hook.type === 'Before')\n .map(\n (hook) => (stepContext: TStepContext | undefined) =>\n hook.callback(Object.assign(context, stepContext)),\n ),\n afterHooks: (hooks ?? [])\n .filter((hook) => hook.type === 'After')\n .map(\n (hook) => (stepContext: TStepContext | undefined) =>\n hook.callback(Object.assign(context, stepContext)),\n ),\n }\n}\n"],"names":["args"],"mappings":"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"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
3
|
+
var compileFeature = require("./_chunks-cjs/compile-feature.cjs"), cucumberExpressions = require("@cucumber/cucumber-expressions");
|
|
4
|
+
function createParameterType(config) {
|
|
5
|
+
return new cucumberExpressions.ParameterType(
|
|
6
|
+
config.name,
|
|
7
|
+
config.matcher,
|
|
8
|
+
config.type ?? String,
|
|
9
|
+
config.transform,
|
|
10
|
+
!1,
|
|
11
|
+
!0
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
function Given(text, callback) {
|
|
15
|
+
return { type: "Context", text, callback };
|
|
16
|
+
}
|
|
17
|
+
function When(text, callback) {
|
|
18
|
+
return { type: "Action", text, callback };
|
|
19
|
+
}
|
|
20
|
+
function Then(text, callback) {
|
|
21
|
+
return { type: "Outcome", text, callback };
|
|
22
|
+
}
|
|
23
|
+
function Before(callback) {
|
|
24
|
+
return { type: "Before", callback };
|
|
25
|
+
}
|
|
26
|
+
function After(callback) {
|
|
27
|
+
return { type: "After", callback };
|
|
28
|
+
}
|
|
29
|
+
exports.compileFeature = compileFeature.compileFeature;
|
|
30
|
+
exports.After = After;
|
|
31
|
+
exports.Before = Before;
|
|
32
|
+
exports.Given = Given;
|
|
33
|
+
exports.Then = Then;
|
|
34
|
+
exports.When = When;
|
|
35
|
+
exports.createParameterType = createParameterType;
|
|
36
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/create-parameter-type.ts","../src/step-definitions.ts","../src/hooks.ts"],"sourcesContent":["import {ParameterType, type RegExps} from '@cucumber/cucumber-expressions'\n\n/**\n * @public\n */\nexport type ParameterTypeConfig<TType = string> = {\n readonly name: string\n matcher: RegExps\n type?: (...args: unknown[]) => TType\n transform?: (...match: string[]) => TType\n}\n\nexport type {ParameterType}\n\n/**\n * @public\n */\nexport function createParameterType<TType = string>(\n config: ParameterTypeConfig<TType>,\n): ParameterType<TType> {\n return new ParameterType(\n config.name,\n config.matcher,\n config.type ?? String,\n config.transform,\n false,\n true,\n )\n}\n","/**\n * @public\n */\nexport type StepDefinitionCallback<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n> = TParamA extends undefined\n ? (context: TContext) => Promise<void> | void\n : TParamB extends undefined\n ? (context: TContext, paramA: TParamA) => Promise<void> | void\n : TParamC extends undefined\n ? (\n context: TContext,\n paramA: TParamA,\n paramB: TParamB,\n ) => Promise<void> | void\n : (\n context: TContext,\n paramA: TParamA,\n paramB: TParamB,\n paramC: TParamC,\n ) => Promise<void> | void\n\n/**\n * @public\n */\nexport type StepDefinition<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n> = {\n type: 'Context' | 'Action' | 'Outcome'\n text: string\n callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>\n}\n\n/**\n * @public\n */\nexport function Given<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n>(\n text: string,\n callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>,\n): StepDefinition<TContext, TParamA, TParamB, TParamC> {\n return {type: 'Context', text, callback}\n}\n\n/**\n * @public\n */\nexport function When<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n>(\n text: string,\n callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>,\n): StepDefinition<TContext, TParamA, TParamB, TParamC> {\n return {type: 'Action', text, callback}\n}\n\n/**\n * @public\n */\nexport function Then<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n>(\n text: string,\n callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>,\n): StepDefinition<TContext, TParamA, TParamB, TParamC> {\n return {type: 'Outcome', text, callback}\n}\n","/**\n * @public\n */\nexport type Hook<TContext extends Record<string, any> = object> = {\n type: 'Before' | 'After'\n callback: HookCallback<TContext>\n}\n\n/**\n * @public\n */\nexport type HookCallback<TContext extends Record<string, any> = object> = (\n context: TContext,\n) => Promise<void> | void\n\n/**\n * @public\n */\nexport function Before<TContext extends Record<string, any> = object>(\n callback: HookCallback<TContext>,\n): Hook<TContext> {\n return {type: 'Before', callback}\n}\n\n/**\n * @public\n */\nexport function After<TContext extends Record<string, any> = object>(\n callback: HookCallback<TContext>,\n): Hook<TContext> {\n return {type: 'After', callback}\n}\n"],"names":["ParameterType"],"mappings":";;;AAiBO,SAAS,oBACd,QACsB;AACtB,SAAO,IAAIA,oBAAAA;AAAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO,QAAQ;AAAA,IACf,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA;AAEJ;ACcO,SAAS,MAMd,MACA,UACqD;AACrD,SAAO,EAAC,MAAM,WAAW,MAAM,SAAA;AACjC;AAKO,SAAS,KAMd,MACA,UACqD;AACrD,SAAO,EAAC,MAAM,UAAU,MAAM,SAAA;AAChC;AAKO,SAAS,KAMd,MACA,UACqD;AACrD,SAAO,EAAC,MAAM,WAAW,MAAM,SAAA;AACjC;AChEO,SAAS,OACd,UACgB;AAChB,SAAO,EAAC,MAAM,UAAU,SAAA;AAC1B;AAKO,SAAS,MACd,UACgB;AAChB,SAAO,EAAC,MAAM,SAAS,SAAA;AACzB;;;;;;;;"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { After, Before, Given, Hook, HookCallback, StepDefinition, StepDefinitionCallback, Then, When } from "./_chunks-dts/step-definitions.cjs";
|
|
2
|
+
import { ParameterType, ParameterType as ParameterType$1, RegExps } from "@cucumber/cucumber-expressions";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
type CompiledFeature<TStepContext extends Record<string, any> = object> = {
|
|
7
|
+
name: string;
|
|
8
|
+
tag: 'only' | 'skip' | undefined;
|
|
9
|
+
scenarios: Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
tag: 'only' | 'skip' | undefined;
|
|
12
|
+
steps: Array<(stepContext?: TStepContext) => Promise<void> | void>;
|
|
13
|
+
}>;
|
|
14
|
+
beforeHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>;
|
|
15
|
+
afterHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
declare function compileFeature<TContext extends Record<string, any> = object, TStepContext extends Record<string, any> = object>({
|
|
21
|
+
featureText,
|
|
22
|
+
hooks,
|
|
23
|
+
stepDefinitions,
|
|
24
|
+
parameterTypes
|
|
25
|
+
}: {
|
|
26
|
+
featureText: string;
|
|
27
|
+
hooks?: Array<Hook<TStepContext>>;
|
|
28
|
+
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>;
|
|
29
|
+
parameterTypes?: Array<ParameterType$1<unknown>>;
|
|
30
|
+
}): CompiledFeature<TStepContext>;
|
|
31
|
+
/**
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
type ParameterTypeConfig<TType = string> = {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
matcher: RegExps;
|
|
37
|
+
type?: (...args: unknown[]) => TType;
|
|
38
|
+
transform?: (...match: string[]) => TType;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
declare function createParameterType<TType = string>(config: ParameterTypeConfig<TType>): ParameterType<TType>;
|
|
44
|
+
export { After, Before, CompiledFeature, Given, Hook, HookCallback, type ParameterType, ParameterTypeConfig, StepDefinition, StepDefinitionCallback, Then, When, compileFeature, createParameterType };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { After, Before, Given, Hook, HookCallback, StepDefinition, StepDefinitionCallback, Then, When } from "./_chunks-dts/step-definitions.js";
|
|
2
|
+
import { ParameterType, ParameterType as ParameterType$1, RegExps } from "@cucumber/cucumber-expressions";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
type CompiledFeature<TStepContext extends Record<string, any> = object> = {
|
|
7
|
+
name: string;
|
|
8
|
+
tag: 'only' | 'skip' | undefined;
|
|
9
|
+
scenarios: Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
tag: 'only' | 'skip' | undefined;
|
|
12
|
+
steps: Array<(stepContext?: TStepContext) => Promise<void> | void>;
|
|
13
|
+
}>;
|
|
14
|
+
beforeHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>;
|
|
15
|
+
afterHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
declare function compileFeature<TContext extends Record<string, any> = object, TStepContext extends Record<string, any> = object>({
|
|
21
|
+
featureText,
|
|
22
|
+
hooks,
|
|
23
|
+
stepDefinitions,
|
|
24
|
+
parameterTypes
|
|
25
|
+
}: {
|
|
26
|
+
featureText: string;
|
|
27
|
+
hooks?: Array<Hook<TStepContext>>;
|
|
28
|
+
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>;
|
|
29
|
+
parameterTypes?: Array<ParameterType$1<unknown>>;
|
|
30
|
+
}): CompiledFeature<TStepContext>;
|
|
31
|
+
/**
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
type ParameterTypeConfig<TType = string> = {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
matcher: RegExps;
|
|
37
|
+
type?: (...args: unknown[]) => TType;
|
|
38
|
+
transform?: (...match: string[]) => TType;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
declare function createParameterType<TType = string>(config: ParameterTypeConfig<TType>): ParameterType<TType>;
|
|
44
|
+
export { After, Before, CompiledFeature, Given, Hook, HookCallback, type ParameterType, ParameterTypeConfig, StepDefinition, StepDefinitionCallback, Then, When, compileFeature, createParameterType };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { compileFeature } from "./_chunks-es/compile-feature.js";
|
|
2
|
+
import { ParameterType } from "@cucumber/cucumber-expressions";
|
|
3
|
+
function createParameterType(config) {
|
|
4
|
+
return new ParameterType(
|
|
5
|
+
config.name,
|
|
6
|
+
config.matcher,
|
|
7
|
+
config.type ?? String,
|
|
8
|
+
config.transform,
|
|
9
|
+
!1,
|
|
10
|
+
!0
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
function Given(text, callback) {
|
|
14
|
+
return { type: "Context", text, callback };
|
|
15
|
+
}
|
|
16
|
+
function When(text, callback) {
|
|
17
|
+
return { type: "Action", text, callback };
|
|
18
|
+
}
|
|
19
|
+
function Then(text, callback) {
|
|
20
|
+
return { type: "Outcome", text, callback };
|
|
21
|
+
}
|
|
22
|
+
function Before(callback) {
|
|
23
|
+
return { type: "Before", callback };
|
|
24
|
+
}
|
|
25
|
+
function After(callback) {
|
|
26
|
+
return { type: "After", callback };
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
After,
|
|
30
|
+
Before,
|
|
31
|
+
Given,
|
|
32
|
+
Then,
|
|
33
|
+
When,
|
|
34
|
+
compileFeature,
|
|
35
|
+
createParameterType
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/create-parameter-type.ts","../src/step-definitions.ts","../src/hooks.ts"],"sourcesContent":["import {ParameterType, type RegExps} from '@cucumber/cucumber-expressions'\n\n/**\n * @public\n */\nexport type ParameterTypeConfig<TType = string> = {\n readonly name: string\n matcher: RegExps\n type?: (...args: unknown[]) => TType\n transform?: (...match: string[]) => TType\n}\n\nexport type {ParameterType}\n\n/**\n * @public\n */\nexport function createParameterType<TType = string>(\n config: ParameterTypeConfig<TType>,\n): ParameterType<TType> {\n return new ParameterType(\n config.name,\n config.matcher,\n config.type ?? String,\n config.transform,\n false,\n true,\n )\n}\n","/**\n * @public\n */\nexport type StepDefinitionCallback<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n> = TParamA extends undefined\n ? (context: TContext) => Promise<void> | void\n : TParamB extends undefined\n ? (context: TContext, paramA: TParamA) => Promise<void> | void\n : TParamC extends undefined\n ? (\n context: TContext,\n paramA: TParamA,\n paramB: TParamB,\n ) => Promise<void> | void\n : (\n context: TContext,\n paramA: TParamA,\n paramB: TParamB,\n paramC: TParamC,\n ) => Promise<void> | void\n\n/**\n * @public\n */\nexport type StepDefinition<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n> = {\n type: 'Context' | 'Action' | 'Outcome'\n text: string\n callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>\n}\n\n/**\n * @public\n */\nexport function Given<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n>(\n text: string,\n callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>,\n): StepDefinition<TContext, TParamA, TParamB, TParamC> {\n return {type: 'Context', text, callback}\n}\n\n/**\n * @public\n */\nexport function When<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n>(\n text: string,\n callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>,\n): StepDefinition<TContext, TParamA, TParamB, TParamC> {\n return {type: 'Action', text, callback}\n}\n\n/**\n * @public\n */\nexport function Then<\n TContext extends Record<string, any> = object,\n TParamA = undefined,\n TParamB = undefined,\n TParamC = undefined,\n>(\n text: string,\n callback: StepDefinitionCallback<TContext, TParamA, TParamB, TParamC>,\n): StepDefinition<TContext, TParamA, TParamB, TParamC> {\n return {type: 'Outcome', text, callback}\n}\n","/**\n * @public\n */\nexport type Hook<TContext extends Record<string, any> = object> = {\n type: 'Before' | 'After'\n callback: HookCallback<TContext>\n}\n\n/**\n * @public\n */\nexport type HookCallback<TContext extends Record<string, any> = object> = (\n context: TContext,\n) => Promise<void> | void\n\n/**\n * @public\n */\nexport function Before<TContext extends Record<string, any> = object>(\n callback: HookCallback<TContext>,\n): Hook<TContext> {\n return {type: 'Before', callback}\n}\n\n/**\n * @public\n */\nexport function After<TContext extends Record<string, any> = object>(\n callback: HookCallback<TContext>,\n): Hook<TContext> {\n return {type: 'After', callback}\n}\n"],"names":[],"mappings":";;AAiBO,SAAS,oBACd,QACsB;AACtB,SAAO,IAAI;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO,QAAQ;AAAA,IACf,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA;AAEJ;ACcO,SAAS,MAMd,MACA,UACqD;AACrD,SAAO,EAAC,MAAM,WAAW,MAAM,SAAA;AACjC;AAKO,SAAS,KAMd,MACA,UACqD;AACrD,SAAO,EAAC,MAAM,UAAU,MAAM,SAAA;AAChC;AAKO,SAAS,KAMd,MACA,UACqD;AACrD,SAAO,EAAC,MAAM,WAAW,MAAM,SAAA;AACjC;AChEO,SAAS,OACd,UACgB;AAChB,SAAO,EAAC,MAAM,UAAU,SAAA;AAC1B;AAKO,SAAS,MACd,UACgB;AAChB,SAAO,EAAC,MAAM,SAAS,SAAA;AACzB;"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
3
|
+
var globals = require("@jest/globals"), compileFeature = require("../_chunks-cjs/compile-feature.cjs");
|
|
4
|
+
function Feature({
|
|
5
|
+
featureText,
|
|
6
|
+
hooks,
|
|
7
|
+
stepDefinitions,
|
|
8
|
+
parameterTypes
|
|
9
|
+
}) {
|
|
10
|
+
const feature = compileFeature.compileFeature({
|
|
11
|
+
featureText,
|
|
12
|
+
hooks: hooks ?? [],
|
|
13
|
+
stepDefinitions,
|
|
14
|
+
parameterTypes: parameterTypes ?? []
|
|
15
|
+
});
|
|
16
|
+
(feature.tag === "only" ? globals.describe.only : feature.tag === "skip" ? globals.describe.skip : globals.describe)(feature.name, () => {
|
|
17
|
+
for (const before of feature.beforeHooks)
|
|
18
|
+
globals.beforeEach(before);
|
|
19
|
+
for (const after of feature.afterHooks)
|
|
20
|
+
globals.afterEach(after);
|
|
21
|
+
for (const scenario of feature.scenarios)
|
|
22
|
+
(scenario.tag === "only" ? globals.test.only : scenario.tag === "skip" ? globals.test.skip : globals.test)(scenario.name, async () => {
|
|
23
|
+
for (const step of scenario.steps)
|
|
24
|
+
await step();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
exports.Feature = Feature;
|
|
29
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/jest/jest-gherkin-driver.ts"],"sourcesContent":["import type {ParameterType} from '@cucumber/cucumber-expressions'\nimport {afterEach, beforeEach, describe, test} from '@jest/globals'\nimport {compileFeature} from '../compile-feature'\nimport type {Hook} from '../hooks'\nimport type {StepDefinition} from '../step-definitions'\n\n/**\n * @public\n */\nexport function Feature<TContext extends Record<string, any> = object>({\n featureText,\n hooks,\n stepDefinitions,\n parameterTypes,\n}: {\n featureText: string\n hooks: Array<Hook<TContext>>\n stepDefinitions: Array<StepDefinition<TContext, any, any, any>>\n parameterTypes?: Array<ParameterType<unknown>>\n}) {\n const feature = compileFeature({\n featureText,\n hooks: hooks ?? [],\n stepDefinitions,\n parameterTypes: parameterTypes ?? [],\n })\n\n const describeFn =\n feature.tag === 'only'\n ? describe.only\n : feature.tag === 'skip'\n ? describe.skip\n : describe\n\n describeFn(feature.name, () => {\n for (const before of feature.beforeHooks) {\n beforeEach(before)\n }\n\n for (const after of feature.afterHooks) {\n afterEach(after)\n }\n\n for (const scenario of feature.scenarios) {\n const testFn =\n scenario.tag === 'only'\n ? test.only\n : scenario.tag === 'skip'\n ? test.skip\n : test\n\n testFn(scenario.name, async () => {\n for (const step of scenario.steps) {\n await step()\n }\n })\n }\n })\n}\n"],"names":["compileFeature","describe","beforeEach","afterEach","test"],"mappings":";;;AASO,SAAS,QAAuD;AAAA,EACrE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,UAAUA,eAAAA,eAAe;AAAA,IAC7B;AAAA,IACA,OAAO,SAAS,CAAA;AAAA,IAChB;AAAA,IACA,gBAAgB,kBAAkB,CAAA;AAAA,EAAC,CACpC;AASD,GANE,QAAQ,QAAQ,SACZC,QAAAA,SAAS,OACT,QAAQ,QAAQ,SACdA,QAAAA,SAAS,OACTA,QAAAA,UAEG,QAAQ,MAAM,MAAM;AAC7B,eAAW,UAAU,QAAQ;AAC3BC,cAAAA,WAAW,MAAM;AAGnB,eAAW,SAAS,QAAQ;AAC1BC,cAAAA,UAAU,KAAK;AAGjB,eAAW,YAAY,QAAQ;AAQ7B,OANE,SAAS,QAAQ,SACbC,QAAAA,KAAK,OACL,SAAS,QAAQ,SACfA,QAAAA,KAAK,OACLA,QAAAA,MAED,SAAS,MAAM,YAAY;AAChC,mBAAW,QAAQ,SAAS;AAC1B,gBAAM,KAAA;AAAA,MAEV,CAAC;AAAA,EAEL,CAAC;AACH;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Hook, StepDefinition } from "../_chunks-dts/step-definitions.cjs";
|
|
2
|
+
import { ParameterType } from "@cucumber/cucumber-expressions";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
declare function Feature<TContext extends Record<string, any> = object>({
|
|
7
|
+
featureText,
|
|
8
|
+
hooks,
|
|
9
|
+
stepDefinitions,
|
|
10
|
+
parameterTypes
|
|
11
|
+
}: {
|
|
12
|
+
featureText: string;
|
|
13
|
+
hooks: Array<Hook<TContext>>;
|
|
14
|
+
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>;
|
|
15
|
+
parameterTypes?: Array<ParameterType<unknown>>;
|
|
16
|
+
}): void;
|
|
17
|
+
export { Feature };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Hook, StepDefinition } from "../_chunks-dts/step-definitions.js";
|
|
2
|
+
import { ParameterType } from "@cucumber/cucumber-expressions";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
declare function Feature<TContext extends Record<string, any> = object>({
|
|
7
|
+
featureText,
|
|
8
|
+
hooks,
|
|
9
|
+
stepDefinitions,
|
|
10
|
+
parameterTypes
|
|
11
|
+
}: {
|
|
12
|
+
featureText: string;
|
|
13
|
+
hooks: Array<Hook<TContext>>;
|
|
14
|
+
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>;
|
|
15
|
+
parameterTypes?: Array<ParameterType<unknown>>;
|
|
16
|
+
}): void;
|
|
17
|
+
export { Feature };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, beforeEach, afterEach, test } from "@jest/globals";
|
|
2
|
+
import { compileFeature } from "../_chunks-es/compile-feature.js";
|
|
3
|
+
function Feature({
|
|
4
|
+
featureText,
|
|
5
|
+
hooks,
|
|
6
|
+
stepDefinitions,
|
|
7
|
+
parameterTypes
|
|
8
|
+
}) {
|
|
9
|
+
const feature = compileFeature({
|
|
10
|
+
featureText,
|
|
11
|
+
hooks: hooks ?? [],
|
|
12
|
+
stepDefinitions,
|
|
13
|
+
parameterTypes: parameterTypes ?? []
|
|
14
|
+
});
|
|
15
|
+
(feature.tag === "only" ? describe.only : feature.tag === "skip" ? describe.skip : describe)(feature.name, () => {
|
|
16
|
+
for (const before of feature.beforeHooks)
|
|
17
|
+
beforeEach(before);
|
|
18
|
+
for (const after of feature.afterHooks)
|
|
19
|
+
afterEach(after);
|
|
20
|
+
for (const scenario of feature.scenarios)
|
|
21
|
+
(scenario.tag === "only" ? test.only : scenario.tag === "skip" ? test.skip : test)(scenario.name, async () => {
|
|
22
|
+
for (const step of scenario.steps)
|
|
23
|
+
await step();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
Feature
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/jest/jest-gherkin-driver.ts"],"sourcesContent":["import type {ParameterType} from '@cucumber/cucumber-expressions'\nimport {afterEach, beforeEach, describe, test} from '@jest/globals'\nimport {compileFeature} from '../compile-feature'\nimport type {Hook} from '../hooks'\nimport type {StepDefinition} from '../step-definitions'\n\n/**\n * @public\n */\nexport function Feature<TContext extends Record<string, any> = object>({\n featureText,\n hooks,\n stepDefinitions,\n parameterTypes,\n}: {\n featureText: string\n hooks: Array<Hook<TContext>>\n stepDefinitions: Array<StepDefinition<TContext, any, any, any>>\n parameterTypes?: Array<ParameterType<unknown>>\n}) {\n const feature = compileFeature({\n featureText,\n hooks: hooks ?? [],\n stepDefinitions,\n parameterTypes: parameterTypes ?? [],\n })\n\n const describeFn =\n feature.tag === 'only'\n ? describe.only\n : feature.tag === 'skip'\n ? describe.skip\n : describe\n\n describeFn(feature.name, () => {\n for (const before of feature.beforeHooks) {\n beforeEach(before)\n }\n\n for (const after of feature.afterHooks) {\n afterEach(after)\n }\n\n for (const scenario of feature.scenarios) {\n const testFn =\n scenario.tag === 'only'\n ? test.only\n : scenario.tag === 'skip'\n ? test.skip\n : test\n\n testFn(scenario.name, async () => {\n for (const step of scenario.steps) {\n await step()\n }\n })\n }\n })\n}\n"],"names":[],"mappings":";;AASO,SAAS,QAAuD;AAAA,EACrE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,UAAU,eAAe;AAAA,IAC7B;AAAA,IACA,OAAO,SAAS,CAAA;AAAA,IAChB;AAAA,IACA,gBAAgB,kBAAkB,CAAA;AAAA,EAAC,CACpC;AASD,GANE,QAAQ,QAAQ,SACZ,SAAS,OACT,QAAQ,QAAQ,SACd,SAAS,OACT,UAEG,QAAQ,MAAM,MAAM;AAC7B,eAAW,UAAU,QAAQ;AAC3B,iBAAW,MAAM;AAGnB,eAAW,SAAS,QAAQ;AAC1B,gBAAU,KAAK;AAGjB,eAAW,YAAY,QAAQ;AAQ7B,OANE,SAAS,QAAQ,SACb,KAAK,OACL,SAAS,QAAQ,SACf,KAAK,OACL,MAED,SAAS,MAAM,YAAY;AAChC,mBAAW,QAAQ,SAAS;AAC1B,gBAAM,KAAA;AAAA,MAEV,CAAC;AAAA,EAEL,CAAC;AACH;"}
|