@qavajs/playwright-runner-adapter 2.1.0 → 2.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 +7 -0
- package/adapter/PlaywrightWorld.d.ts +1 -1
- package/adapter/PlaywrightWorld.js +3 -1
- package/adapter/PlaywrightWorld.js.map +1 -1
- package/adapter/cucumberAdapter.js +130 -164
- package/adapter/cucumberAdapter.js.map +1 -1
- package/adapter/js/PlaywrightWorld.d.ts +31 -0
- package/adapter/js/PlaywrightWorld.js +56 -0
- package/adapter/js/Template.d.ts +10 -0
- package/adapter/js/Template.js +26 -0
- package/adapter/js/cucumberAdapter.d.ts +4 -0
- package/adapter/js/cucumberAdapter.js +244 -0
- package/adapter/js/filter.d.ts +19 -0
- package/adapter/js/filter.js +55 -0
- package/adapter/js/index.d.ts +5 -0
- package/adapter/js/index.js +21 -0
- package/adapter/js/loader.d.ts +14 -0
- package/adapter/js/loader.js +62 -0
- package/package.json +6 -6
- package/src/PlaywrightWorld.ts +4 -2
- package/src/cucumberAdapter.ts +216 -210
- package/tsconfig.js.json +23 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineConfig = defineConfig;
|
|
4
|
+
const loader_1 = require("./loader");
|
|
5
|
+
// Constants
|
|
6
|
+
const ANNOTATION_TYPES = {
|
|
7
|
+
NAME: 'name',
|
|
8
|
+
URI: 'uri',
|
|
9
|
+
TAGS: 'tags'
|
|
10
|
+
};
|
|
11
|
+
const HOOK_NAMES = {
|
|
12
|
+
BEFORE_ALL: 'Before All',
|
|
13
|
+
AFTER_ALL: 'After All',
|
|
14
|
+
BEFORE: 'Before',
|
|
15
|
+
AFTER: 'After',
|
|
16
|
+
BEFORE_STEP: 'Before Step',
|
|
17
|
+
AFTER_STEP: 'After Step',
|
|
18
|
+
WORLD: 'World',
|
|
19
|
+
BEFORE_HOOKS: 'Before Hooks',
|
|
20
|
+
AFTER_HOOKS: 'After Hooks'
|
|
21
|
+
};
|
|
22
|
+
const DEFAULT_VALUES = {
|
|
23
|
+
ATTACHMENT_FILENAME: 'attachment',
|
|
24
|
+
CONTENT_TYPE: 'text/plain',
|
|
25
|
+
COLUMN: 1,
|
|
26
|
+
TEST_CASE_ID: '0',
|
|
27
|
+
TEST_STEP_ID: '0'
|
|
28
|
+
};
|
|
29
|
+
const STEP_ARGUMENT_LABELS = {
|
|
30
|
+
DOC_STRING: ' [MultiLine]',
|
|
31
|
+
DATA_TABLE: ' [DataTable]'
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Creates a location object from step definition
|
|
35
|
+
*/
|
|
36
|
+
function getLine(step) {
|
|
37
|
+
return {
|
|
38
|
+
location: {
|
|
39
|
+
column: DEFAULT_VALUES.COLUMN,
|
|
40
|
+
file: step.uri,
|
|
41
|
+
line: step.line
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Logs data to console
|
|
47
|
+
*/
|
|
48
|
+
function log(data) {
|
|
49
|
+
console.log(data);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Attaches content to test report
|
|
53
|
+
*/
|
|
54
|
+
function attach(body, details) {
|
|
55
|
+
const fileName = details?.fileName ?? DEFAULT_VALUES.ATTACHMENT_FILENAME;
|
|
56
|
+
const contentType = details?.mediaType ?? DEFAULT_VALUES.CONTENT_TYPE;
|
|
57
|
+
return this.test.info().attach(fileName, { body, contentType });
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Generates a human-readable step name with argument type indicator
|
|
61
|
+
*/
|
|
62
|
+
function stepName(pickleStep) {
|
|
63
|
+
let step = pickleStep.text;
|
|
64
|
+
if (pickleStep.argument) {
|
|
65
|
+
step += pickleStep.argument.docString
|
|
66
|
+
? STEP_ARGUMENT_LABELS.DOC_STRING
|
|
67
|
+
: STEP_ARGUMENT_LABELS.DATA_TABLE;
|
|
68
|
+
}
|
|
69
|
+
return step;
|
|
70
|
+
}
|
|
71
|
+
function createTestExecutionResult() {
|
|
72
|
+
return {
|
|
73
|
+
status: 'passed',
|
|
74
|
+
start: Date.now()
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function createHookResult(result) {
|
|
78
|
+
return {
|
|
79
|
+
duration: (Date.now() - result.start),
|
|
80
|
+
message: result.error?.message,
|
|
81
|
+
status: result.status.toUpperCase(),
|
|
82
|
+
exception: result.error
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function createScenarioAnnotation(testCase) {
|
|
86
|
+
const tag = [...new Set(testCase.tags.map((item) => item.name))];
|
|
87
|
+
return [
|
|
88
|
+
{ type: ANNOTATION_TYPES.NAME, description: testCase.name },
|
|
89
|
+
{ type: ANNOTATION_TYPES.URI, description: testCase.uri },
|
|
90
|
+
{ type: ANNOTATION_TYPES.TAGS, description: JSON.stringify(tag) }
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
function createScenarioTags(testCase) {
|
|
94
|
+
return [...new Set(testCase.tags.map((item) => item.name))];
|
|
95
|
+
}
|
|
96
|
+
function createCaseHookPayload(feature, testCase) {
|
|
97
|
+
return {
|
|
98
|
+
gherkinDocument: feature.gherkinDocument,
|
|
99
|
+
pickle: testCase
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
async function executeCaseHooks(test, hooks, world, testCase, defaultHookName, createPayload) {
|
|
103
|
+
for (const hook of hooks) {
|
|
104
|
+
if (!hook.appliesToTestCase(testCase)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const hookName = hook.name ?? defaultHookName;
|
|
108
|
+
const location = getLine(hook);
|
|
109
|
+
await test.step(hookName, () => hook.code.apply(world, [createPayload(hook)]), location);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function executeStepHooks(test, hooks, world, testCase, hookName, createPayload) {
|
|
113
|
+
for (const hook of hooks) {
|
|
114
|
+
if (!hook.appliesToTestCase(testCase)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const location = getLine(hook);
|
|
118
|
+
await test.step(hookName, () => hook.code.apply(world, [createPayload(hook)]), location);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function createStepHookParameter(feature, testCase, pickleStep, result) {
|
|
122
|
+
return {
|
|
123
|
+
gherkinDocument: feature.gherkinDocument,
|
|
124
|
+
testCaseStartedId: DEFAULT_VALUES.TEST_CASE_ID,
|
|
125
|
+
testStepId: DEFAULT_VALUES.TEST_STEP_ID,
|
|
126
|
+
pickle: testCase,
|
|
127
|
+
pickleStep,
|
|
128
|
+
result: createHookResult(result)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function createCaseHookParameter(feature, testCase, result) {
|
|
132
|
+
return {
|
|
133
|
+
gherkinDocument: feature.gherkinDocument,
|
|
134
|
+
testCaseStartedId: DEFAULT_VALUES.TEST_CASE_ID,
|
|
135
|
+
pickle: testCase,
|
|
136
|
+
result: createHookResult(result)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function findSingleStepDefinition(supportCodeLibrary, pickleStep) {
|
|
140
|
+
const matchingSteps = supportCodeLibrary.stepDefinitions
|
|
141
|
+
.filter((stepDefinition) => stepDefinition.matchesStepName(pickleStep.text));
|
|
142
|
+
if (matchingSteps.length === 0) {
|
|
143
|
+
throw new Error(`Step '${pickleStep.text}' is not defined`);
|
|
144
|
+
}
|
|
145
|
+
if (matchingSteps.length > 1) {
|
|
146
|
+
throw new Error(`Step '${pickleStep.text}' matches multiple step definitions`);
|
|
147
|
+
}
|
|
148
|
+
return matchingSteps[0];
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Executes before all hooks
|
|
152
|
+
*/
|
|
153
|
+
function executeBeforeAllHooks(test, hooks) {
|
|
154
|
+
if (hooks.length === 0)
|
|
155
|
+
return;
|
|
156
|
+
test.beforeAll(async () => {
|
|
157
|
+
for (const hook of hooks) {
|
|
158
|
+
const location = getLine(hook);
|
|
159
|
+
await test.step(HOOK_NAMES.BEFORE_ALL, () => hook.code.apply({}), location);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Executes after all hooks
|
|
165
|
+
*/
|
|
166
|
+
function executeAfterAllHooks(test, hooks) {
|
|
167
|
+
if (hooks.length === 0)
|
|
168
|
+
return;
|
|
169
|
+
test.afterAll(async () => {
|
|
170
|
+
for (const hook of hooks) {
|
|
171
|
+
const location = getLine(hook);
|
|
172
|
+
await test.step(HOOK_NAMES.AFTER_ALL, () => hook.code.apply({}), location);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Main configuration function that sets up Cucumber adapter for Playwright
|
|
178
|
+
*/
|
|
179
|
+
function defineConfig(config) {
|
|
180
|
+
const { features, supportCodeLibrary } = (0, loader_1.load)(config);
|
|
181
|
+
const fixture = new supportCodeLibrary.World({ config });
|
|
182
|
+
const test = fixture.test;
|
|
183
|
+
executeBeforeAllHooks(test, supportCodeLibrary.beforeTestRunHookDefinitions);
|
|
184
|
+
for (const feature of features) {
|
|
185
|
+
const tests = feature.tests;
|
|
186
|
+
test.describe(feature.feature, () => {
|
|
187
|
+
for (const testCase of tests) {
|
|
188
|
+
const tag = createScenarioTags(testCase);
|
|
189
|
+
const annotation = createScenarioAnnotation(testCase);
|
|
190
|
+
const testBody = async (fixtures) => {
|
|
191
|
+
const world = new supportCodeLibrary.World({
|
|
192
|
+
log,
|
|
193
|
+
attach,
|
|
194
|
+
supportCodeLibrary,
|
|
195
|
+
config
|
|
196
|
+
});
|
|
197
|
+
world.init(fixtures);
|
|
198
|
+
const result = createTestExecutionResult();
|
|
199
|
+
await executeCaseHooks(test, supportCodeLibrary.beforeTestCaseHookDefinitions, world, testCase, HOOK_NAMES.BEFORE, () => createCaseHookPayload(feature, testCase));
|
|
200
|
+
try {
|
|
201
|
+
for (const pickleStep of testCase.steps) {
|
|
202
|
+
if (result.status !== 'passed') {
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
const step = findSingleStepDefinition(supportCodeLibrary, pickleStep);
|
|
206
|
+
const location = getLine(step);
|
|
207
|
+
await test.step(stepName(pickleStep), async () => {
|
|
208
|
+
await executeStepHooks(test, supportCodeLibrary.beforeTestStepHookDefinitions, world, testCase, HOOK_NAMES.BEFORE_STEP, () => ({
|
|
209
|
+
gherkinDocument: feature.gherkinDocument,
|
|
210
|
+
pickle: testCase,
|
|
211
|
+
pickleStep
|
|
212
|
+
}));
|
|
213
|
+
const { parameters } = await step.getInvocationParameters({
|
|
214
|
+
step: {
|
|
215
|
+
text: pickleStep.text,
|
|
216
|
+
argument: pickleStep.argument
|
|
217
|
+
},
|
|
218
|
+
world
|
|
219
|
+
});
|
|
220
|
+
try {
|
|
221
|
+
await step.code.apply(world, parameters);
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
result.status = 'failed';
|
|
225
|
+
result.error = err;
|
|
226
|
+
throw err;
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
await executeStepHooks(test, supportCodeLibrary.afterTestStepHookDefinitions, world, testCase, HOOK_NAMES.AFTER_STEP, () => createStepHookParameter(feature, testCase, pickleStep, result));
|
|
230
|
+
}
|
|
231
|
+
}, location);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
finally {
|
|
235
|
+
await executeCaseHooks(test, supportCodeLibrary.afterTestCaseHookDefinitions, world, testCase, HOOK_NAMES.AFTER, () => createCaseHookParameter(feature, testCase, result));
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
testBody.toString = () => fixture.init.toString();
|
|
239
|
+
test(testCase.name, { tag, annotation }, testBody);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
executeAfterAllHooks(test, supportCodeLibrary.afterTestRunHookDefinitions);
|
|
244
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate cucumber tag expression to playwright grep
|
|
3
|
+
* @param {string} tagExpression
|
|
4
|
+
* @example
|
|
5
|
+
* import { tags } from '@qavajs/playwright-runner-adapter';
|
|
6
|
+
* export default defineConfig({
|
|
7
|
+
* grep: tags('@oneTag and @anotherTag')
|
|
8
|
+
* });
|
|
9
|
+
*/
|
|
10
|
+
export declare function tags(tagExpression: string): RegExp;
|
|
11
|
+
/**
|
|
12
|
+
* Filter test cases by name
|
|
13
|
+
* @param {(testName: string) => boolean} predicate
|
|
14
|
+
* import { filter } from '@qavajs/playwright-runner-adapter';
|
|
15
|
+
* export default defineConfig({
|
|
16
|
+
* grep: filter(name => name.includes('login test'))
|
|
17
|
+
* });
|
|
18
|
+
*/
|
|
19
|
+
export declare function filter(predicate: (testName: string) => boolean): RegExp;
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
exports.filter = filter;
|
|
8
|
+
const tag_expressions_1 = __importDefault(require("@cucumber/tag-expressions"));
|
|
9
|
+
class TagExpression extends RegExp {
|
|
10
|
+
tagExpression;
|
|
11
|
+
expressionNode;
|
|
12
|
+
constructor(tagExpression) {
|
|
13
|
+
super('');
|
|
14
|
+
this.tagExpression = tagExpression;
|
|
15
|
+
this.expressionNode = (0, tag_expressions_1.default)(this.tagExpression);
|
|
16
|
+
}
|
|
17
|
+
test(testName) {
|
|
18
|
+
const tokens = testName.split(/\s+/);
|
|
19
|
+
return this.expressionNode.evaluate(tokens);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Translate cucumber tag expression to playwright grep
|
|
24
|
+
* @param {string} tagExpression
|
|
25
|
+
* @example
|
|
26
|
+
* import { tags } from '@qavajs/playwright-runner-adapter';
|
|
27
|
+
* export default defineConfig({
|
|
28
|
+
* grep: tags('@oneTag and @anotherTag')
|
|
29
|
+
* });
|
|
30
|
+
*/
|
|
31
|
+
function tags(tagExpression) {
|
|
32
|
+
return new TagExpression(tagExpression);
|
|
33
|
+
}
|
|
34
|
+
class Filter extends RegExp {
|
|
35
|
+
predicate;
|
|
36
|
+
constructor(predicate) {
|
|
37
|
+
super('');
|
|
38
|
+
this.predicate = predicate;
|
|
39
|
+
this.predicate = predicate;
|
|
40
|
+
}
|
|
41
|
+
test(testName) {
|
|
42
|
+
return this.predicate(testName);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Filter test cases by name
|
|
47
|
+
* @param {(testName: string) => boolean} predicate
|
|
48
|
+
* import { filter } from '@qavajs/playwright-runner-adapter';
|
|
49
|
+
* export default defineConfig({
|
|
50
|
+
* grep: filter(name => name.includes('login test'))
|
|
51
|
+
* });
|
|
52
|
+
*/
|
|
53
|
+
function filter(predicate) {
|
|
54
|
+
return new Filter(predicate);
|
|
55
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./PlaywrightWorld"), exports);
|
|
18
|
+
__exportStar(require("./filter"), exports);
|
|
19
|
+
__exportStar(require("./Template"), exports);
|
|
20
|
+
__exportStar(require("@cucumber/cucumber"), exports);
|
|
21
|
+
__exportStar(require("./cucumberAdapter"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Pickle, GherkinDocument } from '@cucumber/messages';
|
|
2
|
+
type Feature = {
|
|
3
|
+
feature?: string;
|
|
4
|
+
gherkinDocument: GherkinDocument;
|
|
5
|
+
tests: readonly Pickle[];
|
|
6
|
+
uri: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function loadFeatures(globPattern: string[]): Feature[];
|
|
9
|
+
export declare function loadStepDefinitions(globPattern: string[]): import("@cucumber/cucumber/lib/support_code_library_builder/types").SupportCodeLibrary;
|
|
10
|
+
export declare function load(config: any): {
|
|
11
|
+
features: Feature[];
|
|
12
|
+
supportCodeLibrary: import("@cucumber/cucumber/lib/support_code_library_builder/types").SupportCodeLibrary;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadFeatures = loadFeatures;
|
|
4
|
+
exports.loadStepDefinitions = loadStepDefinitions;
|
|
5
|
+
exports.load = load;
|
|
6
|
+
const node_fs_1 = require("node:fs");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const node_crypto_1 = require("node:crypto");
|
|
9
|
+
const gherkin_1 = require("@cucumber/gherkin");
|
|
10
|
+
const cucumber_1 = require("@cucumber/cucumber");
|
|
11
|
+
const glob_1 = require("glob");
|
|
12
|
+
const PlaywrightWorld_1 = require("./PlaywrightWorld");
|
|
13
|
+
const uuidFn = () => (0, node_crypto_1.randomUUID)();
|
|
14
|
+
const builder = new gherkin_1.AstBuilder(uuidFn);
|
|
15
|
+
const matcher = new gherkin_1.GherkinClassicTokenMatcher();
|
|
16
|
+
const parser = new gherkin_1.Parser(builder, matcher);
|
|
17
|
+
function duplicates(tests) {
|
|
18
|
+
const counts = {};
|
|
19
|
+
return tests.map(item => {
|
|
20
|
+
const name = item.name;
|
|
21
|
+
if (!(name in counts)) {
|
|
22
|
+
counts[name] = 1;
|
|
23
|
+
}
|
|
24
|
+
if (counts[name] > 1) {
|
|
25
|
+
item.name = `${item.name} ${counts[name]}`;
|
|
26
|
+
}
|
|
27
|
+
counts[name] = counts[name] + 1;
|
|
28
|
+
return item;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function loadFeatures(globPattern) {
|
|
32
|
+
const files = (0, glob_1.globSync)(globPattern);
|
|
33
|
+
return files.map(file => {
|
|
34
|
+
const filePath = (0, node_path_1.resolve)(file);
|
|
35
|
+
const gherkinDocument = parser.parse((0, node_fs_1.readFileSync)(filePath, 'utf-8'));
|
|
36
|
+
return {
|
|
37
|
+
feature: gherkinDocument.feature?.name,
|
|
38
|
+
uri: filePath,
|
|
39
|
+
gherkinDocument,
|
|
40
|
+
tests: duplicates((0, gherkin_1.compile)(gherkinDocument, file, uuidFn))
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function loadStepDefinitions(globPattern) {
|
|
45
|
+
cucumber_1.supportCodeLibraryBuilder.reset(process.cwd(), uuidFn);
|
|
46
|
+
cucumber_1.supportCodeLibraryBuilder.methods.setWorldConstructor(PlaywrightWorld_1.PlaywrightWorld);
|
|
47
|
+
const files = (0, glob_1.globSync)(globPattern);
|
|
48
|
+
for (const file of files) {
|
|
49
|
+
const filePath = (0, node_path_1.resolve)(file);
|
|
50
|
+
require(filePath);
|
|
51
|
+
}
|
|
52
|
+
return cucumber_1.supportCodeLibraryBuilder.finalize();
|
|
53
|
+
}
|
|
54
|
+
function load(config) {
|
|
55
|
+
const features = loadFeatures(config.paths);
|
|
56
|
+
const supportCodeLibrary = loadStepDefinitions([
|
|
57
|
+
...(config.requireModules ?? []),
|
|
58
|
+
...(config.require ?? []),
|
|
59
|
+
...(config.import ?? [])
|
|
60
|
+
]);
|
|
61
|
+
return { features, supportCodeLibrary };
|
|
62
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qavajs/playwright-runner-adapter",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "adapter for playwright test runner",
|
|
5
5
|
"main": "adapter/index.js",
|
|
6
6
|
"types": "adapter/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"build": "tsc",
|
|
8
|
+
"build": "tsc && tsc --project tsconfig.js.json",
|
|
9
9
|
"test:ui": "playwright test --config test/playwright.config.ts --ui",
|
|
10
|
-
"test:e2e": "playwright test --config test/playwright
|
|
10
|
+
"test:e2e": "playwright test --config test/playwright.config.ts --project parallel --project serial"
|
|
11
11
|
},
|
|
12
12
|
"author": "Alexandr Galichenko",
|
|
13
13
|
"license": "MIT",
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@cucumber/gherkin": "^38.0.0",
|
|
23
23
|
"@cucumber/tag-expressions": "^9.0.0",
|
|
24
|
-
"glob": "^13.0.
|
|
24
|
+
"glob": "^13.0.3",
|
|
25
25
|
"@cucumber/cucumber": "^12.6.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@playwright/test": "^1.58.
|
|
29
|
-
"@types/node": "^25.2.
|
|
28
|
+
"@playwright/test": "^1.58.2",
|
|
29
|
+
"@types/node": "^25.2.3",
|
|
30
30
|
"typescript": "^5.9.3"
|
|
31
31
|
},
|
|
32
32
|
"keywords": [
|
package/src/PlaywrightWorld.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { APIRequestContext, Browser, BrowserContext, Page, test, expect } from '
|
|
|
5
5
|
*/
|
|
6
6
|
export class TestWorld {
|
|
7
7
|
log!: (data: any) => void;
|
|
8
|
-
attach!: (data: any, details?: { fileName?: string, mediaType: string }) => void
|
|
8
|
+
attach!: (data: any, details?: { fileName?: string, mediaType: string }) => Promise<void>;
|
|
9
9
|
parameters!: string;
|
|
10
10
|
config: any;
|
|
11
11
|
supportCodeLibrary!: any;
|
|
@@ -17,6 +17,7 @@ export class TestWorld {
|
|
|
17
17
|
this.attach = options.attach;
|
|
18
18
|
this.parameters = options.parameters;
|
|
19
19
|
this.supportCodeLibrary = options.supportCodeLibrary;
|
|
20
|
+
this.config = options.config;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
async executeStep(this: any, text: string, extraParam?: any) {
|
|
@@ -43,9 +44,10 @@ export class PlaywrightWorld extends TestWorld {
|
|
|
43
44
|
browserName!: string;
|
|
44
45
|
request!: APIRequestContext;
|
|
45
46
|
|
|
46
|
-
init: ({ [fixture: string]: any }) = ({ browser, context, page }: { browser: Browser, context: BrowserContext, page: Page }) => {
|
|
47
|
+
init: ({ [fixture: string]: any }) = ({ browser, context, page, request }: { browser: Browser, context: BrowserContext, page: Page, request: APIRequestContext }) => {
|
|
47
48
|
this.browser = browser;
|
|
48
49
|
this.context = context;
|
|
49
50
|
this.page = page;
|
|
51
|
+
this.request = request;
|
|
50
52
|
}
|
|
51
53
|
}
|