@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 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
 
@@ -13,26 +13,12 @@ function attach(body, details) {
13
13
  }
14
14
  const fixture = new supportCodeLibrary.World({});
15
15
  const test = fixture.test;
16
- const stepHandler = test.expect.extend({
17
- async execute(fn) {
18
- try {
19
- await fn();
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
- test(testCase.name, { tag }, async () => {
48
- var _a, _b;
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
- const result = { status: 'passed' };
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
- await stepHandler
87
- .soft(() => step.code.apply(world, parameters), 'Step')
88
- .execute();
89
- for (const afterStep of supportCodeLibrary.afterTestStepHookDefinitions) {
90
- if (afterStep.appliesToTestCase(testCase)) {
91
- await test.step('After Step', () => afterStep.code.apply(world, [{
92
- pickle: testCase,
93
- pickleStep,
94
- result
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
- for (const afterAllHook of supportCodeLibrary.afterTestRunHookDefinitions) {
113
- test.afterAll(() => afterAllHook.code.apply({}));
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":"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"}
1
+ {"version":3,"file":"cucumber.spec.js","sourceRoot":"","sources":["../src/cucumber.spec.ts"],"names":[],"mappings":"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"}
@@ -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
@@ -1,2 +1,3 @@
1
1
  export { PlaywrightWorld } from './src/PlaywrightWorld';
2
2
  export { defineCucumber } from './src/defineCucumber';
3
+ export { tags } from './src/tags';
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.1.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": {
@@ -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
- const stepHandler = test.expect.extend({
19
- async execute(fn: () => Promise<any>) {
20
- try {
21
- await fn();
22
- return {
23
- pass: true,
24
- message: () => ''
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
- test(testCase.name, {tag}, async () => {
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
- const result: { status: string, error?: any } = { status: 'passed' };
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
- await test.step('Before Step', () => beforeStep.code.apply(world, [{
71
- pickle: testCase,
72
- pickleStep
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 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 {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
- await stepHandler
89
- .soft(() => step.code.apply(world, parameters), 'Step')
90
- .execute();
91
- for (const afterStep of supportCodeLibrary.afterTestStepHookDefinitions) {
92
- if (afterStep.appliesToTestCase(testCase)) {
93
- await test.step('After Step', () => afterStep.code.apply(world, [{
94
- pickle: testCase,
95
- pickleStep,
96
- result
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
- for (const afterAllHook of supportCodeLibrary.afterTestRunHookDefinitions) {
116
- test.afterAll(() => afterAllHook.code.apply({}));
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
+ }