@qavajs/playwright-runner-adapter 1.1.1 → 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/CHANGELOG.md +8 -0
- package/README.md +10 -0
- package/adapter/cucumber.spec.js +83 -60
- package/adapter/cucumber.spec.js.map +1 -1
- package/adapter/tags.js +26 -0
- package/adapter/tags.js.map +1 -0
- package/index.d.ts +1 -0
- package/index.js +3 -1
- package/package.json +2 -1
- package/src/cucumber.spec.ts +109 -62
- package/src/tags.ts +20 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,14 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
|
|
|
10
10
|
:pencil: - chore
|
|
11
11
|
:microscope: - experimental
|
|
12
12
|
|
|
13
|
+
## [1.3.0]
|
|
14
|
+
- :rocket: added `tags` function to translate cucumber tag expression to grep parameter
|
|
15
|
+
- :rocket: improved tags displaying in annotation
|
|
16
|
+
|
|
17
|
+
## [1.2.0]
|
|
18
|
+
- :rocket: reworked hooks via playwright hooks
|
|
19
|
+
- :rocket: display proper location in sources
|
|
20
|
+
|
|
13
21
|
## [1.1.1]
|
|
14
22
|
- :beetle: fixed issue with After hooks execution in case of failed test
|
|
15
23
|
|
package/README.md
CHANGED
|
@@ -74,6 +74,16 @@ class ExtendedPlaywrightWorld extends PlaywrightWorld {
|
|
|
74
74
|
}
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
### Tag expression
|
|
78
|
+
It is possible to use regular tag expressions via `tags` util function
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { tags } from '@qavajs/playwright-runner-adapter';
|
|
82
|
+
export default defineConfig({
|
|
83
|
+
grep: tags('@oneTag and @anotherTag')
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
77
87
|
## Limitation
|
|
78
88
|
- ES modules are not supported (at least for node <= 22, where experimental ESM require is introduced)
|
|
79
89
|
|
package/adapter/cucumber.spec.js
CHANGED
|
@@ -13,26 +13,12 @@ function attach(body, details) {
|
|
|
13
13
|
}
|
|
14
14
|
const fixture = new supportCodeLibrary.World({});
|
|
15
15
|
const test = fixture.test;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
pass: true,
|
|
22
|
-
message: () => ''
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
catch (e) {
|
|
26
|
-
return {
|
|
27
|
-
pass: false,
|
|
28
|
-
message: () => e.message,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
16
|
+
test.beforeAll(async () => {
|
|
17
|
+
for (const beforeAllHook of supportCodeLibrary.beforeTestRunHookDefinitions) {
|
|
18
|
+
const location = { location: { column: 1, file: beforeAllHook.uri, line: beforeAllHook.line } };
|
|
19
|
+
await test.step('Before All', () => beforeAllHook.code.apply({}), location);
|
|
31
20
|
}
|
|
32
21
|
});
|
|
33
|
-
for (const beforeAllHook of supportCodeLibrary.beforeTestRunHookDefinitions) {
|
|
34
|
-
test.beforeAll(() => beforeAllHook.code.apply({}));
|
|
35
|
-
}
|
|
36
22
|
for (const feature of features) {
|
|
37
23
|
const tests = feature.tests;
|
|
38
24
|
test.describe(feature.feature, async () => {
|
|
@@ -41,41 +27,57 @@ for (const feature of features) {
|
|
|
41
27
|
attach,
|
|
42
28
|
supportCodeLibrary
|
|
43
29
|
});
|
|
44
|
-
test.beforeEach(world.init);
|
|
30
|
+
test.beforeEach('Fixtures', world.init);
|
|
31
|
+
test.beforeEach('Before Hooks', async () => {
|
|
32
|
+
var _a;
|
|
33
|
+
const testId = test
|
|
34
|
+
.info()
|
|
35
|
+
.annotations
|
|
36
|
+
.find((annotation) => annotation.type === 'testId')
|
|
37
|
+
.description;
|
|
38
|
+
const testCase = tests.find(test => test.id === testId);
|
|
39
|
+
for (const beforeHook of supportCodeLibrary.beforeTestCaseHookDefinitions) {
|
|
40
|
+
if (beforeHook.appliesToTestCase(testCase)) {
|
|
41
|
+
const hookName = (_a = beforeHook.name) !== null && _a !== void 0 ? _a : 'Before';
|
|
42
|
+
const location = { location: { column: 1, file: beforeHook.uri, line: beforeHook.line } };
|
|
43
|
+
await test.step(hookName, () => beforeHook.code.apply(world, [{
|
|
44
|
+
pickle: testCase
|
|
45
|
+
}]), location);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
45
49
|
for (const testCase of tests) {
|
|
46
50
|
const tag = testCase.tags.map((tag) => tag.name);
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
const annotation = [
|
|
52
|
+
{ type: 'name', description: testCase.name },
|
|
53
|
+
{ type: 'testId', description: testCase.id },
|
|
54
|
+
{ type: 'tags', description: JSON.stringify(tag) }
|
|
55
|
+
];
|
|
56
|
+
test(testCase.name, { tag, annotation: annotation }, async () => {
|
|
49
57
|
const testInfo = test.info();
|
|
50
|
-
|
|
51
|
-
for (const beforeHook of supportCodeLibrary.beforeTestCaseHookDefinitions) {
|
|
52
|
-
if (beforeHook.appliesToTestCase(testCase)) {
|
|
53
|
-
const hookName = (_a = beforeHook.name) !== null && _a !== void 0 ? _a : 'Before';
|
|
54
|
-
await test.step(hookName, () => beforeHook.code.apply(world, [{
|
|
55
|
-
pickle: testCase
|
|
56
|
-
}]));
|
|
57
|
-
}
|
|
58
|
-
}
|
|
58
|
+
testInfo.result = { status: 'passed' };
|
|
59
59
|
for (const pickleStep of testCase.steps) {
|
|
60
60
|
if (testInfo.error) {
|
|
61
61
|
break;
|
|
62
62
|
}
|
|
63
|
+
const steps = supportCodeLibrary.stepDefinitions
|
|
64
|
+
.filter(stepDefinition => stepDefinition.matchesStepName(pickleStep.text));
|
|
65
|
+
if (steps.length === 0)
|
|
66
|
+
throw new Error(`Step '${pickleStep.text}' is not defined`);
|
|
67
|
+
if (steps.length > 1)
|
|
68
|
+
throw new Error(`'${pickleStep.text}' matches multiple step definitions`);
|
|
69
|
+
const [step] = steps;
|
|
70
|
+
const location = { location: { column: 1, file: step.uri, line: step.line } };
|
|
63
71
|
await test.step(pickleStep.text, async () => {
|
|
64
72
|
for (const beforeStep of supportCodeLibrary.beforeTestStepHookDefinitions) {
|
|
65
73
|
if (beforeStep.appliesToTestCase(testCase)) {
|
|
74
|
+
const location = { location: { column: 1, file: beforeStep.uri, line: beforeStep.line } };
|
|
66
75
|
await test.step('Before Step', () => beforeStep.code.apply(world, [{
|
|
67
76
|
pickle: testCase,
|
|
68
77
|
pickleStep
|
|
69
|
-
}]));
|
|
78
|
+
}]), location);
|
|
70
79
|
}
|
|
71
80
|
}
|
|
72
|
-
const steps = supportCodeLibrary.stepDefinitions
|
|
73
|
-
.filter(stepDefinition => stepDefinition.matchesStepName(pickleStep.text));
|
|
74
|
-
if (steps.length === 0)
|
|
75
|
-
throw new Error(`Step '${pickleStep.text}' is not defined`);
|
|
76
|
-
if (steps.length > 1)
|
|
77
|
-
throw new Error(`'${pickleStep.text}' matches multiple step definitions`);
|
|
78
|
-
const [step] = steps;
|
|
79
81
|
const { parameters } = await step.getInvocationParameters({
|
|
80
82
|
step: {
|
|
81
83
|
text: pickleStep.text,
|
|
@@ -83,33 +85,54 @@ for (const feature of features) {
|
|
|
83
85
|
},
|
|
84
86
|
world
|
|
85
87
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
try {
|
|
89
|
+
await step.code.apply(world, parameters);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
testInfo.result.error = err;
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
for (const afterStep of supportCodeLibrary.afterTestStepHookDefinitions) {
|
|
97
|
+
if (afterStep.appliesToTestCase(testCase)) {
|
|
98
|
+
const location = { location: { column: 1, file: afterStep.uri, line: afterStep.line } };
|
|
99
|
+
await test.step('After Step', () => afterStep.code.apply(world, [{
|
|
100
|
+
pickle: testCase,
|
|
101
|
+
pickleStep,
|
|
102
|
+
result: testInfo.result
|
|
103
|
+
}]), location);
|
|
104
|
+
}
|
|
96
105
|
}
|
|
97
106
|
}
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
for (const afterHook of supportCodeLibrary.afterTestCaseHookDefinitions) {
|
|
101
|
-
if (afterHook.appliesToTestCase(testCase)) {
|
|
102
|
-
const hookName = (_b = afterHook.name) !== null && _b !== void 0 ? _b : 'After';
|
|
103
|
-
await test.step(hookName, () => afterHook.code.apply(world, [{
|
|
104
|
-
pickle: testCase, result
|
|
105
|
-
}]));
|
|
106
|
-
}
|
|
107
|
+
}, location);
|
|
107
108
|
}
|
|
108
109
|
});
|
|
109
110
|
}
|
|
111
|
+
test.afterEach('After Hooks', async () => {
|
|
112
|
+
var _a;
|
|
113
|
+
const testInfo = test.info();
|
|
114
|
+
const testId = testInfo
|
|
115
|
+
.annotations
|
|
116
|
+
.find((annotation) => annotation.type === 'testId')
|
|
117
|
+
.description;
|
|
118
|
+
const testCase = tests.find(test => test.id === testId);
|
|
119
|
+
for (const afterHook of supportCodeLibrary.afterTestCaseHookDefinitions) {
|
|
120
|
+
if (afterHook.appliesToTestCase(testCase)) {
|
|
121
|
+
const hookName = (_a = afterHook.name) !== null && _a !== void 0 ? _a : 'After';
|
|
122
|
+
const location = { location: { column: 1, file: afterHook.uri, line: afterHook.line } };
|
|
123
|
+
await test.step(hookName, () => afterHook.code.apply(world, [{
|
|
124
|
+
pickle: testCase,
|
|
125
|
+
result: testInfo.result
|
|
126
|
+
}]), location);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
110
130
|
});
|
|
111
131
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
132
|
+
test.afterAll(async () => {
|
|
133
|
+
for (const afterAllHook of supportCodeLibrary.afterTestRunHookDefinitions) {
|
|
134
|
+
const location = { location: { column: 1, file: afterAllHook.uri, line: afterAllHook.line } };
|
|
135
|
+
await test.step('After All', () => afterAllHook.code.apply({}), location);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
115
138
|
//# sourceMappingURL=cucumber.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cucumber.spec.js","sourceRoot":"","sources":["../src/cucumber.spec.ts"],"names":[],"mappings":";;AAAA,qCAAgC;AAEhC,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAC,GAAG,IAAA,aAAI,GAAE,CAAC;AAE/C,SAAS,GAAG,CAAC,IAAS;IAClB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,MAAM,CAAsB,IAAS,EAAE,OAAY;;IACxD,MAAM,QAAQ,GAAG,MAAA,OAAO,CAAC,QAAQ,mCAAI,YAAY,CAAC;IAClD,MAAM,WAAW,GAAG,MAAA,OAAO,CAAC,SAAS,mCAAI,YAAY,CAAC;IACtD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"cucumber.spec.js","sourceRoot":"","sources":["../src/cucumber.spec.ts"],"names":[],"mappings":"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"}
|
package/adapter/tags.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.tags = tags;
|
|
7
|
+
const tag_expressions_1 = __importDefault(require("@cucumber/tag-expressions"));
|
|
8
|
+
/**
|
|
9
|
+
* Translate cucumber tag expression to playwright grep
|
|
10
|
+
* @param {string} tagExpression
|
|
11
|
+
* @example
|
|
12
|
+
* import { tags } from '@qavajs/playwright-runner-adapter';
|
|
13
|
+
* export default defineConfig({
|
|
14
|
+
* grep: tags('@oneTag and @anotherTag')
|
|
15
|
+
* })
|
|
16
|
+
*/
|
|
17
|
+
function tags(tagExpression) {
|
|
18
|
+
const expressionNode = (0, tag_expressions_1.default)(tagExpression);
|
|
19
|
+
return {
|
|
20
|
+
test(testName) {
|
|
21
|
+
const tokens = testName.split(' ');
|
|
22
|
+
return expressionNode.evaluate(tokens);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../src/tags.ts"],"names":[],"mappings":";;;;;AAWA,oBAQC;AAnBD,gFAA6C;AAE7C;;;;;;;;GAQG;AACH,SAAgB,IAAI,CAAC,aAAqB;IACtC,MAAM,cAAc,GAAG,IAAA,yBAAK,EAAC,aAAa,CAAC,CAAC;IAC5C,OAAO;QACH,IAAI,CAAC,QAAgB;YACjB,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnC,OAAO,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC;KACM,CAAC;AAChB,CAAC"}
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const { PlaywrightWorld } = require('./adapter/PlaywrightWorld');
|
|
2
2
|
const { defineCucumber } = require('./adapter/defineCucumber');
|
|
3
|
+
const { tags } = require('./adapter/tags');
|
|
3
4
|
|
|
4
5
|
module.exports = {
|
|
5
6
|
PlaywrightWorld,
|
|
6
|
-
defineCucumber
|
|
7
|
+
defineCucumber,
|
|
8
|
+
tags
|
|
7
9
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qavajs/playwright-runner-adapter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "adapter for playwright test runner",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsc",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@cucumber/gherkin": "^30.0.4",
|
|
14
|
+
"@cucumber/tag-expressions": "^6.1.1",
|
|
14
15
|
"glob": "^11.0.1"
|
|
15
16
|
},
|
|
16
17
|
"devDependencies": {
|
package/src/cucumber.spec.ts
CHANGED
|
@@ -9,33 +9,23 @@ function log(data: any) {
|
|
|
9
9
|
function attach(this: { test: any }, body: any, details: any) {
|
|
10
10
|
const fileName = details.fileName ?? 'attachment';
|
|
11
11
|
const contentType = details.mediaType ?? 'text/plain';
|
|
12
|
-
this.test.info().attach(fileName, {body, contentType});
|
|
12
|
+
this.test.info().attach(fileName, { body, contentType });
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const fixture = new supportCodeLibrary.World({});
|
|
16
16
|
const test = fixture.test;
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} catch (e: any) {
|
|
27
|
-
return {
|
|
28
|
-
pass: false,
|
|
29
|
-
message: () => e.message,
|
|
30
|
-
}
|
|
31
|
-
}
|
|
18
|
+
test.beforeAll(async () => {
|
|
19
|
+
for (const beforeAllHook of supportCodeLibrary.beforeTestRunHookDefinitions) {
|
|
20
|
+
const location = { location: { column: 1, file: beforeAllHook.uri, line: beforeAllHook.line }}
|
|
21
|
+
await test.step(
|
|
22
|
+
'Before All',
|
|
23
|
+
() => beforeAllHook.code.apply({}),
|
|
24
|
+
location
|
|
25
|
+
)
|
|
32
26
|
}
|
|
33
27
|
});
|
|
34
28
|
|
|
35
|
-
for (const beforeAllHook of supportCodeLibrary.beforeTestRunHookDefinitions) {
|
|
36
|
-
test.beforeAll(() => beforeAllHook.code.apply({}));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
29
|
for (const feature of features) {
|
|
40
30
|
const tests = feature.tests;
|
|
41
31
|
test.describe(feature.feature as string, async () => {
|
|
@@ -45,73 +35,130 @@ for (const feature of features) {
|
|
|
45
35
|
supportCodeLibrary
|
|
46
36
|
});
|
|
47
37
|
|
|
48
|
-
test.beforeEach(world.init);
|
|
38
|
+
test.beforeEach('Fixtures', world.init);
|
|
39
|
+
|
|
40
|
+
test.beforeEach('Before Hooks', async () => {
|
|
41
|
+
const testId = test
|
|
42
|
+
.info()
|
|
43
|
+
.annotations
|
|
44
|
+
.find((annotation: { type: string }) => annotation.type === 'testId')
|
|
45
|
+
.description;
|
|
46
|
+
const testCase = tests.find(test => test.id === testId);
|
|
47
|
+
for (const beforeHook of supportCodeLibrary.beforeTestCaseHookDefinitions) {
|
|
48
|
+
if (beforeHook.appliesToTestCase(testCase)) {
|
|
49
|
+
const hookName = beforeHook.name ?? 'Before';
|
|
50
|
+
const location = { location: { column: 1, file: beforeHook.uri, line: beforeHook.line }}
|
|
51
|
+
await test.step(
|
|
52
|
+
hookName,
|
|
53
|
+
() => beforeHook.code.apply(world, [{
|
|
54
|
+
pickle: testCase
|
|
55
|
+
}]),
|
|
56
|
+
location
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
49
61
|
|
|
50
62
|
for (const testCase of tests) {
|
|
51
63
|
const tag = testCase.tags.map((tag: { name: string }) => tag.name);
|
|
52
|
-
|
|
64
|
+
const annotation = [
|
|
65
|
+
{ type: 'name', description: testCase.name },
|
|
66
|
+
{ type: 'testId', description: testCase.id },
|
|
67
|
+
{ type: 'tags', description: JSON.stringify(tag) }
|
|
68
|
+
];
|
|
69
|
+
test(testCase.name, { tag, annotation: annotation }, async () => {
|
|
53
70
|
const testInfo = test.info();
|
|
54
|
-
|
|
55
|
-
for (const beforeHook of supportCodeLibrary.beforeTestCaseHookDefinitions) {
|
|
56
|
-
if (beforeHook.appliesToTestCase(testCase)) {
|
|
57
|
-
const hookName = beforeHook.name ?? 'Before';
|
|
58
|
-
await test.step(hookName, () => beforeHook.code.apply(world, [{
|
|
59
|
-
pickle: testCase
|
|
60
|
-
}]));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
71
|
+
testInfo.result = { status: 'passed' };
|
|
63
72
|
for (const pickleStep of testCase.steps) {
|
|
64
73
|
if (testInfo.error) {
|
|
65
74
|
break;
|
|
66
75
|
}
|
|
76
|
+
const steps = supportCodeLibrary.stepDefinitions
|
|
77
|
+
.filter(stepDefinition => stepDefinition.matchesStepName(pickleStep.text));
|
|
78
|
+
if (steps.length === 0) throw new Error(`Step '${pickleStep.text}' is not defined`);
|
|
79
|
+
if (steps.length > 1) throw new Error(`'${pickleStep.text}' matches multiple step definitions`);
|
|
80
|
+
const [ step ] = steps;
|
|
81
|
+
const location = { location: { column: 1, file: step.uri, line: step.line }}
|
|
67
82
|
await test.step(pickleStep.text, async () => {
|
|
68
83
|
for (const beforeStep of supportCodeLibrary.beforeTestStepHookDefinitions) {
|
|
69
84
|
if (beforeStep.appliesToTestCase(testCase)) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
const location = { location: { column: 1, file: beforeStep.uri, line: beforeStep.line }}
|
|
86
|
+
await test.step(
|
|
87
|
+
'Before Step',
|
|
88
|
+
() => beforeStep.code.apply(world, [{
|
|
89
|
+
pickle: testCase,
|
|
90
|
+
pickleStep
|
|
91
|
+
}]),
|
|
92
|
+
location
|
|
93
|
+
);
|
|
74
94
|
}
|
|
75
95
|
}
|
|
76
|
-
const
|
|
77
|
-
.filter(stepDefinition => stepDefinition.matchesStepName(pickleStep.text));
|
|
78
|
-
if (steps.length === 0) throw new Error(`Step '${pickleStep.text}' is not defined`);
|
|
79
|
-
if (steps.length > 1) throw new Error(`'${pickleStep.text}' matches multiple step definitions`);
|
|
80
|
-
const [step] = steps;
|
|
81
|
-
const {parameters} = await step.getInvocationParameters({
|
|
96
|
+
const { parameters } = await step.getInvocationParameters({
|
|
82
97
|
step: {
|
|
83
98
|
text: pickleStep.text,
|
|
84
99
|
argument: pickleStep.argument
|
|
85
100
|
},
|
|
86
101
|
world
|
|
87
102
|
} as any);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
try {
|
|
104
|
+
await step.code.apply(world, parameters);
|
|
105
|
+
} catch (err: any) {
|
|
106
|
+
testInfo.result.error = err;
|
|
107
|
+
throw err;
|
|
108
|
+
} finally {
|
|
109
|
+
for (const afterStep of supportCodeLibrary.afterTestStepHookDefinitions) {
|
|
110
|
+
if (afterStep.appliesToTestCase(testCase)) {
|
|
111
|
+
const location = { location: { column: 1, file: afterStep.uri, line: afterStep.line }}
|
|
112
|
+
await test.step(
|
|
113
|
+
'After Step',
|
|
114
|
+
() => afterStep.code.apply(world, [{
|
|
115
|
+
pickle: testCase,
|
|
116
|
+
pickleStep,
|
|
117
|
+
result: testInfo.result
|
|
118
|
+
}]),
|
|
119
|
+
location
|
|
120
|
+
);
|
|
121
|
+
}
|
|
98
122
|
}
|
|
99
123
|
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
for (const afterHook of supportCodeLibrary.afterTestCaseHookDefinitions) {
|
|
103
|
-
if (afterHook.appliesToTestCase(testCase)) {
|
|
104
|
-
const hookName = afterHook.name ?? 'After';
|
|
105
|
-
await test.step(hookName, () => afterHook.code.apply(world, [{
|
|
106
|
-
pickle: testCase, result
|
|
107
|
-
}]));
|
|
108
|
-
}
|
|
124
|
+
}, location);
|
|
109
125
|
}
|
|
110
126
|
})
|
|
111
127
|
}
|
|
128
|
+
|
|
129
|
+
test.afterEach('After Hooks', async () => {
|
|
130
|
+
const testInfo = test.info();
|
|
131
|
+
const testId = testInfo
|
|
132
|
+
.annotations
|
|
133
|
+
.find((annotation: { type: string }) => annotation.type === 'testId')
|
|
134
|
+
.description;
|
|
135
|
+
const testCase = tests.find(test => test.id === testId);
|
|
136
|
+
for (const afterHook of supportCodeLibrary.afterTestCaseHookDefinitions) {
|
|
137
|
+
if (afterHook.appliesToTestCase(testCase)) {
|
|
138
|
+
const hookName = afterHook.name ?? 'After';
|
|
139
|
+
const location = { location: { column: 1, file: afterHook.uri, line: afterHook.line }}
|
|
140
|
+
await test.step(
|
|
141
|
+
hookName,
|
|
142
|
+
() => afterHook.code.apply(world, [{
|
|
143
|
+
pickle: testCase,
|
|
144
|
+
result: testInfo.result
|
|
145
|
+
}]),
|
|
146
|
+
location
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
112
152
|
});
|
|
113
153
|
}
|
|
114
154
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
155
|
+
test.afterAll(async () => {
|
|
156
|
+
for (const afterAllHook of supportCodeLibrary.afterTestRunHookDefinitions) {
|
|
157
|
+
const location = { location: { column: 1, file: afterAllHook.uri, line: afterAllHook.line }}
|
|
158
|
+
await test.step(
|
|
159
|
+
'After All',
|
|
160
|
+
() => afterAllHook.code.apply({}),
|
|
161
|
+
location
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
});
|
package/src/tags.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import parse from '@cucumber/tag-expressions'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Translate cucumber tag expression to playwright grep
|
|
5
|
+
* @param {string} tagExpression
|
|
6
|
+
* @example
|
|
7
|
+
* import { tags } from '@qavajs/playwright-runner-adapter';
|
|
8
|
+
* export default defineConfig({
|
|
9
|
+
* grep: tags('@oneTag and @anotherTag')
|
|
10
|
+
* })
|
|
11
|
+
*/
|
|
12
|
+
export function tags(tagExpression: string): RegExp {
|
|
13
|
+
const expressionNode = parse(tagExpression);
|
|
14
|
+
return {
|
|
15
|
+
test(testName: string) {
|
|
16
|
+
const tokens = testName.split(' ');
|
|
17
|
+
return expressionNode.evaluate(tokens);
|
|
18
|
+
}
|
|
19
|
+
} as RegExp;
|
|
20
|
+
}
|