Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | 13x 13x 13x 13x 13x 13x 13x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 2x 2x 2x 1x 1x 3x 3x 1x 2x 3x 3x 1x 2x 1x 1x 1x 2x 1x 1x 1x 2x 2x 2x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 1x 1x | import * as Cucumber from 'cucumber' import mockery from 'mockery' import isGlob from 'is-glob' import glob from 'glob' import path from 'path' import CucumberReporter from './reporter' import Hookrunner from './hookRunner' import { EventEmitter } from 'events' import { executeHooksWithArgs, executeSync, executeAsync, runFnInFiberContext, hasWdioSyncSupport } from '@wdio/config' import { DEFAULT_OPTS } from './constants' class CucumberAdapter { constructor (cid, config, specs, capabilities, reporter) { this.cwd = process.cwd() this.cid = cid this.specs = specs this.reporter = reporter this.capabilities = capabilities this.config = config this.cucumberOpts = Object.assign(DEFAULT_OPTS, config.cucumberOpts) } async run () { let runtimeError let result try { this.registerRequiredModules() Cucumber.supportCodeLibraryBuilder.reset(this.cwd) this.loadSpecFiles() this.wrapSteps() Cucumber.setDefaultTimeout(this.cucumberOpts.timeout) const supportCodeLibrary = Cucumber.supportCodeLibraryBuilder.finalize() const eventBroadcaster = new EventEmitter() // eslint-disable-next-line no-new new Hookrunner(eventBroadcaster, this.config) const reporterOptions = { capabilities: this.capabilities, ignoreUndefinedDefinitions: Boolean(this.cucumberOpts.ignoreUndefinedDefinitions), failAmbiguousDefinitions: Boolean(this.cucumberOpts.failAmbiguousDefinitions), tagsInTitle: Boolean(this.cucumberOpts.tagsInTitle) } this.cucumberReporter = new CucumberReporter(eventBroadcaster, reporterOptions, this.cid, this.specs, this.reporter) const pickleFilter = new Cucumber.PickleFilter({ featurePaths: this.specs, names: this.cucumberOpts.name, tagExpression: this.cucumberOpts.tagExpression }) const testCases = await Cucumber.getTestCasesFromFilesystem({ cwd: this.cwd, eventBroadcaster, featurePaths: this.specs, order: this.cucumberOpts.order, pickleFilter }) const runtime = new Cucumber.Runtime({ eventBroadcaster, options: this.cucumberOpts, supportCodeLibrary, testCases }) await executeHooksWithArgs(this.config.before, [this.capabilities, this.specs]) result = await runtime.start() ? 0 : 1 /** * if we ignore undefined definitions we trust the reporter * with the fail count */ Iif (this.cucumberOpts.ignoreUndefinedDefinitions && result) { result = this.cucumberReporter.failedCount } } catch (e) { runtimeError = e result = 1 } await executeHooksWithArgs(this.config.after, [runtimeError || result, this.capabilities, this.specs]) /** * in case the spec has a runtime error throw after the wdio hook */ if (runtimeError) { throw runtimeError } return result } /** * Transpilation https://github.com/cucumber/cucumber-js/blob/master/docs/cli.md#transpilation * Usage: `['module']` * we extend it a bit with ability to init and pass configuration to modules. * Pass an array with path to module and its configuration instead: * Usage: `[['module', {}]]` * Or pass your own function * Usage: `[() => { require('ts-node').register({ files: true }) }]` */ registerRequiredModules () { this.cucumberOpts.requireModule.map(requiredModule => { if (Array.isArray(requiredModule)) { require(requiredModule[0])(requiredModule[1]) } else if (typeof requiredModule === 'function') { requiredModule() } else { require(requiredModule) } }) } requiredFiles () { return this.cucumberOpts.require.reduce( (files, requiredFile) => files.concat(isGlob(requiredFile) ? glob.sync(requiredFile) : [requiredFile] ), [] ) } loadSpecFiles () { // we use mockery to allow people to import 'our' cucumber even though their spec files are in their folders // because of that we don't have to attach anything to the global object, and the current cucumber spec files // should just work with no changes with this framework mockery.enable({ useCleanCache: false, warnOnReplace: false, warnOnUnregistered: false }) mockery.registerMock('cucumber', Cucumber) this.requiredFiles().forEach((codePath) => { const filepath = path.isAbsolute(codePath) ? codePath : path.join(process.cwd(), codePath) // This allows rerunning a stepDefinitions file delete require.cache[require.resolve(filepath)] require(filepath) }) mockery.disable() } /** * wraps step definition code with sync/async runner with a retry option */ wrapSteps () { const wrapStepSync = this.wrapStepSync const wrapStepAsync = this.wrapStepAsync Cucumber.setDefinitionFunctionWrapper((fn, options = {}) => { const retryTest = isFinite(options.retry) ? parseInt(options.retry, 10) : 0 return fn.name === 'async' || !hasWdioSyncSupport ? wrapStepAsync(fn, retryTest) /* istanbul ignore next */ : wrapStepSync(fn, retryTest) }) } /** * wrap step definition to enable retry ability * @param {Function} code step definition * @param {Number} retryTest amount of allowed repeats is case of a failure * @return {Function} wrapped step definiton for sync WebdriverIO code */ wrapStepSync (code, retryTest = 0) { return function (...args) { return runFnInFiberContext( executeSync.bind(this, code, retryTest, args), ).apply(this) } } /** * wrap step definition to enable retry ability * @param {Function} code step definitoon * @param {Number} retryTest amount of allowed repeats is case of a failure * @return {Function} wrapped step definiton for async WebdriverIO code */ wrapStepAsync (code, retryTest = 0) { return function (...args) { return executeAsync.call(this, code, retryTest, args) } } } const _CucumberAdapter = CucumberAdapter const adapterFactory = {} /** * tested by smoke tests */ /* istanbul ignore next */ adapterFactory.run = async function (...args) { const adapter = new _CucumberAdapter(...args) const result = await adapter.run() return result } export default adapterFactory export { CucumberAdapter, adapterFactory } |