@zohodesk/testinglibrary 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/bdd-framework/cli/commands/env.js +1 -1
- package/build/bdd-framework/cli/commands/test.js +19 -19
- package/build/bdd-framework/config/env.js +3 -3
- package/build/bdd-framework/cucumber/loadFeatures.js +2 -2
- package/build/bdd-framework/cucumber/loadSteps.js +2 -2
- package/build/bdd-framework/gen/index.js +14 -11
- package/build/bdd-framework/gen/testFile.js +12 -12
- package/build/bdd-framework/gen/testPoms.js +2 -2
- package/build/bdd-framework/playwright/loadConfig.js +2 -2
- package/build/bdd-framework/playwright/testTypeImpl.js +17 -1
- package/build/bdd-framework/playwright/utils.js +4 -1
- package/build/bdd-framework/run/bddWorld.js +3 -2
- package/build/bdd-framework/snippets/index.js +9 -5
- package/build/bdd-framework/stepDefinitions/createBdd.js +2 -2
- package/build/bdd-framework/stepDefinitions/decorators/poms.js +17 -3
- package/build/bdd-framework/stepDefinitions/defineStep.js +2 -2
- package/build/bdd-framework/utils/exit.js +52 -0
- package/build/bdd-framework/utils/index.js +0 -6
- package/build/core/playwright/test-runner.js +9 -1
- package/{Changelog.md → changelog.md} +5 -0
- package/npm-shrinkwrap.json +19 -10
- package/package.json +2 -2
|
@@ -34,7 +34,7 @@ function showPackageVersion(packageName) {
|
|
|
34
34
|
* to aneble using directly from /dist in tests.
|
|
35
35
|
*/
|
|
36
36
|
function getOwnVersion() {
|
|
37
|
-
return '5.
|
|
37
|
+
return '5.4.0';
|
|
38
38
|
}
|
|
39
39
|
function showPlaywrightConfigPath(cliConfigPath) {
|
|
40
40
|
const resolvedConfigFile = (0, _loadConfig.resolveConfigFile)(cliConfigPath);
|
|
@@ -11,40 +11,40 @@ var _events = require("events");
|
|
|
11
11
|
var _path = _interopRequireDefault(require("path"));
|
|
12
12
|
var _commander = require("commander");
|
|
13
13
|
var _gen = require("../../gen");
|
|
14
|
-
var _utils = require("../../utils");
|
|
15
14
|
var _loadConfig = require("../../playwright/loadConfig");
|
|
16
15
|
var _env = require("../../config/env");
|
|
17
16
|
var _config = require("../../config");
|
|
18
17
|
var _options = require("../options");
|
|
18
|
+
var _exit = require("../../utils/exit");
|
|
19
19
|
const GEN_WORKER_PATH = _path.default.resolve(__dirname, '..', 'worker.js');
|
|
20
20
|
const testCommand = new _commander.Command('test').description('Generate Playwright test files from Gherkin documents').addOption(_options.configOption).option('--tags <expression>', `Tags expression to filter scenarios for generation`).option('--verbose', `Verbose mode (default: ${Boolean(_config.defaults.verbose)})`).action(async opts => {
|
|
21
21
|
await (0, _loadConfig.loadConfig)(opts.config);
|
|
22
|
-
const configs =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
await generateFilesForConfigs(configs, cliOptions);
|
|
22
|
+
const configs = readConfigsFromEnv();
|
|
23
|
+
mergeCliOptions(configs, opts);
|
|
24
|
+
await generateFilesForConfigs(configs);
|
|
26
25
|
});
|
|
27
26
|
exports.testCommand = testCommand;
|
|
28
|
-
function
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
function readConfigsFromEnv() {
|
|
28
|
+
const configs = Object.values((0, _env.getEnvConfigs)());
|
|
29
|
+
assertConfigsCount(configs);
|
|
30
|
+
return configs;
|
|
31
|
+
}
|
|
32
|
+
function mergeCliOptions(configs, opts) {
|
|
33
|
+
configs.forEach(config => {
|
|
34
|
+
if ('tags' in opts) config.tags = opts.tags;
|
|
35
|
+
if ('verbose' in opts) config.verbose = Boolean(opts.verbose);
|
|
36
|
+
});
|
|
33
37
|
}
|
|
34
38
|
function assertConfigsCount(configs) {
|
|
35
39
|
if (configs.length === 0) {
|
|
36
|
-
(0,
|
|
40
|
+
(0, _exit.exit)(`No BDD configs found. Did you use defineBddConfig() in playwright.config.ts?`);
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
|
-
async function generateFilesForConfigs(configs
|
|
43
|
+
async function generateFilesForConfigs(configs) {
|
|
40
44
|
// run first config in main thread and other in workers (to have fresh require cache)
|
|
41
45
|
// See: https://github.com/vitalets/playwright-bdd/issues/32
|
|
42
46
|
const tasks = configs.map((config, index) => {
|
|
43
|
-
|
|
44
|
-
...config,
|
|
45
|
-
...cliConfig
|
|
46
|
-
};
|
|
47
|
-
return index === 0 ? new _gen.TestFilesGenerator(finalConfig).generate() : runInWorker(finalConfig);
|
|
47
|
+
return index === 0 ? new _gen.TestFilesGenerator(config).generate() : runInWorker(config);
|
|
48
48
|
});
|
|
49
49
|
return Promise.all(tasks);
|
|
50
50
|
}
|
|
@@ -54,6 +54,6 @@ async function runInWorker(config) {
|
|
|
54
54
|
config
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
const [exitCode] = await (0, _events.once)(worker, 'exit');
|
|
58
|
+
if (exitCode) (0, _exit.exit)();
|
|
59
59
|
}
|
|
@@ -8,7 +8,7 @@ exports.getConfigFromEnv = getConfigFromEnv;
|
|
|
8
8
|
exports.getEnvConfigs = getEnvConfigs;
|
|
9
9
|
exports.saveConfigToEnv = saveConfigToEnv;
|
|
10
10
|
var _path = _interopRequireDefault(require("path"));
|
|
11
|
-
var
|
|
11
|
+
var _exit = require("../utils/exit");
|
|
12
12
|
/**
|
|
13
13
|
* Storing configs in env var PLAYWRIGHT_BDD_CONFIGS as JSON-stringified values.
|
|
14
14
|
* For passing configs to playwright workers and bddgen.
|
|
@@ -22,7 +22,7 @@ function saveConfigToEnv(config) {
|
|
|
22
22
|
// Throw error only if different calls of defineBddConfig() use the same outputDir.
|
|
23
23
|
// See: https://github.com/vitalets/playwright-bdd/issues/39#issuecomment-1653805368
|
|
24
24
|
if (!isSameConfigs(config, existingConfig)) {
|
|
25
|
-
(0,
|
|
25
|
+
(0, _exit.exit)(`When using several calls of defineBddConfig()`, `please manually provide different "outputDir" option.`);
|
|
26
26
|
}
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
@@ -34,7 +34,7 @@ function getConfigFromEnv(outputDir) {
|
|
|
34
34
|
outputDir = _path.default.resolve(outputDir);
|
|
35
35
|
const config = envConfigs[outputDir];
|
|
36
36
|
if (!config) {
|
|
37
|
-
(0,
|
|
37
|
+
(0, _exit.exit)(`Config not found for outputDir: "${outputDir}".`, `Available dirs: ${Object.keys(envConfigs).join('\n')}`);
|
|
38
38
|
}
|
|
39
39
|
return config;
|
|
40
40
|
}
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.loadFeatures = loadFeatures;
|
|
7
7
|
var _loadSources = require("./loadSources");
|
|
8
|
-
var
|
|
8
|
+
var _exit = require("../utils/exit");
|
|
9
9
|
async function loadFeatures(runConfiguration, environment) {
|
|
10
10
|
const {
|
|
11
11
|
filteredPickles,
|
|
@@ -34,6 +34,6 @@ function handleParseErrors(parseErrors) {
|
|
|
34
34
|
const message = parseErrors.map(parseError => {
|
|
35
35
|
return `Parse error in "${parseError.source.uri}" ${parseError.message}`;
|
|
36
36
|
}).join('\n');
|
|
37
|
-
(0,
|
|
37
|
+
(0, _exit.exit)(message);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -7,8 +7,8 @@ exports.findStepDefinition = findStepDefinition;
|
|
|
7
7
|
exports.hasTsNodeRegister = hasTsNodeRegister;
|
|
8
8
|
exports.loadSteps = loadSteps;
|
|
9
9
|
var _api = require("@cucumber/cucumber/api");
|
|
10
|
-
var _utils = require("../utils");
|
|
11
10
|
var _transform = require("../playwright/transform");
|
|
11
|
+
var _exit = require("../utils/exit");
|
|
12
12
|
const cache = new Map();
|
|
13
13
|
async function loadSteps(runConfiguration, environment = {}) {
|
|
14
14
|
const cacheKey = JSON.stringify(runConfiguration);
|
|
@@ -26,7 +26,7 @@ function findStepDefinition(supportCodeLibrary, stepText, file) {
|
|
|
26
26
|
return step.matchesStepName(stepText);
|
|
27
27
|
});
|
|
28
28
|
if (matchedSteps.length === 0) return;
|
|
29
|
-
if (matchedSteps.length > 1) (0,
|
|
29
|
+
if (matchedSteps.length > 1) (0, _exit.exit)([`Several step definitions found for text: ${stepText} (${file})`, ...matchedSteps.map(s => `- ${s.pattern}`)].join('\n'));
|
|
30
30
|
// todo: check stepDefinition.keyword with PickleStepType
|
|
31
31
|
return matchedSteps[0];
|
|
32
32
|
}
|
|
@@ -13,13 +13,13 @@ var _loadConfig = require("../cucumber/loadConfig");
|
|
|
13
13
|
var _loadFeatures = require("../cucumber/loadFeatures");
|
|
14
14
|
var _loadSteps = require("../cucumber/loadSteps");
|
|
15
15
|
var _config = require("../config");
|
|
16
|
-
var _utils = require("../utils");
|
|
17
16
|
var _snippets = require("../snippets");
|
|
18
17
|
var _steps = require("../stepDefinitions/decorators/steps");
|
|
19
18
|
var _transform = require("../playwright/transform");
|
|
20
19
|
var _dir = require("../config/dir");
|
|
21
20
|
var _logger = require("../utils/logger");
|
|
22
21
|
var _tagExpressions = _interopRequireDefault(require("@cucumber/tag-expressions"));
|
|
22
|
+
var _exit = require("../utils/exit");
|
|
23
23
|
/**
|
|
24
24
|
* Generate playwright test files from Gherkin documents.
|
|
25
25
|
*/
|
|
@@ -41,13 +41,15 @@ class TestFilesGenerator {
|
|
|
41
41
|
if (config.tags) this.tagsExpression = (0, _tagExpressions.default)(config.tags);
|
|
42
42
|
}
|
|
43
43
|
async generate() {
|
|
44
|
-
await
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
await (0, _exit.withExitHandler)(async () => {
|
|
45
|
+
await this.loadCucumberConfig();
|
|
46
|
+
await Promise.all([this.loadFeatures(), this.loadSteps()]);
|
|
47
|
+
this.buildFiles();
|
|
48
|
+
await this.checkUndefinedSteps();
|
|
49
|
+
this.checkImportCustomTest();
|
|
50
|
+
await this.clearOutputDir();
|
|
51
|
+
await this.saveFiles();
|
|
52
|
+
});
|
|
51
53
|
}
|
|
52
54
|
async extractSteps() {
|
|
53
55
|
await this.loadCucumberConfig();
|
|
@@ -118,7 +120,7 @@ class TestFilesGenerator {
|
|
|
118
120
|
const absFeaturePath = _path.default.resolve(configDir, relFeaturePath);
|
|
119
121
|
const relOutputPath = _path.default.relative(this.config.featuresRoot, absFeaturePath);
|
|
120
122
|
if (relOutputPath.startsWith('..')) {
|
|
121
|
-
(0,
|
|
123
|
+
(0, _exit.exit)(`All feature files should be located underneath featuresRoot.`, `Please change featuresRoot or paths in configuration.\n`, `featureFile: ${absFeaturePath}\n`, `featuresRoot: ${this.config.featuresRoot}\n`);
|
|
122
124
|
}
|
|
123
125
|
const absOutputPath = _path.default.resolve(this.config.outputDir, relOutputPath);
|
|
124
126
|
return `${absOutputPath}.spec.js`;
|
|
@@ -127,14 +129,15 @@ class TestFilesGenerator {
|
|
|
127
129
|
const undefinedSteps = this.files.reduce((sum, file) => sum + file.undefinedSteps.length, 0);
|
|
128
130
|
if (undefinedSteps > 0) {
|
|
129
131
|
const snippets = new _snippets.Snippets(this.files, this.runConfiguration, this.supportCodeLibrary);
|
|
130
|
-
await snippets.
|
|
132
|
+
await snippets.print();
|
|
133
|
+
(0, _exit.exit)();
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
checkImportCustomTest() {
|
|
134
137
|
if (this.config.importTestFrom) return;
|
|
135
138
|
const hasCustomTest = this.files.some(file => file.hasCustomTest);
|
|
136
139
|
if (hasCustomTest) {
|
|
137
|
-
(0,
|
|
140
|
+
(0, _exit.exit)(`When using custom "test" function in createBdd() you should`, `set "importTestFrom" config option that points to file exporting custom test.`);
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
143
|
async saveFiles() {
|
|
@@ -16,6 +16,7 @@ var _utils = require("../utils");
|
|
|
16
16
|
var _testPoms = require("./testPoms");
|
|
17
17
|
var _testNode = require("./testNode");
|
|
18
18
|
var _stepConfig = require("../stepDefinitions/stepConfig");
|
|
19
|
+
var _exit = require("../utils/exit");
|
|
19
20
|
/**
|
|
20
21
|
* Generate test code.
|
|
21
22
|
*/
|
|
@@ -116,7 +117,7 @@ class TestFile {
|
|
|
116
117
|
throw new Error(`Empty child: ${JSON.stringify(child)}`);
|
|
117
118
|
}
|
|
118
119
|
getScenarioLines(scenario, parent) {
|
|
119
|
-
return isOutline(scenario) ? this.getOutlineSuite(scenario, parent) : this.getTest(scenario, parent);
|
|
120
|
+
return this.isOutline(scenario) ? this.getOutlineSuite(scenario, parent) : this.getTest(scenario, parent);
|
|
120
121
|
}
|
|
121
122
|
/**
|
|
122
123
|
* Generate test.beforeEach for Background
|
|
@@ -293,12 +294,7 @@ class TestFile {
|
|
|
293
294
|
}
|
|
294
295
|
getStepKeyword(step) {
|
|
295
296
|
const origKeyword = step.keyword.trim();
|
|
296
|
-
|
|
297
|
-
if (origKeyword === '*') {
|
|
298
|
-
enKeyword = 'And';
|
|
299
|
-
} else {
|
|
300
|
-
enKeyword = this.i18nKeywordsMap ? this.i18nKeywordsMap.get(origKeyword) : origKeyword;
|
|
301
|
-
}
|
|
297
|
+
const enKeyword = origKeyword === '*' ? 'And' : this.getEnglishKeyword(origKeyword);
|
|
302
298
|
if (!enKeyword) throw new Error(`Keyword not found: ${origKeyword}`);
|
|
303
299
|
return enKeyword;
|
|
304
300
|
}
|
|
@@ -312,7 +308,7 @@ class TestFile {
|
|
|
312
308
|
if (resolvedFixtures.length !== 1) {
|
|
313
309
|
const suggestedTags = resolvedFixtures.filter(f => !f.byTag).map(f => (0, _testPoms.buildFixtureTag)(f.name)).join(', ');
|
|
314
310
|
const suggestedTagsStr = suggestedTags.length ? ` or set one of the following tags: ${suggestedTags}` : '.';
|
|
315
|
-
(0,
|
|
311
|
+
(0, _exit.exit)(`Can't guess fixture for decorator step "${pickleStep.text}" in file: ${this.sourceFile}.`, `Please refactor your Page Object classes${suggestedTagsStr}`);
|
|
316
312
|
}
|
|
317
313
|
const fixtureName = resolvedFixtures[0].name;
|
|
318
314
|
return {
|
|
@@ -349,8 +345,12 @@ class TestFile {
|
|
|
349
345
|
// see: https://github.com/cucumber/tag-expressions/tree/main/javascript
|
|
350
346
|
return ((_this$options$tagsExp = this.options.tagsExpression) === null || _this$options$tagsExp === void 0 ? void 0 : _this$options$tagsExp.evaluate(node.tags)) === false;
|
|
351
347
|
}
|
|
348
|
+
isOutline(scenario) {
|
|
349
|
+
const keyword = this.getEnglishKeyword(scenario.keyword);
|
|
350
|
+
return keyword === 'ScenarioOutline' || keyword === 'Scenario Outline' || keyword === 'Scenario Template';
|
|
351
|
+
}
|
|
352
|
+
getEnglishKeyword(keyword) {
|
|
353
|
+
return this.i18nKeywordsMap ? this.i18nKeywordsMap.get(keyword) : keyword;
|
|
354
|
+
}
|
|
352
355
|
}
|
|
353
|
-
exports.TestFile = TestFile;
|
|
354
|
-
function isOutline(scenario) {
|
|
355
|
-
return scenario.keyword === 'Scenario Outline' || scenario.keyword === 'Scenario Template';
|
|
356
|
-
}
|
|
356
|
+
exports.TestFile = TestFile;
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.TestPoms = void 0;
|
|
7
7
|
exports.buildFixtureTag = buildFixtureTag;
|
|
8
8
|
var _poms = require("../stepDefinitions/decorators/poms");
|
|
9
|
-
var
|
|
9
|
+
var _exit = require("../utils/exit");
|
|
10
10
|
/**
|
|
11
11
|
* Track PomNodes used in the particular test.
|
|
12
12
|
* To select correct fixture for decorator steps.
|
|
@@ -110,7 +110,7 @@ class TestPoms {
|
|
|
110
110
|
if (!usedPom.byTag) return;
|
|
111
111
|
const childFixturesBySteps = childFixtures.filter(f => !f.byTag);
|
|
112
112
|
if (childFixturesBySteps.length) {
|
|
113
|
-
(0,
|
|
113
|
+
(0, _exit.exit)(`Scenario "${this.title}" contains ${childFixturesBySteps.length} step(s)`, `not compatible with required fixture "${pomNode.fixtureName}"`);
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
}
|
|
@@ -10,7 +10,7 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
10
10
|
var _fs = _interopRequireDefault(require("fs"));
|
|
11
11
|
var _utils = require("./utils");
|
|
12
12
|
var _transform = require("./transform");
|
|
13
|
-
var
|
|
13
|
+
var _exit = require("../utils/exit");
|
|
14
14
|
/**
|
|
15
15
|
* Loading Playwright config.
|
|
16
16
|
* See: https://github.com/microsoft/playwright/blob/main/packages/playwright-test/src/common/configLoader.ts
|
|
@@ -37,6 +37,6 @@ function getConfigFilePath(cliConfigPath) {
|
|
|
37
37
|
function assertConfigFileExists(resolvedConfigFile, cliConfigPath) {
|
|
38
38
|
if (!resolvedConfigFile || !_fs.default.existsSync(resolvedConfigFile)) {
|
|
39
39
|
const configFilePath = getConfigFilePath(cliConfigPath);
|
|
40
|
-
(0,
|
|
40
|
+
(0, _exit.exit)(`Can't find Playwright config file in: ${configFilePath}`);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.getTestImpl = getTestImpl;
|
|
7
6
|
exports.isParentChildTest = isParentChildTest;
|
|
7
|
+
exports.runStepWithCustomLocation = runStepWithCustomLocation;
|
|
8
8
|
var _test = require("@playwright/test");
|
|
9
9
|
var _utils = require("../utils");
|
|
10
10
|
/**
|
|
@@ -22,6 +22,22 @@ function getTestFixtures(test) {
|
|
|
22
22
|
function getTestImpl(test) {
|
|
23
23
|
return test[testTypeSymbol];
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Run step with location pointing to Given, When, Then call.
|
|
27
|
+
*/
|
|
28
|
+
// eslint-disable-next-line max-params
|
|
29
|
+
async function runStepWithCustomLocation(test, stepText, location, body) {
|
|
30
|
+
const testInfo = test.info();
|
|
31
|
+
// See: https://github.com/microsoft/playwright/blob/main/packages/playwright/src/common/testType.ts#L221
|
|
32
|
+
// @ts-expect-error _runAsStep is hidden from public
|
|
33
|
+
return testInfo._runAsStep({
|
|
34
|
+
category: 'test.step',
|
|
35
|
+
title: stepText,
|
|
36
|
+
location
|
|
37
|
+
}, async () => {
|
|
38
|
+
return await body();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
25
41
|
/**
|
|
26
42
|
* Returns true if all fixtures of parent test found in child test.
|
|
27
43
|
*/
|
|
@@ -28,7 +28,10 @@ function getPlaywrightRoot() {
|
|
|
28
28
|
// See: https://github.com/microsoft/playwright/pull/26946
|
|
29
29
|
const playwrightTestRoot = (0, _utils.resolvePackageRoot)('@playwright/test');
|
|
30
30
|
const libDir = _path.default.join(playwrightTestRoot, 'lib');
|
|
31
|
-
|
|
31
|
+
|
|
32
|
+
// Recently added functionality in playwright
|
|
33
|
+
const playwrightDir = _path.default.join(playwrightTestRoot, 'node_modules', 'playwright');
|
|
34
|
+
playwrightRoot = _fs.default.existsSync(libDir) ? playwrightTestRoot : playwrightDir;
|
|
32
35
|
}
|
|
33
36
|
return playwrightRoot;
|
|
34
37
|
}
|
|
@@ -27,7 +27,8 @@ class BddWorld extends _cucumber.World {
|
|
|
27
27
|
// attach custom fixtures to world - the only way to pass them to cucumber step fn
|
|
28
28
|
this.customFixtures = customFixtures;
|
|
29
29
|
const code = (0, _defineStep.getStepCode)(stepDefinition);
|
|
30
|
-
//
|
|
30
|
+
// Get location of step call in generated test file.
|
|
31
|
+
// This call must be exactly here to have correct call stack.
|
|
31
32
|
const location = (0, _getLocationInFile.getLocationInFile)(this.test.info().file);
|
|
32
33
|
const {
|
|
33
34
|
parameters
|
|
@@ -39,7 +40,7 @@ class BddWorld extends _cucumber.World {
|
|
|
39
40
|
},
|
|
40
41
|
world: this
|
|
41
42
|
});
|
|
42
|
-
const res = await (0, _testTypeImpl.
|
|
43
|
+
const res = await (0, _testTypeImpl.runStepWithCustomLocation)(this.test, text, location, () => code.apply(this, parameters));
|
|
43
44
|
delete this.customFixtures;
|
|
44
45
|
return res;
|
|
45
46
|
}
|
|
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.Snippets = void 0;
|
|
7
7
|
var _loadSnippetBuilder = require("../cucumber/loadSnippetBuilder");
|
|
8
|
-
var _utils = require("../utils");
|
|
9
8
|
var _logger = require("../utils/logger");
|
|
10
9
|
var _stepConfig = require("../stepDefinitions/stepConfig");
|
|
11
10
|
/**
|
|
@@ -23,13 +22,15 @@ class Snippets {
|
|
|
23
22
|
this.runConfiguration = runConfiguration;
|
|
24
23
|
this.supportCodeLibrary = supportCodeLibrary;
|
|
25
24
|
}
|
|
26
|
-
async
|
|
25
|
+
async print() {
|
|
27
26
|
this.snippetBuilder = await this.createSnippetBuilder();
|
|
28
27
|
const snippets = this.getSnippets();
|
|
29
28
|
this.printHeader();
|
|
30
29
|
this.printSnippets(snippets);
|
|
31
30
|
this.printFooter(snippets);
|
|
31
|
+
// exit();
|
|
32
32
|
}
|
|
33
|
+
|
|
33
34
|
async createSnippetBuilder() {
|
|
34
35
|
const {
|
|
35
36
|
snippetInterface
|
|
@@ -117,15 +118,18 @@ class Snippets {
|
|
|
117
118
|
_logger.logger.error(snippets.concat(['']).join('\n\n'));
|
|
118
119
|
}
|
|
119
120
|
printFooter(snippets) {
|
|
120
|
-
|
|
121
|
+
_logger.logger.error(`Missing step definitions (${snippets.length}).`, `Use snippets above to create them.`);
|
|
122
|
+
this.printWarningOnZeroScannedFiles();
|
|
121
123
|
}
|
|
122
|
-
|
|
124
|
+
printWarningOnZeroScannedFiles() {
|
|
123
125
|
const {
|
|
124
126
|
requirePaths,
|
|
125
127
|
importPaths
|
|
126
128
|
} = this.supportCodeLibrary.originalCoordinates;
|
|
127
129
|
const scannedFilesCount = requirePaths.length + importPaths.length;
|
|
128
|
-
|
|
130
|
+
if (scannedFilesCount === 0 && !this.isDecorators()) {
|
|
131
|
+
_logger.logger.error(`Note that 0 step definition files found, check the config.`);
|
|
132
|
+
}
|
|
129
133
|
}
|
|
130
134
|
}
|
|
131
135
|
exports.Snippets = Snippets;
|
|
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.createBdd = createBdd;
|
|
7
7
|
exports.extractFixtureNames = extractFixtureNames;
|
|
8
8
|
var _fixtureParameterNames = require("../playwright/fixtureParameterNames");
|
|
9
|
-
var _utils = require("../utils");
|
|
10
9
|
var _bddFixtures = require("../run/bddFixtures");
|
|
11
10
|
var _testTypeImpl = require("../playwright/testTypeImpl");
|
|
12
11
|
var _defineStep = require("./defineStep");
|
|
12
|
+
var _exit = require("../utils/exit");
|
|
13
13
|
/**
|
|
14
14
|
* Stuff related to writing steps in Playwright-style.
|
|
15
15
|
*/
|
|
@@ -43,7 +43,7 @@ function extractFixtureNames(fn) {
|
|
|
43
43
|
function isCustomTest(customTest) {
|
|
44
44
|
const isCustomTest = Boolean(customTest && customTest !== _bddFixtures.test);
|
|
45
45
|
if (isCustomTest && customTest && !(0, _testTypeImpl.isParentChildTest)(_bddFixtures.test, customTest)) {
|
|
46
|
-
(0,
|
|
46
|
+
(0, _exit.exit)(`createBdd() should use test extended from "@zohodesk/testinglibrary"`);
|
|
47
47
|
}
|
|
48
48
|
return isCustomTest;
|
|
49
49
|
}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.Fixture = Fixture;
|
|
7
7
|
exports.getPomNodeByFixtureName = getPomNodeByFixtureName;
|
|
8
8
|
var _steps = require("./steps");
|
|
9
|
+
var _exit = require("../../utils/exit");
|
|
9
10
|
/**
|
|
10
11
|
* POM classes marked with @Fixture
|
|
11
12
|
*/
|
|
@@ -20,25 +21,38 @@ const pomGraph = new Map();
|
|
|
20
21
|
*/
|
|
21
22
|
function Fixture(fixtureName) {
|
|
22
23
|
// context parameter is required for decorator by TS even though it's not used
|
|
23
|
-
|
|
24
|
-
return (Ctor, _context) => {
|
|
24
|
+
return Ctor => {
|
|
25
25
|
createPomNode(Ctor, fixtureName);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
function createPomNode(Ctor, fixtureName) {
|
|
29
29
|
const pomNode = {
|
|
30
30
|
fixtureName,
|
|
31
|
+
className: Ctor.name,
|
|
31
32
|
children: new Set()
|
|
32
33
|
};
|
|
34
|
+
ensureUniqueFixtureName(pomNode);
|
|
33
35
|
pomGraph.set(Ctor, pomNode);
|
|
34
36
|
(0, _steps.linkStepsWithPomNode)(Ctor, pomNode);
|
|
35
37
|
linkParentWithPomNode(Ctor, pomNode);
|
|
36
38
|
return pomNode;
|
|
37
39
|
}
|
|
40
|
+
function ensureUniqueFixtureName({
|
|
41
|
+
fixtureName,
|
|
42
|
+
className
|
|
43
|
+
}) {
|
|
44
|
+
if (!fixtureName) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const existingPom = getPomNodeByFixtureName(fixtureName);
|
|
48
|
+
if (existingPom) {
|
|
49
|
+
(0, _exit.exit)(`Duplicate fixture name "${fixtureName}"`, `defined for classes: ${existingPom.className}, ${className}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
38
52
|
function linkParentWithPomNode(Ctor, pomNode) {
|
|
39
53
|
const parentCtor = Object.getPrototypeOf(Ctor);
|
|
40
54
|
if (!parentCtor) return;
|
|
41
|
-
// if parentCtor is not in pomGraph, add it
|
|
55
|
+
// if parentCtor is not in pomGraph, add it.
|
|
42
56
|
// Case: parent class is not marked with @Fixture, but has decorator steps (base class)
|
|
43
57
|
const parentPomNode = pomGraph.get(parentCtor) || createPomNode(parentCtor, '');
|
|
44
58
|
parentPomNode.children.add(pomNode);
|
|
@@ -7,7 +7,7 @@ exports.buildCucumberStepCode = buildCucumberStepCode;
|
|
|
7
7
|
exports.defineStep = defineStep;
|
|
8
8
|
exports.getStepCode = getStepCode;
|
|
9
9
|
var _cucumber = require("@cucumber/cucumber");
|
|
10
|
-
var
|
|
10
|
+
var _exit = require("../utils/exit");
|
|
11
11
|
/**
|
|
12
12
|
* Defines step by config.
|
|
13
13
|
* Calls cucumber's Given(), When(), Then() under the hood.
|
|
@@ -26,7 +26,7 @@ function defineStep(stepConfig) {
|
|
|
26
26
|
// and skip/delay registering cucumber steps until cucumber is loaded
|
|
27
27
|
const isMissingCucumber = /Cucumber that isn't running/i.test(e.message);
|
|
28
28
|
if (isMissingCucumber) {
|
|
29
|
-
(0,
|
|
29
|
+
(0, _exit.exit)(`Option "importTestFrom" should point to a separate file without step definitions`, `(e.g. without calls of Given, When, Then)`);
|
|
30
30
|
} else {
|
|
31
31
|
throw e;
|
|
32
32
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.exit = exit;
|
|
7
|
+
exports.withExitHandler = withExitHandler;
|
|
8
|
+
var _logger = require("./logger");
|
|
9
|
+
var _worker_threads = require("worker_threads");
|
|
10
|
+
/**
|
|
11
|
+
* Exit utils.
|
|
12
|
+
*
|
|
13
|
+
* When calling process.exit() in worker thread used for file generation,
|
|
14
|
+
* logs are not flushed (https://github.com/vitalets/playwright-bdd/issues/59).
|
|
15
|
+
* That's why instead of process.exit we throw ExitError
|
|
16
|
+
* that just sets process.exitCode = 1 and allow program to exit normally.
|
|
17
|
+
*
|
|
18
|
+
* On the other hand, when running in main thread, especially inside Playwright,
|
|
19
|
+
* thrown error is captured by Playwright and show with additional messages (e.g. no tests found).
|
|
20
|
+
* That's why in main thread we to call process.exit() to show only needed error.
|
|
21
|
+
*
|
|
22
|
+
* Relevant discussions:
|
|
23
|
+
* - https://github.com/nodejs/node/issues/6379
|
|
24
|
+
* - https://github.com/nodejs/node-v0.x-archive/issues/3737
|
|
25
|
+
* - https://github.com/cucumber/cucumber-js/pull/123
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
class ExitError extends Error {
|
|
29
|
+
get stack() {
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function withExitHandler(fn) {
|
|
34
|
+
try {
|
|
35
|
+
return await fn();
|
|
36
|
+
} catch (e) {
|
|
37
|
+
if (e instanceof ExitError) {
|
|
38
|
+
process.exitCode = 1;
|
|
39
|
+
} else {
|
|
40
|
+
throw e;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function exit(...messages) {
|
|
45
|
+
messages = messages.filter(Boolean);
|
|
46
|
+
if (_worker_threads.isMainThread) {
|
|
47
|
+
if (messages.length) _logger.logger.error('Error:', ...messages);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
} else {
|
|
50
|
+
throw new ExitError(messages.join(' '));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -4,7 +4,6 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.exitWithMessage = exitWithMessage;
|
|
8
7
|
exports.getPackageVersion = getPackageVersion;
|
|
9
8
|
exports.getSymbolByName = getSymbolByName;
|
|
10
9
|
exports.removeDuplicates = removeDuplicates;
|
|
@@ -12,11 +11,6 @@ exports.resolvePackageRoot = resolvePackageRoot;
|
|
|
12
11
|
exports.template = template;
|
|
13
12
|
var _fs = _interopRequireDefault(require("fs"));
|
|
14
13
|
var _path = _interopRequireDefault(require("path"));
|
|
15
|
-
var _logger = require("./logger");
|
|
16
|
-
function exitWithMessage(...messages) {
|
|
17
|
-
_logger.logger.error('ERROR:', ...messages.filter(Boolean));
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
14
|
// See: https://stackoverflow.com/questions/50453640/how-can-i-get-the-value-of-a-symbol-property
|
|
21
15
|
function getSymbolByName(target, name) {
|
|
22
16
|
const ownKeys = Reflect.ownKeys(target);
|
|
@@ -73,6 +73,14 @@ function runPlaywright(command, args) {
|
|
|
73
73
|
resolve();
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
|
+
process.on('exit', () => {
|
|
77
|
+
//childProcessForRunningPlaywright.kill();
|
|
78
|
+
reject('Terminating Playwright Process...');
|
|
79
|
+
});
|
|
80
|
+
process.on('SIGINT', () => {
|
|
81
|
+
//childProcessForRunningPlaywright.kill();
|
|
82
|
+
reject('Cleaning up...');
|
|
83
|
+
});
|
|
76
84
|
});
|
|
77
85
|
}
|
|
78
86
|
function main() {
|
|
@@ -97,7 +105,7 @@ function main() {
|
|
|
97
105
|
}
|
|
98
106
|
Promise.all(promises).then(() => runPlaywright(command, args)).catch(err => {
|
|
99
107
|
_logger.Logger.log(_logger.Logger.FAILURE_TYPE, err);
|
|
100
|
-
process.exit(
|
|
108
|
+
process.exit();
|
|
101
109
|
});
|
|
102
110
|
}
|
|
103
111
|
var _default = main;
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zohodesk/testinglibrary",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1-exp.1",
|
|
4
4
|
"lockfileVersion": 1,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"dependencies": {
|
|
@@ -2577,13 +2577,22 @@
|
|
|
2577
2577
|
"integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q=="
|
|
2578
2578
|
},
|
|
2579
2579
|
"@playwright/test": {
|
|
2580
|
-
"version": "1.
|
|
2581
|
-
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.
|
|
2582
|
-
"integrity": "sha512-
|
|
2580
|
+
"version": "1.39.0",
|
|
2581
|
+
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz",
|
|
2582
|
+
"integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==",
|
|
2583
2583
|
"requires": {
|
|
2584
|
-
"
|
|
2585
|
-
|
|
2586
|
-
|
|
2584
|
+
"playwright": "1.39.0"
|
|
2585
|
+
},
|
|
2586
|
+
"dependencies": {
|
|
2587
|
+
"playwright": {
|
|
2588
|
+
"version": "1.39.0",
|
|
2589
|
+
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz",
|
|
2590
|
+
"integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==",
|
|
2591
|
+
"requires": {
|
|
2592
|
+
"fsevents": "2.3.2",
|
|
2593
|
+
"playwright-core": "1.39.0"
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2587
2596
|
}
|
|
2588
2597
|
},
|
|
2589
2598
|
"@sinclair/typebox": {
|
|
@@ -6715,9 +6724,9 @@
|
|
|
6715
6724
|
}
|
|
6716
6725
|
},
|
|
6717
6726
|
"playwright-core": {
|
|
6718
|
-
"version": "1.
|
|
6719
|
-
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.
|
|
6720
|
-
"integrity": "sha512
|
|
6727
|
+
"version": "1.39.0",
|
|
6728
|
+
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz",
|
|
6729
|
+
"integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw=="
|
|
6721
6730
|
},
|
|
6722
6731
|
"pretty-format": {
|
|
6723
6732
|
"version": "29.7.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zohodesk/testinglibrary",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@babel/preset-react": "7.22.5",
|
|
24
24
|
"@cucumber/cucumber": "9.2.0",
|
|
25
|
-
"@playwright/test": "1.
|
|
25
|
+
"@playwright/test": "1.39.0",
|
|
26
26
|
"@testing-library/jest-dom": "5.11.9",
|
|
27
27
|
"@testing-library/react": "11.2.7",
|
|
28
28
|
"@testing-library/react-hooks": "7.0.2",
|