@zohodesk/testinglibrary 0.1.8-exp-bdd-v1 → 0.1.8-exp.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/.babelrc +18 -18
- package/.eslintrc.js +31 -27
- package/.prettierrc +5 -5
- package/README.md +17 -17
- package/bin/cli.js +2 -2
- package/build/bdd-framework/cli/commands/env.js +4 -4
- package/build/bdd-framework/cli/commands/test.js +6 -2
- package/build/bdd-framework/cli/options.js +4 -4
- package/build/bdd-framework/cli/worker.js +3 -3
- package/build/bdd-framework/config/dir.js +6 -6
- package/build/bdd-framework/config/env.js +5 -4
- package/build/bdd-framework/config/index.js +2 -2
- package/build/bdd-framework/config/lang.js +14 -0
- package/build/bdd-framework/cucumber/buildStepDefinition.js +3 -3
- package/build/bdd-framework/cucumber/loadSnippetBuilder.js +3 -3
- package/build/bdd-framework/cucumber/loadSources.js +9 -9
- package/build/bdd-framework/cucumber/loadSteps.js +8 -3
- package/build/bdd-framework/decorators.js +2 -2
- package/build/bdd-framework/gen/fixtures.js +48 -0
- package/build/bdd-framework/gen/formatter.js +64 -17
- package/build/bdd-framework/gen/i18n.js +9 -5
- package/build/bdd-framework/gen/index.js +9 -8
- package/build/bdd-framework/gen/testFile.js +121 -55
- package/build/bdd-framework/gen/testNode.js +19 -6
- package/build/bdd-framework/gen/testPoms.js +49 -39
- package/build/bdd-framework/hooks/scenario.js +107 -0
- package/build/bdd-framework/hooks/worker.js +83 -0
- package/build/bdd-framework/playwright/fixtureParameterNames.js +27 -11
- package/build/bdd-framework/playwright/getLocationInFile.js +17 -11
- package/build/bdd-framework/playwright/loadConfig.js +3 -3
- package/build/bdd-framework/playwright/testTypeImpl.js +19 -15
- package/build/bdd-framework/playwright/transform.js +10 -6
- package/build/bdd-framework/playwright/utils.js +3 -6
- package/build/bdd-framework/run/StepInvoker.js +73 -0
- package/build/bdd-framework/run/bddFixtures.js +118 -55
- package/build/bdd-framework/run/bddWorld.js +24 -36
- package/build/bdd-framework/snippets/index.js +5 -3
- package/build/bdd-framework/snippets/snippetSyntax.js +3 -1
- package/build/bdd-framework/snippets/snippetSyntaxTs.js +4 -4
- package/build/bdd-framework/stepDefinitions/createBdd.js +30 -13
- package/build/bdd-framework/stepDefinitions/decorators/{poms.js → class.js} +13 -9
- package/build/bdd-framework/stepDefinitions/decorators/steps.js +14 -8
- package/build/bdd-framework/stepDefinitions/defineStep.js +5 -4
- package/build/bdd-framework/stepDefinitions/stepConfig.js +5 -5
- package/build/bdd-framework/utils/exit.js +26 -18
- package/build/bdd-framework/utils/index.js +30 -4
- package/build/bdd-framework/utils/jsStringWrap.js +9 -9
- package/build/bdd-framework/utils/logger.js +5 -3
- package/build/core/playwright/builtInFixtures/addTags.js +19 -0
- package/build/core/playwright/builtInFixtures/cacheLayer.js +13 -0
- package/build/core/playwright/builtInFixtures/context.js +15 -0
- package/build/core/playwright/builtInFixtures/index.js +26 -0
- package/build/core/playwright/builtInFixtures/page.js +51 -0
- package/build/core/playwright/clear-caches.js +29 -0
- package/build/core/playwright/custom-commands.js +1 -1
- package/build/core/playwright/index.js +6 -74
- package/build/core/playwright/readConfigFile.js +37 -30
- package/build/core/playwright/report-generator.js +2 -1
- package/build/core/playwright/setup/config-creator.js +43 -20
- package/build/core/playwright/setup/config-utils.js +30 -0
- package/build/core/playwright/setup/custom-reporter.js +109 -0
- package/build/core/playwright/tag-processor.js +68 -0
- package/build/core/playwright/test-runner.js +8 -12
- package/build/index.d.ts +60 -5
- package/build/index.js +18 -12
- package/build/lib/cli.js +10 -1
- package/build/parser/sample.feature +34 -34
- package/build/parser/sample.spec.js +18 -18
- package/build/setup-folder-structure/helper.js +35 -0
- package/build/setup-folder-structure/reportEnhancement/addonScript.html +25 -0
- package/build/setup-folder-structure/reportEnhancement/reportAlteration.js +25 -0
- package/build/setup-folder-structure/samples/auth-setup-sample.js +72 -72
- package/build/setup-folder-structure/samples/authUsers-sample.json +8 -8
- package/build/setup-folder-structure/samples/env-config-sample.json +20 -20
- package/build/setup-folder-structure/samples/git-ignore.sample.js +36 -32
- package/build/setup-folder-structure/samples/uat-config-sample.js +44 -43
- package/build/setup-folder-structure/setupProject.js +10 -5
- package/build/utils/cliArgsToObject.js +29 -25
- package/build/utils/fileUtils.js +15 -4
- package/changelog.md +137 -74
- package/jest.config.js +63 -63
- package/npm-shrinkwrap.json +6469 -7781
- package/package.json +55 -54
- package/playwright.config.js +112 -112
- package/build/bdd-framework/cucumber/gherkin.d.ts +0 -45
- package/build/bdd-framework/gen/poms.js +0 -46
- package/build/bdd-framework/stepDefinitions/createDecorators.js +0 -108
- package/build/bdd-poc/core-runner/exportMethods.js +0 -20
- package/build/bdd-poc/core-runner/stepDefinitions.js +0 -53
- package/build/bdd-poc/main.js +0 -10
- package/build/bdd-poc/runner.js +0 -19
- package/build/bdd-poc/test/cucumber/featureFileParer.js +0 -81
- package/build/bdd-poc/test/stepGenerate/stepFileGenerate.js +0 -36
- package/build/bdd-poc/test/stepGenerate/stepsnippets.js +0 -43
- package/build/bdd-poc/test/testDataMap.js +0 -98
- package/build/bdd-poc/test/testStructure.js +0 -83
- package/build/bdd-poc/utils/stringManipulation.js +0 -19
|
@@ -10,15 +10,18 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
10
10
|
var _formatter = require("./formatter");
|
|
11
11
|
var _i18n = require("./i18n");
|
|
12
12
|
var _loadSteps = require("../cucumber/loadSteps");
|
|
13
|
-
var _createBdd = require("../stepDefinitions/createBdd");
|
|
14
13
|
var _index = require("@cucumber/cucumber/lib/formatter/helpers/index");
|
|
15
14
|
var _utils = require("../utils");
|
|
16
15
|
var _testPoms = require("./testPoms");
|
|
17
16
|
var _testNode = require("./testNode");
|
|
18
17
|
var _stepConfig = require("../stepDefinitions/stepConfig");
|
|
19
18
|
var _exit = require("../utils/exit");
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
var _fixtures = require("./fixtures");
|
|
20
|
+
var _scenario = require("../hooks/scenario");
|
|
21
|
+
var _worker = require("../hooks/worker");
|
|
22
|
+
var _lang = require("../config/lang");
|
|
23
|
+
/**
|
|
24
|
+
* Generate test code.
|
|
22
25
|
*/
|
|
23
26
|
|
|
24
27
|
class TestFile {
|
|
@@ -26,6 +29,7 @@ class TestFile {
|
|
|
26
29
|
lines = [];
|
|
27
30
|
i18nKeywordsMap;
|
|
28
31
|
formatter;
|
|
32
|
+
hasCucumberStyle = false;
|
|
29
33
|
testNodes = [];
|
|
30
34
|
hasCustomTest = false;
|
|
31
35
|
undefinedSteps = [];
|
|
@@ -37,7 +41,9 @@ class TestFile {
|
|
|
37
41
|
const {
|
|
38
42
|
uri
|
|
39
43
|
} = this.options.doc;
|
|
40
|
-
if (!uri)
|
|
44
|
+
if (!uri) {
|
|
45
|
+
throw new Error(`Document without uri`);
|
|
46
|
+
}
|
|
41
47
|
return uri;
|
|
42
48
|
}
|
|
43
49
|
get content() {
|
|
@@ -45,7 +51,10 @@ class TestFile {
|
|
|
45
51
|
}
|
|
46
52
|
get language() {
|
|
47
53
|
var _this$options$doc$fea;
|
|
48
|
-
return ((_this$options$doc$fea = this.options.doc.feature) === null || _this$options$doc$fea === void 0 ? void 0 : _this$options$doc$fea.language) ||
|
|
54
|
+
return ((_this$options$doc$fea = this.options.doc.feature) === null || _this$options$doc$fea === void 0 ? void 0 : _this$options$doc$fea.language) || _lang.LANG_EN;
|
|
55
|
+
}
|
|
56
|
+
get isEnglish() {
|
|
57
|
+
return (0, _lang.isEnglish)(this.language);
|
|
49
58
|
}
|
|
50
59
|
get config() {
|
|
51
60
|
return this.options.config;
|
|
@@ -55,14 +64,18 @@ class TestFile {
|
|
|
55
64
|
}
|
|
56
65
|
build() {
|
|
57
66
|
this.loadI18nKeywords();
|
|
58
|
-
this.lines = [...this.getFileHeader(),
|
|
67
|
+
this.lines = [...this.getFileHeader(),
|
|
68
|
+
// prettier-ignore
|
|
69
|
+
...this.getRootSuite(), ...this.getFileFixtures()];
|
|
59
70
|
return this;
|
|
60
71
|
}
|
|
61
72
|
save() {
|
|
62
73
|
const dir = _path.default.dirname(this.outputPath);
|
|
63
|
-
if (!_fs.default.existsSync(dir))
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
if (!_fs.default.existsSync(dir)) {
|
|
75
|
+
_fs.default.mkdirSync(dir, {
|
|
76
|
+
recursive: true
|
|
77
|
+
});
|
|
78
|
+
}
|
|
66
79
|
_fs.default.writeFileSync(this.outputPath, this.content);
|
|
67
80
|
}
|
|
68
81
|
getFileHeader() {
|
|
@@ -70,7 +83,7 @@ class TestFile {
|
|
|
70
83
|
return this.formatter.fileHeader(this.sourceFile, importTestFrom);
|
|
71
84
|
}
|
|
72
85
|
loadI18nKeywords() {
|
|
73
|
-
if (this.
|
|
86
|
+
if (!this.isEnglish) {
|
|
74
87
|
this.i18nKeywordsMap = (0, _i18n.getKeywordsMap)(this.language);
|
|
75
88
|
}
|
|
76
89
|
}
|
|
@@ -78,7 +91,9 @@ class TestFile {
|
|
|
78
91
|
const {
|
|
79
92
|
importTestFrom
|
|
80
93
|
} = this.config;
|
|
81
|
-
if (!importTestFrom)
|
|
94
|
+
if (!importTestFrom) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
82
97
|
const {
|
|
83
98
|
file,
|
|
84
99
|
varName
|
|
@@ -90,37 +105,46 @@ class TestFile {
|
|
|
90
105
|
};
|
|
91
106
|
}
|
|
92
107
|
getFileFixtures() {
|
|
93
|
-
return this.formatter.useFixtures([...this.formatter.testFixture(), ...this.formatter.tagsFixture(this.testNodes)]);
|
|
108
|
+
return this.formatter.useFixtures([...this.formatter.testFixture(), ...(!this.isEnglish ? this.formatter.langFixture(this.language) : []), ...((0, _scenario.hasScenarioHooks)() || this.hasCucumberStyle ? this.formatter.bddWorldFixtures() : []), ...this.formatter.scenarioHookFixtures((0, _scenario.getScenarioHooksFixtures)()), ...this.formatter.workerHookFixtures((0, _worker.getWorkerHooksFixtures)()), ...this.formatter.tagsFixture(this.testNodes)]);
|
|
94
109
|
}
|
|
95
110
|
getRootSuite() {
|
|
96
111
|
const {
|
|
97
112
|
feature
|
|
98
113
|
} = this.options.doc;
|
|
99
|
-
if (!feature)
|
|
114
|
+
if (!feature) {
|
|
115
|
+
throw new Error(`Document without feature.`);
|
|
116
|
+
}
|
|
100
117
|
return this.getSuite(feature);
|
|
101
118
|
}
|
|
102
|
-
/**
|
|
103
|
-
* Generate test.describe suite for root Feature or Rule
|
|
119
|
+
/**
|
|
120
|
+
* Generate test.describe suite for root Feature or Rule
|
|
104
121
|
*/
|
|
105
122
|
getSuite(feature, parent) {
|
|
106
123
|
const node = new _testNode.TestNode(feature, parent);
|
|
124
|
+
if (node.isSkipped()) {
|
|
125
|
+
return this.formatter.suite(node, []);
|
|
126
|
+
}
|
|
107
127
|
const lines = [];
|
|
108
|
-
// const { backgrounds, rules, scenarios } =
|
|
109
|
-
// bgFixtures, bgTags - used as fixture hints for decorator steps
|
|
110
128
|
feature.children.forEach(child => lines.push(...this.getSuiteChild(child, node)));
|
|
111
129
|
return this.formatter.suite(node, lines);
|
|
112
130
|
}
|
|
113
131
|
getSuiteChild(child, parent) {
|
|
114
|
-
if ('rule' in child && child.rule)
|
|
115
|
-
|
|
116
|
-
|
|
132
|
+
if ('rule' in child && child.rule) {
|
|
133
|
+
return this.getSuite(child.rule, parent);
|
|
134
|
+
}
|
|
135
|
+
if (child.background) {
|
|
136
|
+
return this.getBeforeEach(child.background, parent);
|
|
137
|
+
}
|
|
138
|
+
if (child.scenario) {
|
|
139
|
+
return this.getScenarioLines(child.scenario, parent);
|
|
140
|
+
}
|
|
117
141
|
throw new Error(`Empty child: ${JSON.stringify(child)}`);
|
|
118
142
|
}
|
|
119
143
|
getScenarioLines(scenario, parent) {
|
|
120
144
|
return this.isOutline(scenario) ? this.getOutlineSuite(scenario, parent) : this.getTest(scenario, parent);
|
|
121
145
|
}
|
|
122
|
-
/**
|
|
123
|
-
* Generate test.beforeEach for Background
|
|
146
|
+
/**
|
|
147
|
+
* Generate test.beforeEach for Background
|
|
124
148
|
*/
|
|
125
149
|
getBeforeEach(bg, parent) {
|
|
126
150
|
const node = new _testNode.TestNode({
|
|
@@ -133,15 +157,18 @@ class TestFile {
|
|
|
133
157
|
} = this.getSteps(bg, node.tags);
|
|
134
158
|
return this.formatter.beforeEach(fixtures, lines);
|
|
135
159
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Generate test.describe suite for Scenario Outline
|
|
160
|
+
/**
|
|
161
|
+
* Generate test.describe suite for Scenario Outline
|
|
138
162
|
*/
|
|
139
163
|
getOutlineSuite(scenario, parent) {
|
|
140
164
|
const node = new _testNode.TestNode(scenario, parent);
|
|
165
|
+
if (node.isSkipped()) {
|
|
166
|
+
return this.formatter.suite(node, []);
|
|
167
|
+
}
|
|
141
168
|
const lines = [];
|
|
142
169
|
let exampleIndex = 0;
|
|
143
170
|
scenario.examples.forEach(examples => {
|
|
144
|
-
const titleFormat = this.getExamplesTitleFormat(examples);
|
|
171
|
+
const titleFormat = this.getExamplesTitleFormat(scenario, examples);
|
|
145
172
|
examples.tableBody.forEach(exampleRow => {
|
|
146
173
|
const testTitle = this.getOutlineTestTitle(titleFormat, examples, exampleRow, ++exampleIndex);
|
|
147
174
|
const testLines = this.getOutlineTest(scenario, examples, exampleRow, testTitle, node);
|
|
@@ -150,8 +177,8 @@ class TestFile {
|
|
|
150
177
|
});
|
|
151
178
|
return this.formatter.suite(node, lines);
|
|
152
179
|
}
|
|
153
|
-
/**
|
|
154
|
-
* Generate test from Examples row of Scenario Outline
|
|
180
|
+
/**
|
|
181
|
+
* Generate test from Examples row of Scenario Outline
|
|
155
182
|
*/
|
|
156
183
|
// eslint-disable-next-line max-params
|
|
157
184
|
getOutlineTest(scenario, examples, exampleRow, title, parent) {
|
|
@@ -159,7 +186,12 @@ class TestFile {
|
|
|
159
186
|
name: title,
|
|
160
187
|
tags: examples.tags
|
|
161
188
|
}, parent);
|
|
162
|
-
if (this.skipByTagsExpression(node))
|
|
189
|
+
if (this.skipByTagsExpression(node)) {
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
if (node.isSkipped()) {
|
|
193
|
+
return this.formatter.test(node, new Set(), []);
|
|
194
|
+
}
|
|
163
195
|
this.testNodes.push(node);
|
|
164
196
|
const {
|
|
165
197
|
fixtures,
|
|
@@ -167,12 +199,17 @@ class TestFile {
|
|
|
167
199
|
} = this.getSteps(scenario, node.tags, exampleRow.id);
|
|
168
200
|
return this.formatter.test(node, fixtures, lines);
|
|
169
201
|
}
|
|
170
|
-
/**
|
|
171
|
-
* Generate test from Scenario
|
|
202
|
+
/**
|
|
203
|
+
* Generate test from Scenario
|
|
172
204
|
*/
|
|
173
205
|
getTest(scenario, parent) {
|
|
174
206
|
const node = new _testNode.TestNode(scenario, parent);
|
|
175
|
-
if (this.skipByTagsExpression(node))
|
|
207
|
+
if (this.skipByTagsExpression(node)) {
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
if (node.isSkipped()) {
|
|
211
|
+
return this.formatter.test(node, new Set(), []);
|
|
212
|
+
}
|
|
176
213
|
this.testNodes.push(node);
|
|
177
214
|
const {
|
|
178
215
|
fixtures,
|
|
@@ -180,8 +217,8 @@ class TestFile {
|
|
|
180
217
|
} = this.getSteps(scenario, node.tags);
|
|
181
218
|
return this.formatter.test(node, fixtures, lines);
|
|
182
219
|
}
|
|
183
|
-
/**
|
|
184
|
-
* Generate test steps
|
|
220
|
+
/**
|
|
221
|
+
* Generate test steps
|
|
185
222
|
*/
|
|
186
223
|
getSteps(scenario, tags, outlineExampleRowId) {
|
|
187
224
|
const testFixtureNames = new Set();
|
|
@@ -230,8 +267,8 @@ class TestFile {
|
|
|
230
267
|
lines
|
|
231
268
|
};
|
|
232
269
|
}
|
|
233
|
-
/**
|
|
234
|
-
* Generate step for Given, When, Then
|
|
270
|
+
/**
|
|
271
|
+
* Generate step for Given, When, Then
|
|
235
272
|
*/
|
|
236
273
|
// eslint-disable-next-line max-statements, complexity
|
|
237
274
|
getStep(step, previousKeywordType, outlineExampleRowId) {
|
|
@@ -242,26 +279,27 @@ class TestFile {
|
|
|
242
279
|
language: this.language,
|
|
243
280
|
previousKeywordType
|
|
244
281
|
});
|
|
245
|
-
|
|
282
|
+
const enKeyword = this.getStepEnglishKeyword(step);
|
|
246
283
|
if (!stepDefinition) {
|
|
247
284
|
this.undefinedSteps.push({
|
|
248
285
|
keywordType,
|
|
249
286
|
step,
|
|
250
287
|
pickleStep
|
|
251
288
|
});
|
|
252
|
-
return this.getMissingStep(
|
|
289
|
+
return this.getMissingStep(enKeyword, keywordType, pickleStep);
|
|
253
290
|
}
|
|
254
291
|
// for cucumber-style stepConfig is undefined
|
|
255
292
|
const stepConfig = (0, _stepConfig.getStepConfig)(stepDefinition);
|
|
256
|
-
if (stepConfig !== null && stepConfig !== void 0 && stepConfig.hasCustomTest)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (!(0, _stepConfig.isPlaywrightStyle)(stepConfig))
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const
|
|
293
|
+
if (stepConfig !== null && stepConfig !== void 0 && stepConfig.hasCustomTest) {
|
|
294
|
+
this.hasCustomTest = true;
|
|
295
|
+
}
|
|
296
|
+
if (!(0, _stepConfig.isPlaywrightStyle)(stepConfig)) {
|
|
297
|
+
this.hasCucumberStyle = true;
|
|
298
|
+
}
|
|
299
|
+
const fixtureNames = this.getStepFixtureNames(stepDefinition);
|
|
300
|
+
const line = (0, _stepConfig.isDecorator)(stepConfig) ? '' : this.formatter.step(enKeyword, pickleStep.text, pickleStep.argument, fixtureNames);
|
|
263
301
|
return {
|
|
264
|
-
keyword,
|
|
302
|
+
keyword: enKeyword,
|
|
265
303
|
keywordType,
|
|
266
304
|
fixtureNames,
|
|
267
305
|
line,
|
|
@@ -288,16 +326,29 @@ class TestFile {
|
|
|
288
326
|
const hasRowId = !outlineExampleRowId || astNodeIds.includes(outlineExampleRowId);
|
|
289
327
|
return hasStepId && hasRowId;
|
|
290
328
|
});
|
|
291
|
-
if (pickleStep)
|
|
329
|
+
if (pickleStep) {
|
|
330
|
+
return pickleStep;
|
|
331
|
+
}
|
|
292
332
|
}
|
|
293
333
|
throw new Error(`Pickle step not found for step: ${step.text}`);
|
|
294
334
|
}
|
|
295
|
-
|
|
296
|
-
const
|
|
297
|
-
const enKeyword =
|
|
298
|
-
if (!enKeyword)
|
|
335
|
+
getStepEnglishKeyword(step) {
|
|
336
|
+
const nativeKeyword = step.keyword.trim();
|
|
337
|
+
const enKeyword = nativeKeyword === '*' ? 'And' : this.getEnglishKeyword(nativeKeyword);
|
|
338
|
+
if (!enKeyword) {
|
|
339
|
+
throw new Error(`Keyword not found: ${nativeKeyword}`);
|
|
340
|
+
}
|
|
299
341
|
return enKeyword;
|
|
300
342
|
}
|
|
343
|
+
getStepFixtureNames(stepDefinition) {
|
|
344
|
+
const stepConfig = (0, _stepConfig.getStepConfig)(stepDefinition);
|
|
345
|
+
if ((0, _stepConfig.isPlaywrightStyle)(stepConfig)) {
|
|
346
|
+
// for decorator steps fixtureNames are defined later in second pass
|
|
347
|
+
return (0, _stepConfig.isDecorator)(stepConfig) ? [] : (0, _fixtures.extractFixtureNames)(stepConfig.fn);
|
|
348
|
+
} else {
|
|
349
|
+
return (0, _fixtures.extractFixtureNamesFromFnBodyMemo)(stepDefinition.code);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
301
352
|
getDecoratorStep(step, testPoms) {
|
|
302
353
|
const {
|
|
303
354
|
keyword,
|
|
@@ -323,11 +374,16 @@ class TestFile {
|
|
|
323
374
|
exampleRow.cells.forEach((cell, index) => {
|
|
324
375
|
var _examples$tableHeader;
|
|
325
376
|
const colName = (_examples$tableHeader = examples.tableHeader) === null || _examples$tableHeader === void 0 || (_examples$tableHeader = _examples$tableHeader.cells[index]) === null || _examples$tableHeader === void 0 ? void 0 : _examples$tableHeader.value;
|
|
326
|
-
if (colName)
|
|
377
|
+
if (colName) {
|
|
378
|
+
params[colName] = cell.value;
|
|
379
|
+
}
|
|
327
380
|
});
|
|
328
381
|
return (0, _utils.template)(titleFormat, params);
|
|
329
382
|
}
|
|
330
|
-
getExamplesTitleFormat(examples) {
|
|
383
|
+
getExamplesTitleFormat(scenario, examples) {
|
|
384
|
+
return this.getExamplesTitleFormatFromComment(examples) || this.getExamplesTitleFormatFromScenarioName(scenario, examples) || this.config.examplesTitleFormat;
|
|
385
|
+
}
|
|
386
|
+
getExamplesTitleFormatFromComment(examples) {
|
|
331
387
|
var _comment$text;
|
|
332
388
|
const {
|
|
333
389
|
line
|
|
@@ -338,12 +394,22 @@ class TestFile {
|
|
|
338
394
|
});
|
|
339
395
|
const commentText = comment === null || comment === void 0 || (_comment$text = comment.text) === null || _comment$text === void 0 ? void 0 : _comment$text.trim();
|
|
340
396
|
const prefix = '# title-format:';
|
|
341
|
-
return commentText !== null && commentText !== void 0 && commentText.startsWith(prefix) ? commentText.replace(prefix, '').trim() :
|
|
397
|
+
return commentText !== null && commentText !== void 0 && commentText.startsWith(prefix) ? commentText.replace(prefix, '').trim() : '';
|
|
398
|
+
}
|
|
399
|
+
getExamplesTitleFormatFromScenarioName(scenario, examples) {
|
|
400
|
+
var _examples$tableHeader2;
|
|
401
|
+
const columnsInScenarioName = (0, _utils.extractTemplateParams)(scenario.name);
|
|
402
|
+
const hasColumnsFromExamples = columnsInScenarioName.length && ((_examples$tableHeader2 = examples.tableHeader) === null || _examples$tableHeader2 === void 0 || (_examples$tableHeader2 = _examples$tableHeader2.cells) === null || _examples$tableHeader2 === void 0 ? void 0 : _examples$tableHeader2.some(cell => {
|
|
403
|
+
return cell.value && columnsInScenarioName.includes(cell.value);
|
|
404
|
+
}));
|
|
405
|
+
return hasColumnsFromExamples ? scenario.name : '';
|
|
342
406
|
}
|
|
343
407
|
skipByTagsExpression(node) {
|
|
344
|
-
var _this$options$tagsExp;
|
|
345
408
|
// see: https://github.com/cucumber/tag-expressions/tree/main/javascript
|
|
346
|
-
|
|
409
|
+
const {
|
|
410
|
+
tagsExpression
|
|
411
|
+
} = this.options;
|
|
412
|
+
return tagsExpression && !tagsExpression.evaluate(node.tags);
|
|
347
413
|
}
|
|
348
414
|
isOutline(scenario) {
|
|
349
415
|
const keyword = this.getEnglishKeyword(scenario.keyword);
|
|
@@ -5,9 +5,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.TestNode = void 0;
|
|
7
7
|
var _utils = require("../utils");
|
|
8
|
-
/**
|
|
9
|
-
* Universal TestNode class of parent-child relations in test file structure.
|
|
10
|
-
* Holds tags and titles path.
|
|
8
|
+
/**
|
|
9
|
+
* Universal TestNode class of parent-child relations in test file structure.
|
|
10
|
+
* Holds tags and titles path.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
const SPECIAL_TAGS = ['@only', '@skip', '@fixme'];
|
|
@@ -23,6 +23,9 @@ class TestNode {
|
|
|
23
23
|
this.title = gherkinNode.name;
|
|
24
24
|
this.titlePath = ((parent === null || parent === void 0 ? void 0 : parent.titlePath) || []).concat([this.title]);
|
|
25
25
|
}
|
|
26
|
+
isSkipped() {
|
|
27
|
+
return this.flags.skip || this.flags.fixme;
|
|
28
|
+
}
|
|
26
29
|
initOwnTags(gherkinNode) {
|
|
27
30
|
const tagNames = (0, _utils.removeDuplicates)(getTagNames(gherkinNode.tags));
|
|
28
31
|
tagNames.forEach(tag => {
|
|
@@ -33,10 +36,20 @@ class TestNode {
|
|
|
33
36
|
}
|
|
34
37
|
});
|
|
35
38
|
}
|
|
39
|
+
// eslint-disable-next-line complexity
|
|
36
40
|
setFlag(tag) {
|
|
37
|
-
|
|
38
|
-
if (tag === '@
|
|
39
|
-
|
|
41
|
+
// in case of several system tags, @only takes precendence
|
|
42
|
+
if (tag === '@only') {
|
|
43
|
+
this.flags = {
|
|
44
|
+
only: true
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (tag === '@skip' && !this.flags.only) {
|
|
48
|
+
this.flags.skip = true;
|
|
49
|
+
}
|
|
50
|
+
if (tag === '@fixme' && !this.flags.only) {
|
|
51
|
+
this.flags.fixme = true;
|
|
52
|
+
}
|
|
40
53
|
}
|
|
41
54
|
}
|
|
42
55
|
exports.TestNode = TestNode;
|
|
@@ -5,29 +5,29 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.TestPoms = void 0;
|
|
7
7
|
exports.buildFixtureTag = buildFixtureTag;
|
|
8
|
-
var
|
|
8
|
+
var _class = require("../stepDefinitions/decorators/class");
|
|
9
9
|
var _exit = require("../utils/exit");
|
|
10
|
-
/**
|
|
11
|
-
* Track PomNodes used in the particular test.
|
|
12
|
-
* To select correct fixture for decorator steps.
|
|
13
|
-
*
|
|
14
|
-
* Idea: try to use the deepest child fixture for parent steps.
|
|
15
|
-
*
|
|
16
|
-
* Example inheritance tree:
|
|
17
|
-
* A
|
|
18
|
-
* / \
|
|
19
|
-
* B C
|
|
20
|
-
* / \ \
|
|
21
|
-
* D E F
|
|
22
|
-
*
|
|
23
|
-
* If test uses steps from classes A and D:
|
|
24
|
-
* -> resolved fixture will be D, even for steps from A.
|
|
25
|
-
*
|
|
26
|
-
* If test uses steps from classes A, D and C:
|
|
27
|
-
* -> error, b/c A has 2 possible fixtures.
|
|
28
|
-
*
|
|
29
|
-
* If test uses steps from classes A and C, but @fixture tag is D:
|
|
30
|
-
* -> error, b/c A has 2 possible fixtures.
|
|
10
|
+
/**
|
|
11
|
+
* Track PomNodes used in the particular test.
|
|
12
|
+
* To select correct fixture for decorator steps.
|
|
13
|
+
*
|
|
14
|
+
* Idea: try to use the deepest child fixture for parent steps.
|
|
15
|
+
*
|
|
16
|
+
* Example inheritance tree:
|
|
17
|
+
* A
|
|
18
|
+
* / \
|
|
19
|
+
* B C
|
|
20
|
+
* / \ \
|
|
21
|
+
* D E F
|
|
22
|
+
*
|
|
23
|
+
* If test uses steps from classes A and D:
|
|
24
|
+
* -> resolved fixture will be D, even for steps from A.
|
|
25
|
+
*
|
|
26
|
+
* If test uses steps from classes A, D and C:
|
|
27
|
+
* -> error, b/c A has 2 possible fixtures.
|
|
28
|
+
*
|
|
29
|
+
* If test uses steps from classes A and C, but @fixture tag is D:
|
|
30
|
+
* -> error, b/c A has 2 possible fixtures.
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
const FIXTURE_TAG_PREFIX = '@fixture:';
|
|
@@ -44,7 +44,7 @@ class TestPoms {
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
addByFixtureName(fixtureName) {
|
|
47
|
-
const pomNode = (0,
|
|
47
|
+
const pomNode = (0, _class.getPomNodeByFixtureName)(fixtureName);
|
|
48
48
|
this.addUsedPom(pomNode, {
|
|
49
49
|
byTag: false
|
|
50
50
|
});
|
|
@@ -52,31 +52,35 @@ class TestPoms {
|
|
|
52
52
|
addByTag(tag) {
|
|
53
53
|
const fixtureName = extractFixtureName(tag);
|
|
54
54
|
if (fixtureName) {
|
|
55
|
-
const pomNode = (0,
|
|
55
|
+
const pomNode = (0, _class.getPomNodeByFixtureName)(fixtureName);
|
|
56
56
|
this.addUsedPom(pomNode, {
|
|
57
57
|
byTag: true
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Resolve all used pomNodes to fixtures.
|
|
63
|
-
* This is needed to handle @fixture: tagged pomNodes
|
|
64
|
-
* that does not have steps in the test, but should be considered.
|
|
61
|
+
/**
|
|
62
|
+
* Resolve all used pomNodes to fixtures.
|
|
63
|
+
* This is needed to handle @fixture: tagged pomNodes
|
|
64
|
+
* that does not have steps in the test, but should be considered.
|
|
65
65
|
*/
|
|
66
66
|
resolveFixtures() {
|
|
67
67
|
this.usedPoms.forEach((_, pomNode) => {
|
|
68
68
|
this.getResolvedFixtures(pomNode);
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Returns fixtures suitable for particular pomNode (actually for step)
|
|
71
|
+
/**
|
|
72
|
+
* Returns fixtures suitable for particular pomNode (actually for step)
|
|
73
73
|
*/
|
|
74
74
|
getResolvedFixtures(pomNode) {
|
|
75
75
|
const usedPom = this.usedPoms.get(pomNode);
|
|
76
|
-
if (usedPom !== null && usedPom !== void 0 && usedPom.fixtures)
|
|
76
|
+
if (usedPom !== null && usedPom !== void 0 && usedPom.fixtures) {
|
|
77
|
+
return usedPom.fixtures;
|
|
78
|
+
}
|
|
77
79
|
// Recursively resolve children fixtures, used in test.
|
|
78
80
|
let childFixtures = [...pomNode.children].map(child => this.getResolvedFixtures(child)).flat();
|
|
79
|
-
if (!usedPom)
|
|
81
|
+
if (!usedPom) {
|
|
82
|
+
return childFixtures;
|
|
83
|
+
}
|
|
80
84
|
if (childFixtures.length) {
|
|
81
85
|
this.verifyChildFixtures(pomNode, usedPom, childFixtures);
|
|
82
86
|
usedPom.fixtures = childFixtures;
|
|
@@ -91,23 +95,29 @@ class TestPoms {
|
|
|
91
95
|
addUsedPom(pomNode, {
|
|
92
96
|
byTag
|
|
93
97
|
}) {
|
|
94
|
-
if (!pomNode)
|
|
98
|
+
if (!pomNode) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
95
101
|
const usedPom = this.usedPoms.get(pomNode);
|
|
96
102
|
if (usedPom) {
|
|
97
|
-
if (byTag && !usedPom.byTag)
|
|
103
|
+
if (byTag && !usedPom.byTag) {
|
|
104
|
+
usedPom.byTag = true;
|
|
105
|
+
}
|
|
98
106
|
} else {
|
|
99
107
|
this.usedPoms.set(pomNode, {
|
|
100
108
|
byTag
|
|
101
109
|
});
|
|
102
110
|
}
|
|
103
111
|
}
|
|
104
|
-
/**
|
|
105
|
-
* For scenarios with @fixture:xxx tags verify that there are no steps from fixtures,
|
|
106
|
-
* deeper than xxx.
|
|
107
|
-
* @fixture:xxx tag provides maximum fixture that can be used in the scenario.
|
|
112
|
+
/**
|
|
113
|
+
* For scenarios with @fixture:xxx tags verify that there are no steps from fixtures,
|
|
114
|
+
* deeper than xxx.
|
|
115
|
+
* @fixture:xxx tag provides maximum fixture that can be used in the scenario.
|
|
108
116
|
*/
|
|
109
117
|
verifyChildFixtures(pomNode, usedPom, childFixtures) {
|
|
110
|
-
if (!usedPom.byTag)
|
|
118
|
+
if (!usedPom.byTag) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
111
121
|
const childFixturesBySteps = childFixtures.filter(f => !f.byTag);
|
|
112
122
|
if (childFixturesBySteps.length) {
|
|
113
123
|
(0, _exit.exit)(`Scenario "${this.title}" contains ${childFixturesBySteps.length} step(s)`, `not compatible with required fixture "${pomNode.fixtureName}"`);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getScenarioHooksFixtures = getScenarioHooksFixtures;
|
|
8
|
+
exports.hasScenarioHooks = hasScenarioHooks;
|
|
9
|
+
exports.runScenarioHooks = runScenarioHooks;
|
|
10
|
+
exports.scenarioHookFactory = scenarioHookFactory;
|
|
11
|
+
var _tagExpressions = _interopRequireDefault(require("@cucumber/tag-expressions"));
|
|
12
|
+
var _fixtureParameterNames = require("../playwright/fixtureParameterNames");
|
|
13
|
+
var _utils = require("../utils");
|
|
14
|
+
/**
|
|
15
|
+
* Scenario level hooks: Before / After.
|
|
16
|
+
*
|
|
17
|
+
* before(async ({ page }) => {})
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const scenarioHooks = [];
|
|
21
|
+
let scenarioHooksFixtures;
|
|
22
|
+
/**
|
|
23
|
+
* Returns Before() / After() functions.
|
|
24
|
+
*/
|
|
25
|
+
function scenarioHookFactory(type) {
|
|
26
|
+
return (...args) => {
|
|
27
|
+
addHook({
|
|
28
|
+
type,
|
|
29
|
+
options: getOptionsFromArgs(args),
|
|
30
|
+
fn: getFnFromArgs(args)
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function hasScenarioHooks() {
|
|
35
|
+
return scenarioHooks.length > 0;
|
|
36
|
+
}
|
|
37
|
+
// eslint-disable-next-line complexity
|
|
38
|
+
async function runScenarioHooks(type, fixtures) {
|
|
39
|
+
let error;
|
|
40
|
+
for (const hook of scenarioHooks) {
|
|
41
|
+
if (hook.type !== type) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (hook.tagsExpression && !hook.tagsExpression.evaluate(fixtures.$tags)) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const {
|
|
48
|
+
timeout
|
|
49
|
+
} = hook.options;
|
|
50
|
+
try {
|
|
51
|
+
await (0, _utils.callWithTimeout)(() => hook.fn.call(fixtures.$bddWorld, fixtures), timeout, `${type} hook timeout (${timeout} ms)`);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
if (type === 'before') {
|
|
54
|
+
throw e;
|
|
55
|
+
}
|
|
56
|
+
if (!error) {
|
|
57
|
+
error = e;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (error) {
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function getScenarioHooksFixtures() {
|
|
66
|
+
if (!scenarioHooksFixtures) {
|
|
67
|
+
const fixturesFakeObj = {
|
|
68
|
+
$bddWorld: null,
|
|
69
|
+
$tags: null,
|
|
70
|
+
$testInfo: null
|
|
71
|
+
};
|
|
72
|
+
const set = new Set();
|
|
73
|
+
scenarioHooks.forEach(hook => {
|
|
74
|
+
(0, _fixtureParameterNames.fixtureParameterNames)(hook.fn).filter(fixtureName => !Object.prototype.hasOwnProperty.call(fixturesFakeObj, fixtureName)).forEach(fixtureName => set.add(fixtureName));
|
|
75
|
+
});
|
|
76
|
+
scenarioHooksFixtures = [...set];
|
|
77
|
+
}
|
|
78
|
+
return scenarioHooksFixtures;
|
|
79
|
+
}
|
|
80
|
+
function getOptionsFromArgs(args) {
|
|
81
|
+
if (typeof args[0] === 'string') {
|
|
82
|
+
return {
|
|
83
|
+
tags: args[0]
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (typeof args[0] === 'object') {
|
|
87
|
+
return args[0];
|
|
88
|
+
}
|
|
89
|
+
return {};
|
|
90
|
+
}
|
|
91
|
+
function getFnFromArgs(args) {
|
|
92
|
+
return args.length === 1 ? args[0] : args[1];
|
|
93
|
+
}
|
|
94
|
+
function setTagsExpression(hook) {
|
|
95
|
+
if (hook.options.tags) {
|
|
96
|
+
hook.tagsExpression = (0, _tagExpressions.default)(hook.options.tags);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function addHook(hook) {
|
|
100
|
+
setTagsExpression(hook);
|
|
101
|
+
if (hook.type === 'before') {
|
|
102
|
+
scenarioHooks.push(hook);
|
|
103
|
+
} else {
|
|
104
|
+
// 'after' hooks run in reverse order
|
|
105
|
+
scenarioHooks.unshift(hook);
|
|
106
|
+
}
|
|
107
|
+
}
|