@vr1/be-driven-syntax-sugar 1.0.0 → 2.0.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/build/scenario.d.ts +3 -2
- package/build/scenario.js +4 -2
- package/build/scenario.js.map +1 -1
- package/build/testScenario/ScenarioSteps.d.ts +10 -0
- package/build/testScenario/ScenarioSteps.js +47 -0
- package/build/testScenario/ScenarioSteps.js.map +1 -0
- package/build/testScenario/TestScenario.d.ts +7 -11
- package/build/testScenario/TestScenario.js +18 -41
- package/build/testScenario/TestScenario.js.map +1 -1
- package/build/testScenario/TestStep.d.ts +7 -2
- package/build/testScenario/runTest.d.ts +4 -3
- package/build/testScenario/runTest.js +34 -7
- package/build/testScenario/runTest.js.map +1 -1
- package/build/types/ScenarioOptions.d.ts +7 -0
- package/build/types/ScenarioOptions.js +3 -0
- package/build/types/ScenarioOptions.js.map +1 -0
- package/build/types/StepWrapper.d.ts +1 -2
- package/build/types/TestWrapper.d.ts +1 -0
- package/build/types/TestWrapper.js +3 -0
- package/build/types/TestWrapper.js.map +1 -0
- package/build/types/index.d.ts +2 -0
- package/build/types/index.js +2 -0
- package/build/types/index.js.map +1 -1
- package/package.json +4 -2
- package/src/scenario.ts +7 -3
- package/src/testScenario/ScenarioSteps.ts +48 -0
- package/src/testScenario/TestScenario.ts +19 -43
- package/src/testScenario/TestStep.ts +8 -2
- package/src/testScenario/runTest.ts +44 -9
- package/src/types/ScenarioOptions.ts +9 -0
- package/src/types/StepWrapper.ts +1 -3
- package/src/types/TestWrapper.ts +1 -0
- package/src/types/index.ts +2 -0
package/build/scenario.d.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
-
import { StepWrapper } from "./types/StepWrapper";
|
2
1
|
import { ScenarioFirstStep } from "@vr1/be-driven-interface";
|
3
|
-
|
2
|
+
import { ScenarioOptions } from "./types/ScenarioOptions";
|
3
|
+
export declare function scenario(testName: string, options?: ScenarioOptions): ScenarioFirstStep;
|
4
|
+
export declare function scenario(options?: ScenarioOptions): ScenarioFirstStep;
|
package/build/scenario.js
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.scenario = scenario;
|
4
4
|
const testScenario_1 = require("./testScenario");
|
5
|
-
function scenario(
|
6
|
-
|
5
|
+
function scenario(first, second) {
|
6
|
+
const testName = typeof first === "string" ? first : "";
|
7
|
+
const options = (typeof first === "object" ? first : second) ?? {};
|
8
|
+
return new testScenario_1.TestScenario(testName, options);
|
7
9
|
}
|
8
10
|
//# sourceMappingURL=scenario.js.map
|
package/build/scenario.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":";;
|
1
|
+
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":";;AAMA,4BAIC;AAVD,iDAA8C;AAM9C,SAAgB,QAAQ,CAAC,KAAgC,EAAE,MAAwB;IACjF,MAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,MAAM,OAAO,GAAG,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACnE,OAAO,IAAI,2BAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC"}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { Step } from "@vr1/be-driven-interface";
|
2
|
+
import { Test } from "./TestStep";
|
3
|
+
export declare class ScenarioSteps<T extends Step<any>> implements Step<T> {
|
4
|
+
protected test: Test;
|
5
|
+
constructor(test: Test);
|
6
|
+
given<TArgs extends any[], TMnemonic extends (...a: TArgs) => any>(func: TMnemonic, ...args: TArgs): T;
|
7
|
+
when<TArgs extends any[], TMnemonic extends (...a: TArgs) => any>(func: TMnemonic, ...args: TArgs): T;
|
8
|
+
then<TArgs extends any[], TMnemonic extends (...a: TArgs) => any>(func: TMnemonic, ...args: TArgs): T;
|
9
|
+
and<TArgs extends any[], TMnemonic extends (...a: TArgs) => any>(func: TMnemonic, ...args: TArgs): T;
|
10
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.ScenarioSteps = void 0;
|
4
|
+
const be_driven_interface_1 = require("@vr1/be-driven-interface");
|
5
|
+
const function_name_to_sentence_1 = require("@vr1/function-name-to-sentence");
|
6
|
+
class ScenarioSteps {
|
7
|
+
test;
|
8
|
+
constructor(test) {
|
9
|
+
this.test = test;
|
10
|
+
}
|
11
|
+
given(func, ...args) {
|
12
|
+
this.test.steps.push(createStep(func, args, be_driven_interface_1.StepType.Given));
|
13
|
+
return this;
|
14
|
+
}
|
15
|
+
when(func, ...args) {
|
16
|
+
this.test.steps.push(createStep(func, args, be_driven_interface_1.StepType.When));
|
17
|
+
return this;
|
18
|
+
}
|
19
|
+
then(func, ...args) {
|
20
|
+
this.test.steps.push(createStep(func, args, be_driven_interface_1.StepType.Then));
|
21
|
+
return this;
|
22
|
+
}
|
23
|
+
and(func, ...args) {
|
24
|
+
const previousStep = this.test.steps[this.test.steps.length - 1];
|
25
|
+
this.test.steps.push(createStep(func, args, previousStep.stepType, true));
|
26
|
+
return this;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
exports.ScenarioSteps = ScenarioSteps;
|
30
|
+
function createStep(target, args, type, and = false) {
|
31
|
+
const stepType = target.stepType ?? type;
|
32
|
+
if (stepType !== type)
|
33
|
+
throw new Error(`Cannot use ${stepType} type of step, ${type} was expected.`);
|
34
|
+
return {
|
35
|
+
stepName: createName(target, args),
|
36
|
+
target,
|
37
|
+
stepType,
|
38
|
+
args,
|
39
|
+
and
|
40
|
+
};
|
41
|
+
}
|
42
|
+
function createName(target, args) {
|
43
|
+
return (target.stepName != null && target.stepName !== "")
|
44
|
+
? args.reduce((prev, cur, i) => prev.replace(new RegExp(`\\{${i}\\}`, "g"), cur), target.stepName)
|
45
|
+
: (0, function_name_to_sentence_1.functionNameToSentence)(target.name);
|
46
|
+
}
|
47
|
+
//# sourceMappingURL=ScenarioSteps.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ScenarioSteps.js","sourceRoot":"","sources":["../../src/testScenario/ScenarioSteps.ts"],"names":[],"mappings":";;;AAAA,kEAA0D;AAE1D,8EAAwE;AAGxE,MAAa,aAAa;IACF;IAAtB,YAAsB,IAAU;QAAV,SAAI,GAAJ,IAAI,CAAM;IAAI,CAAC;IAE9B,KAAK,CAA8D,IAAe,EAAE,GAAG,IAAW;QACvG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,8BAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7D,OAAO,IAAW,CAAC;IACrB,CAAC;IAEM,IAAI,CAA8D,IAAe,EAAE,GAAG,IAAW;QACtG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,8BAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5D,OAAO,IAAW,CAAC;IACrB,CAAC;IAEM,IAAI,CAA8D,IAAe,EAAE,GAAG,IAAW;QACtG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,8BAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5D,OAAO,IAAW,CAAC;IACrB,CAAC;IAEM,GAAG,CAA8D,IAAe,EAAE,GAAG,IAAW;QACrG,MAAM,YAAY,GAAa,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAa,CAAC;QACvF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1E,OAAO,IAAW,CAAC;IACrB,CAAC;CACF;AAvBD,sCAuBC;AAED,SAAS,UAAU,CAAC,MAAW,EAAE,IAAW,EAAE,IAAc,EAAE,MAAe,KAAK;IAChF,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;IACzC,IAAI,QAAQ,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,cAAc,QAAQ,kBAAkB,IAAI,gBAAgB,CAAC,CAAC;IACrG,OAAO;QACL,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC;QAClC,MAAM;QACN,QAAQ;QACR,IAAI;QACJ,GAAG;KACJ,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,MAAW,EAAE,IAAW;IAC1C,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE,CAAC;QACxD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;QAClG,CAAC,CAAC,IAAA,kDAAsB,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC"}
|
@@ -1,13 +1,9 @@
|
|
1
|
-
import { Scenario } from "@vr1/be-driven-interface";
|
2
|
-
import {
|
3
|
-
|
4
|
-
|
5
|
-
private
|
6
|
-
constructor(
|
7
|
-
|
8
|
-
when<TArgs extends any[], TMnemonic extends (...a: TArgs) => void | Promise<void>>(func: TMnemonic, ...args: TArgs): Scenario;
|
9
|
-
then<TArgs extends any[], TMnemonic extends (...a: TArgs) => void | Promise<void>>(func: TMnemonic, ...args: TArgs): Scenario;
|
10
|
-
and<TArgs extends any[], TMnemonic extends (...a: TArgs) => void | Promise<void>>(func: TMnemonic, ...args: TArgs): Scenario;
|
11
|
-
split(): Scenario;
|
1
|
+
import { Scenario, Variance } from "@vr1/be-driven-interface";
|
2
|
+
import { ScenarioOptions } from "../types/ScenarioOptions";
|
3
|
+
import { ScenarioSteps } from "./ScenarioSteps";
|
4
|
+
export declare class TestScenario extends ScenarioSteps<Scenario> implements Scenario {
|
5
|
+
private options;
|
6
|
+
constructor(testName: string, options: ScenarioOptions);
|
7
|
+
vary(...variance: Variance[]): Scenario;
|
12
8
|
run(): Promise<void>;
|
13
9
|
}
|
@@ -1,52 +1,29 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.TestScenario = void 0;
|
4
|
-
const be_driven_interface_1 = require("@vr1/be-driven-interface");
|
5
4
|
const runTest_1 = require("./runTest");
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
constructor(
|
10
|
-
|
5
|
+
const ScenarioSteps_1 = require("./ScenarioSteps");
|
6
|
+
class TestScenario extends ScenarioSteps_1.ScenarioSteps {
|
7
|
+
options;
|
8
|
+
constructor(testName, options) {
|
9
|
+
super({ testName, steps: [] });
|
10
|
+
this.options = options;
|
11
11
|
}
|
12
|
-
|
13
|
-
|
12
|
+
vary(...variance) {
|
13
|
+
const subTests = variance.map((_, i) => ({ testName: `${i}`, steps: [] }));
|
14
|
+
this.test.steps.push(subTests);
|
15
|
+
variance.forEach((v, i) => v((testName) => {
|
16
|
+
if (typeof (testName) === "string" && testName !== "")
|
17
|
+
subTests[i].testName = testName;
|
18
|
+
return new ScenarioSteps_1.ScenarioSteps(subTests[i]);
|
19
|
+
}));
|
14
20
|
return this;
|
15
21
|
}
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
then(func, ...args) {
|
21
|
-
this.steps.push(createStep(func, args, be_driven_interface_1.StepType.Then));
|
22
|
-
return this;
|
23
|
-
}
|
24
|
-
and(func, ...args) {
|
25
|
-
this.steps.push(createStep(func, args, this.steps[this.steps.length - 1].type));
|
26
|
-
return this;
|
27
|
-
}
|
28
|
-
split() {
|
29
|
-
throw new Error("Splitting test into several tests is not supported in syntax-sugar mode.");
|
30
|
-
}
|
31
|
-
run() {
|
32
|
-
const steps = this.steps;
|
33
|
-
this.steps = null;
|
34
|
-
return (0, runTest_1.runTest)(this.wrapper, steps);
|
22
|
+
async run() {
|
23
|
+
const test = this.test;
|
24
|
+
this.test = null;
|
25
|
+
await Promise.all((0, runTest_1.runTest)(this.options, test));
|
35
26
|
}
|
36
27
|
}
|
37
28
|
exports.TestScenario = TestScenario;
|
38
|
-
function createStep(target, args, type) {
|
39
|
-
const stepType = target.stepType ?? type;
|
40
|
-
if (stepType !== type)
|
41
|
-
throw new Error(`Cannot use ${stepType} type of step, ${type} was expected.`);
|
42
|
-
return {
|
43
|
-
name: createName(target, args),
|
44
|
-
target,
|
45
|
-
type,
|
46
|
-
args,
|
47
|
-
};
|
48
|
-
}
|
49
|
-
function createName(target, args) {
|
50
|
-
return args.reduce((prev, cur, i) => prev.replace(new RegExp(`\\{${i}\\}`, "g"), cur), target.stepName ?? target.name);
|
51
|
-
}
|
52
29
|
//# sourceMappingURL=TestScenario.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"TestScenario.js","sourceRoot":"","sources":["../../src/testScenario/TestScenario.ts"],"names":[],"mappings":";;;
|
1
|
+
{"version":3,"file":"TestScenario.js","sourceRoot":"","sources":["../../src/testScenario/TestScenario.ts"],"names":[],"mappings":";;;AAEA,uCAAoC;AAEpC,mDAAgD;AAIhD,MAAa,YAAa,SAAQ,6BAAuB;IACjB;IAAtC,YAAY,QAAgB,EAAU,OAAwB;QAC5D,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QADK,YAAO,GAAP,OAAO,CAAiB;IAE9D,CAAC;IAEM,IAAI,CAAC,GAAG,QAAoB;QACjC,MAAM,QAAQ,GAAW,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE;YACxC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,QAAQ,IAAI,QAAQ,KAAK,EAAE;gBAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;YACvF,OAAO,IAAI,6BAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC,CAAC;QACJ,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,GAAG;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,MAAM,OAAO,CAAC,GAAG,CAAC,IAAA,iBAAO,EAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC;CACF;AApBD,oCAoBC"}
|
@@ -1,7 +1,12 @@
|
|
1
1
|
import { StepType } from "@vr1/be-driven-interface";
|
2
2
|
export interface TestStep {
|
3
|
-
|
4
|
-
|
3
|
+
stepType: StepType;
|
4
|
+
and: boolean;
|
5
|
+
stepName: string;
|
5
6
|
target: Function;
|
6
7
|
args: any[];
|
7
8
|
}
|
9
|
+
export interface Test {
|
10
|
+
testName: string;
|
11
|
+
steps: Array<TestStep | Test[]>;
|
12
|
+
}
|
@@ -1,3 +1,4 @@
|
|
1
|
-
import {
|
2
|
-
import { TestStep } from "./TestStep";
|
3
|
-
export declare function runTest(
|
1
|
+
import { ScenarioOptions } from "../types/ScenarioOptions";
|
2
|
+
import { Test, TestStep } from "./TestStep";
|
3
|
+
export declare function runTest(options: ScenarioOptions, test: Test): Array<Promise<void>>;
|
4
|
+
export declare function runSteps(options: ScenarioOptions, testName: string, steps: TestStep[]): Promise<void>;
|
@@ -1,13 +1,40 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.runTest = runTest;
|
4
|
-
|
4
|
+
exports.runSteps = runSteps;
|
5
|
+
const array_multiplex_1 = require("@vr1/array-multiplex");
|
6
|
+
const defaultOptions = {
|
7
|
+
testWrapper: async (name, test) => test(),
|
8
|
+
stepWrapper: async (type, name, step) => step(),
|
9
|
+
};
|
10
|
+
function runTest(options, test) {
|
11
|
+
options = { ...defaultOptions, ...options };
|
12
|
+
const multi = (0, array_multiplex_1.multiplex)(test.steps);
|
13
|
+
const promises = multi.map(line => runTestLine(options, test.testName, line));
|
14
|
+
return promises;
|
15
|
+
}
|
16
|
+
async function runTestLine(options, testName, line) {
|
17
|
+
const subTests = line.filter(isTest);
|
18
|
+
const fullTestName = subTests.reduce((acc, test) => `${acc} ${test.testName}`, testName);
|
19
|
+
const steps = line.flatMap(step => isTest(step) ? step.steps : step);
|
20
|
+
await runSteps(options, fullTestName, steps);
|
21
|
+
}
|
22
|
+
function isTest(test) {
|
23
|
+
return typeof test.testName === "string";
|
24
|
+
}
|
25
|
+
async function runSteps(options, testName, steps) {
|
26
|
+
options = { ...defaultOptions, ...options };
|
5
27
|
const store = {};
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
28
|
+
Object.assign(store, options.initialData);
|
29
|
+
await options.testWrapper(testName, async (data) => {
|
30
|
+
Object.assign(store, data);
|
31
|
+
for (let step of steps) {
|
32
|
+
const stepType = step.and ? "And" : step.stepType;
|
33
|
+
await options.stepWrapper(stepType, step.stepName, async () => {
|
34
|
+
const stepOutput = await step.target.call(store, ...step.args);
|
35
|
+
Object.assign(store, stepOutput);
|
36
|
+
});
|
37
|
+
}
|
38
|
+
});
|
12
39
|
}
|
13
40
|
//# sourceMappingURL=runTest.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"runTest.js","sourceRoot":"","sources":["../../src/testScenario/runTest.ts"],"names":[],"mappings":";;
|
1
|
+
{"version":3,"file":"runTest.js","sourceRoot":"","sources":["../../src/testScenario/runTest.ts"],"names":[],"mappings":";;AASA,0BAKC;AAaD,4BAkBC;AA7CD,0DAAiD;AAIjD,MAAM,cAAc,GAAoB;IACtC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;IACzC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;CAChD,CAAC;AAEF,SAAgB,OAAO,CAAC,OAAwB,EAAE,IAAU;IAC1D,OAAO,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAA,2BAAS,EAAkB,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9E,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAwB,EAAE,QAAgB,EAAE,IAAyB;IAC9F,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC;IACzF,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACnF,MAAM,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,MAAM,CAAC,IAAqB;IACnC,OAAO,OAAa,IAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC;AAClD,CAAC;AAEM,KAAK,UAAU,QAAQ,CAAC,OAAwB,EAAE,QAAgB,EAAE,KAAiB;IAC1F,OAAO,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,EAAE,CAAC;IAE5C,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAE1C,MAAM,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAC,IAAI,EAAC,EAAE;QAC/C,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3B,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAkB,CAAC;YAC5D,MAAM,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;gBAC5D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/D,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YACnC,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;AAGL,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ScenarioOptions.js","sourceRoot":"","sources":["../../src/types/ScenarioOptions.ts"],"names":[],"mappings":""}
|
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
export type StepWrapper = (type: StepType, name: string, func: () => Promise<void>) => Promise<void>;
|
1
|
+
export type StepWrapper = (stepType: string, name: string, step: () => Promise<void>) => Promise<void>;
|
@@ -0,0 +1 @@
|
|
1
|
+
export type TestWrapper = (testName: string, test: (initialData?: object) => Promise<void>) => void;
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"TestWrapper.js","sourceRoot":"","sources":["../../src/types/TestWrapper.ts"],"names":[],"mappings":""}
|
package/build/types/index.d.ts
CHANGED
package/build/types/index.js
CHANGED
@@ -15,4 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
15
|
};
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
17
|
__exportStar(require("./StepWrapper"), exports);
|
18
|
+
__exportStar(require("./TestWrapper"), exports);
|
19
|
+
__exportStar(require("./ScenarioOptions"), exports);
|
18
20
|
//# sourceMappingURL=index.js.map
|
package/build/types/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B"}
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,gDAA8B;AAC9B,oDAAkC"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vr1/be-driven-syntax-sugar",
|
3
|
-
"version": "
|
3
|
+
"version": "2.0.1",
|
4
4
|
"description": "syntax sugar to write pw and jest tests in bdd style ",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -40,6 +40,8 @@
|
|
40
40
|
"typescript": "^5.7.3"
|
41
41
|
},
|
42
42
|
"dependencies": {
|
43
|
-
"@vr1/
|
43
|
+
"@vr1/array-multiplex": "^1.1.0",
|
44
|
+
"@vr1/be-driven-interface": "^2.0.4",
|
45
|
+
"@vr1/function-name-to-sentence": "^1.0.0"
|
44
46
|
}
|
45
47
|
}
|
package/src/scenario.ts
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
import { StepWrapper } from "./types/StepWrapper";
|
2
1
|
import { TestScenario } from "./testScenario";
|
3
2
|
import { ScenarioFirstStep } from "@vr1/be-driven-interface";
|
3
|
+
import { ScenarioOptions } from "./types/ScenarioOptions";
|
4
4
|
|
5
|
-
export function scenario(
|
6
|
-
|
5
|
+
export function scenario(testName: string, options?: ScenarioOptions): ScenarioFirstStep;
|
6
|
+
export function scenario(options?: ScenarioOptions): ScenarioFirstStep;
|
7
|
+
export function scenario(first?: string | ScenarioOptions, second?: ScenarioOptions): ScenarioFirstStep {
|
8
|
+
const testName = typeof first === "string" ? first : "";
|
9
|
+
const options = (typeof first === "object" ? first : second) ?? {};
|
10
|
+
return new TestScenario(testName, options);
|
7
11
|
}
|
8
12
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { StepType, Step } from "@vr1/be-driven-interface";
|
2
|
+
import { Test, TestStep } from "./TestStep";
|
3
|
+
import { functionNameToSentence } from "@vr1/function-name-to-sentence";
|
4
|
+
|
5
|
+
|
6
|
+
export class ScenarioSteps<T extends Step<any>> implements Step<T> {
|
7
|
+
constructor(protected test: Test) { }
|
8
|
+
|
9
|
+
public given<TArgs extends any[], TMnemonic extends (...a: TArgs) => any>(func: TMnemonic, ...args: TArgs): T {
|
10
|
+
this.test.steps.push(createStep(func, args, StepType.Given));
|
11
|
+
return this as any;
|
12
|
+
}
|
13
|
+
|
14
|
+
public when<TArgs extends any[], TMnemonic extends (...a: TArgs) => any>(func: TMnemonic, ...args: TArgs): T {
|
15
|
+
this.test.steps.push(createStep(func, args, StepType.When));
|
16
|
+
return this as any;
|
17
|
+
}
|
18
|
+
|
19
|
+
public then<TArgs extends any[], TMnemonic extends (...a: TArgs) => any>(func: TMnemonic, ...args: TArgs): T {
|
20
|
+
this.test.steps.push(createStep(func, args, StepType.Then));
|
21
|
+
return this as any;
|
22
|
+
}
|
23
|
+
|
24
|
+
public and<TArgs extends any[], TMnemonic extends (...a: TArgs) => any>(func: TMnemonic, ...args: TArgs): T {
|
25
|
+
const previousStep: TestStep = this.test.steps[this.test.steps.length - 1] as TestStep;
|
26
|
+
this.test.steps.push(createStep(func, args, previousStep.stepType, true));
|
27
|
+
return this as any;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
function createStep(target: any, args: any[], type: StepType, and: boolean = false): TestStep {
|
32
|
+
const stepType = target.stepType ?? type;
|
33
|
+
if (stepType !== type) throw new Error(`Cannot use ${stepType} type of step, ${type} was expected.`);
|
34
|
+
return {
|
35
|
+
stepName: createName(target, args),
|
36
|
+
target,
|
37
|
+
stepType,
|
38
|
+
args,
|
39
|
+
and
|
40
|
+
};
|
41
|
+
}
|
42
|
+
|
43
|
+
function createName(target: any, args: any[]): string {
|
44
|
+
return (target.stepName != null && target.stepName !== "")
|
45
|
+
? args.reduce((prev, cur, i) => prev.replace(new RegExp(`\\{${i}\\}`, "g"), cur), target.stepName)
|
46
|
+
: functionNameToSentence(target.name);
|
47
|
+
}
|
48
|
+
|
@@ -1,53 +1,29 @@
|
|
1
1
|
|
2
|
-
import { Scenario,
|
3
|
-
import { StepWrapper } from "../types";
|
4
|
-
import { TestStep } from "./TestStep";
|
2
|
+
import { Scenario, Variance } from "@vr1/be-driven-interface";
|
5
3
|
import { runTest } from "./runTest";
|
4
|
+
import { ScenarioOptions } from "../types/ScenarioOptions";
|
5
|
+
import { ScenarioSteps } from "./ScenarioSteps";
|
6
|
+
import { Test } from "./TestStep";
|
6
7
|
|
7
|
-
export class TestScenario implements Scenario {
|
8
|
-
private steps: TestStep[] = [];
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
this.steps.push(createStep(func, args, StepType.Given));
|
14
|
-
return this;
|
15
|
-
}
|
16
|
-
public when<TArgs extends any[], TMnemonic extends (...a: TArgs) => void | Promise<void>>(func: TMnemonic, ...args: TArgs): Scenario {
|
17
|
-
this.steps.push(createStep(func, args, StepType.When));
|
18
|
-
return this;
|
19
|
-
}
|
20
|
-
public then<TArgs extends any[], TMnemonic extends (...a: TArgs) => void | Promise<void>>(func: TMnemonic, ...args: TArgs): Scenario {
|
21
|
-
this.steps.push(createStep(func, args, StepType.Then));
|
22
|
-
return this;
|
23
|
-
}
|
24
|
-
public and<TArgs extends any[], TMnemonic extends (...a: TArgs) => void | Promise<void>>(func: TMnemonic, ...args: TArgs): Scenario {
|
25
|
-
this.steps.push(createStep(func, args, this.steps[this.steps.length - 1].type));
|
26
|
-
return this;
|
9
|
+
export class TestScenario extends ScenarioSteps<Scenario> implements Scenario {
|
10
|
+
constructor(testName: string, private options: ScenarioOptions) {
|
11
|
+
super({ testName, steps: [] });
|
27
12
|
}
|
28
13
|
|
29
|
-
public
|
30
|
-
|
14
|
+
public vary(...variance: Variance[]): Scenario {
|
15
|
+
const subTests: Test[] = variance.map((_, i) => ({ testName: `${i}`, steps: [] }));
|
16
|
+
this.test.steps.push(subTests);
|
17
|
+
variance.forEach((v, i) => v((testName) => {
|
18
|
+
if (typeof (testName) === "string" && testName !== "") subTests[i].testName = testName;
|
19
|
+
return new ScenarioSteps(subTests[i]);
|
20
|
+
}));
|
21
|
+
return this;
|
31
22
|
}
|
32
23
|
|
33
|
-
public run(): Promise<void> {
|
34
|
-
const
|
35
|
-
this.
|
36
|
-
|
24
|
+
public async run(): Promise<void> {
|
25
|
+
const test = this.test;
|
26
|
+
this.test = null;
|
27
|
+
await Promise.all(runTest(this.options, test));
|
37
28
|
}
|
38
29
|
}
|
39
|
-
|
40
|
-
function createStep(target: any, args: any[], type: StepType): TestStep {
|
41
|
-
const stepType = target.stepType ?? type;
|
42
|
-
if (stepType !== type) throw new Error(`Cannot use ${stepType} type of step, ${type} was expected.`);
|
43
|
-
return {
|
44
|
-
name: createName(target, args),
|
45
|
-
target,
|
46
|
-
type,
|
47
|
-
args,
|
48
|
-
};
|
49
|
-
}
|
50
|
-
function createName(target: any, args: any[]): string {
|
51
|
-
return args.reduce((prev, cur, i) => prev.replace(new RegExp(`\\{${i}\\}`, "g"), cur), target.stepName ?? target.name);
|
52
|
-
}
|
53
|
-
|
@@ -1,8 +1,14 @@
|
|
1
1
|
import { StepType } from "@vr1/be-driven-interface";
|
2
2
|
|
3
3
|
export interface TestStep {
|
4
|
-
|
5
|
-
|
4
|
+
stepType: StepType;
|
5
|
+
and: boolean;
|
6
|
+
stepName: string;
|
6
7
|
target: Function;
|
7
8
|
args: any[];
|
8
9
|
}
|
10
|
+
|
11
|
+
export interface Test {
|
12
|
+
testName: string;
|
13
|
+
steps: Array<TestStep | Test[]>;
|
14
|
+
}
|
@@ -1,13 +1,48 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
1
|
+
import { multiplex } from "@vr1/array-multiplex";
|
2
|
+
import { ScenarioOptions } from "../types/ScenarioOptions";
|
3
|
+
import { Test, TestStep } from "./TestStep";
|
4
|
+
|
5
|
+
const defaultOptions: ScenarioOptions = {
|
6
|
+
testWrapper: async (name, test) => test(),
|
7
|
+
stepWrapper: async (type, name, step) => step(),
|
8
|
+
};
|
9
|
+
|
10
|
+
export function runTest(options: ScenarioOptions, test: Test): Array<Promise<void>> {
|
11
|
+
options = { ...defaultOptions, ...options };
|
12
|
+
const multi = multiplex<TestStep | Test>(test.steps);
|
13
|
+
const promises = multi.map(line => runTestLine(options, test.testName, line));
|
14
|
+
return promises;
|
15
|
+
}
|
16
|
+
|
17
|
+
async function runTestLine(options: ScenarioOptions, testName: string, line: (Test | TestStep)[]): Promise<void> {
|
18
|
+
const subTests = line.filter(isTest);
|
19
|
+
const fullTestName = subTests.reduce((acc, test) => `${acc} ${test.testName}`, testName);
|
20
|
+
const steps = line.flatMap(step => isTest(step) ? step.steps as TestStep[] : step);
|
21
|
+
await runSteps(options, fullTestName, steps);
|
22
|
+
}
|
23
|
+
|
24
|
+
function isTest(test: Test | TestStep): test is Test {
|
25
|
+
return typeof (<any>test).testName === "string";
|
26
|
+
}
|
27
|
+
|
28
|
+
export async function runSteps(options: ScenarioOptions, testName: string, steps: TestStep[]): Promise<void> {
|
29
|
+
options = { ...defaultOptions, ...options };
|
3
30
|
|
4
|
-
export async function runTest(wrapper: StepWrapper, steps: TestStep[]): Promise<void> {
|
5
31
|
const store = {};
|
32
|
+
Object.assign(store, options.initialData);
|
33
|
+
|
34
|
+
await options.testWrapper(testName, async data => {
|
35
|
+
Object.assign(store, data);
|
36
|
+
for (let step of steps) {
|
37
|
+
const stepType = step.and ? "And" : step.stepType as string;
|
38
|
+
await options.stepWrapper(stepType, step.stepName, async () => {
|
39
|
+
const stepOutput = await step.target.call(store, ...step.args);
|
40
|
+
Object.assign(store, stepOutput);
|
41
|
+
});
|
42
|
+
}
|
43
|
+
});
|
44
|
+
|
6
45
|
|
7
|
-
for (let step of steps) {
|
8
|
-
await wrapper(step.type, step.name, async () => {
|
9
|
-
const stepOutput = await step.target.call(store, ...step.args);
|
10
|
-
Object.assign(store, stepOutput);
|
11
|
-
});
|
12
|
-
}
|
13
46
|
}
|
47
|
+
|
48
|
+
|
package/src/types/StepWrapper.ts
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
export type TestWrapper = (testName: string, test: (initialData?: object) => Promise<void>) => void;
|
package/src/types/index.ts
CHANGED