UNPKG

@serenity-js/cucumber

Version:

Serenity/JS test runner adapter for seamless integration with any version of Cucumber.js, facilitating BDD-style test automation and leveraging Serenity/JS reporting capabilities

149 lines 5.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CucumberOptions = void 0; const core_1 = require("@serenity-js/core"); const io_1 = require("@serenity-js/core/lib/io"); /** * @private */ class CucumberOptions { finder; fileSystem; config; constructor(finder, fileSystem, config) { this.finder = finder; this.fileSystem = fileSystem; this.config = config; } isStrict() { return this.asBoolean('strict', true); } asArgumentsForCucumber(version) { return Object.keys(this.config) .reduce((acc, option) => isNotEmpty(this.config[option]) ? acc.concat(this.optionToValues(option, this.config[option], version)) : acc, // Cucumber ignores the first two arguments anyway, but let's add them for completeness // https://github.com/cucumber/cucumber-js/blob/d74bc45ba98132bdd0af62e0e52d1fe9ff017006/src/cli/helpers.js#L15 ['node', 'cucumber-js']) .concat(this.config.rerun && this.fileSystem.exists(io_1.Path.from(this.config.rerun)) ? this.config.rerun : []); } asArray(value) { if (value === undefined) { return []; } if (Array.isArray(value)) { return Array.from(value); } return [value]; } asCucumberApiConfiguration() { // https://github.com/cucumber/cucumber-js/blob/main/docs/configuration.md return { dryRun: this.config.dryRun, forceExit: false, failFast: this.config.failFast, format: this.asArray(this.config.format), formatOptions: this.config.formatOptions, paths: this.asArray(this.config.paths) .flatMap(glob => this.absolutePathsToFilesMatching(glob)), import: this.asArray(this.config.import) .flatMap(glob => this.absolutePathsToFilesMatching(glob)), require: this.asArray(this.config.require) .flatMap(glob => this.absolutePathsToFilesMatching(glob)), requireModule: this.asArray(this.config.requireModule), language: this.config.language, name: this.asArray(this.config.name), publish: false, retry: this.config.retry, retryTagFilter: this.config.retryTagFilter, strict: this.config.strict, tags: this.asArray(this.config.tags).join(' and '), worldParameters: this.config.worldParameters, // Cucumber typings rely on `type-fest` and we don't need another dependency to define one type // order: PickleOrder // parallel: number, // this only works when Cucumber is the runner, in which scenario CucumberCLIAdapter is not used anyway }; } absolutePathsToFilesMatching(glob) { const matchingPaths = this.finder.filesMatching(glob); if (matchingPaths.length === 0) { throw new core_1.ConfigurationError(`No files found matching the pattern ${glob}`); } return matchingPaths.map(path => path.value); } optionToValues(option, value, version) { const cliOption = this.asCliOptionName(option); switch (true) { case cliOption === 'tags' && version.isAtLeast(new io_1.Version('2.0.0')) && value !== false: return this.valuesToArgs(cliOption, this.tagsToCucumberExpressions(listOf(value))); case cliOption === 'rerun': return []; // ignore since we're appending the rerun file anyway case typeof value === 'boolean': return listOf(this.flagToArg(cliOption, value)); case this.isObject(value): return this.valuesToArgs(cliOption, JSON.stringify(value, undefined, 0)); default: return this.valuesToArgs(cliOption, listOf(value)); } } asBoolean(key, defaultValue) { if (typeof this.config[key] === 'boolean') { return this.config[key]; } if (typeof this.config[negated(key)] === 'boolean') { return !this.config[negated(key)]; } return defaultValue; } isObject(value) { return typeof value === 'object' && Array.isArray(value) === false && Object.prototype.toString.call(value) === '[object Object]'; } /** * Converts camelCase option names to kebab-case. */ asCliOptionName(option) { return option .replaceAll(/([\da-z]|(?=[A-Z]))([A-Z])/g, '$1-$2') .toLowerCase(); } tagsToCucumberExpressions(tags) { return tags.filter(tag => !!tag.replace) .map(tag => tag.replaceAll('~', 'not ')) .join(' and '); } flagToArg(option, value) { switch (true) { case !!value: return `--${option}`; case isNegated(option) && !value: return `--${option.replace(/^no-/, '')}`; default: return `--no-${option}`; } } valuesToArgs(option, values) { return listOf(values) .map(value => [`--${option}`, value]) .reduce((acc, tuple) => acc.concat(tuple), []); } } exports.CucumberOptions = CucumberOptions; function isNegated(optionName) { return optionName.startsWith('no-'); } // this method will need to be smarter if it was to be public, i.e. to avoid double negatives like noStrict=false function negated(name) { return 'no' + name.charAt(0).toUpperCase() + name.slice(1); } function isNotEmpty(value) { return value !== undefined && value !== null && value !== '' && !(Array.isArray(value) && value.length === 0); } function listOf(valueOrValues) { return [].concat(valueOrValues).filter(isNotEmpty); } //# sourceMappingURL=CucumberOptions.js.map