Implementation:Webdriverio Webdriverio CucumberAdapter Class
Metadata
| Field | Value |
|---|---|
| Page ID | CucumberAdapter_Class |
| Page Type | Implementation |
| Implementation Type | API Doc |
| Repository | webdriverio/webdriverio |
| Package | @wdio/cucumber-framework |
| Source | packages/wdio-cucumber-framework/src/index.ts (L57-522), packages/wdio-cucumber-framework/src/cucumberFormatter.ts (L43-610)
|
| Related Pages | implements Principle:Webdriverio_Webdriverio_Cucumber_Execution |
Overview
Concrete tool for executing Cucumber BDD scenarios within the WDIO testrunner, provided by the @wdio/cucumber-framework package.
Description
The CucumberAdapter class implements the WDIO framework adapter interface. It initializes the Cucumber runtime with WDIO-specific configuration, parses Gherkin documents, wraps step definitions with WDIO hooks, runs scenarios, and emits test results via the CucumberFormatter to WDIO reporters.
The adapter is the central orchestration class for Cucumber-based test execution within WDIO. It is instantiated by the adapterFactory.init() factory function, which is called by the WDIO testrunner in each worker process.
Source
CucumberAdapter class: packages/wdio-cucumber-framework/src/index.ts lines 57-522
CucumberFormatter class: packages/wdio-cucumber-framework/src/cucumberFormatter.ts lines 43-610
Factory export: packages/wdio-cucumber-framework/src/index.ts lines 569-581
Signature
export class CucumberAdapter {
private _cwd: string
private _newId: () => string
private _cucumberOpts: Required<CucumberOptions>
private _hasTests: boolean
private gherkinParser: InstanceType<typeof Gherkin.Parser>
constructor(
private _cid: string,
private _config: WebdriverIO.Config,
private _specs: string[],
private _capabilities: Capabilities.ResolvedTestrunnerCapabilities,
private _reporter: EventEmitter,
private _eventEmitter: EventEmitter,
private _generateSkipTags: boolean = true,
private _cucumberFormatter: string = url.pathToFileURL(
path.resolve(__dirname, 'cucumberFormatter.js')
).href
)
async init(): Promise<CucumberAdapter>
hasTests(): boolean
async run(): Promise<number>
}
Import
The adapter is internal to @wdio/cucumber-framework and is loaded automatically when framework: 'cucumber' is set in the WDIO configuration. It is not intended for direct import by users.
// Internal: loaded by WDIO testrunner via adapterFactory
import adapterFactory from '@wdio/cucumber-framework'
// The factory creates and initializes the adapter:
const adapter = await adapterFactory.init(cid, config, specs, capabilities, reporter)
Inputs
| Parameter | Type | Description |
|---|---|---|
_cid |
string |
Worker capability ID (e.g., '0-0')
|
_config |
WebdriverIO.Config |
Full WDIO configuration object including cucumberOpts
|
_specs |
string[] |
Array of spec file paths (feature files) assigned to this worker |
_capabilities |
Capabilities.ResolvedTestrunnerCapabilities |
Resolved browser/device capabilities for this worker |
_reporter |
EventEmitter |
Reporter event emitter for publishing test results |
_eventEmitter |
EventEmitter |
Internal event emitter for adapter-formatter communication |
Outputs
| Output | Type | Description |
|---|---|---|
Return value of run() |
number |
Exit code: 0 = all tests passed, 1 = one or more tests failed
|
| Reporter events | (emitted) | Test lifecycle events emitted to _reporter: suite:start, suite:end, test:start, test:pass, test:fail, test:pending, hook:start, hook:end, suite:retry
|
Key Methods
init()
Initializes the adapter after construction. Generates dynamic skip tags from capabilities, filters specs against tag expressions using loadSources(), and deduplicates the spec list. Returns the adapter instance for chaining.
// packages/wdio-cucumber-framework/src/index.ts (L183-213)
async init() {
if (this._generateSkipTags) {
this._cucumberOpts.tags = this.generateDynamicSkipTags()
.concat(this._cucumberOpts.tags || [])
.join(' and ')
}
const { plan } = await loadSources({
paths: this._specs,
defaultDialect: this._cucumberOpts.language,
order: this._cucumberOpts.order,
names: this._cucumberOpts.name,
tagExpression: this._cucumberOpts.tags,
})
this._specs = plan?.map((pl) => path.resolve(pl.uri))
// ... line number filtering and deduplication
this._hasTests = this._specs.length > 0
return this
}
run()
Executes the Cucumber test run. This is the main execution method that:
- Registers required modules for transpilation
- Resets the support code library builder
- Adds WDIO lifecycle hooks (beforeFeature, beforeScenario, beforeStep, afterStep, afterScenario, afterFeature)
- Loads step definition files
- Wraps step definitions with WDIO hooks
- Sets the default timeout
- Calls
loadConfiguration()andrunCucumber()from@cucumber/cucumber/api - Executes the WDIO
afterhook - Returns the exit code
// packages/wdio-cucumber-framework/src/index.ts (L219-301)
async run() {
let runtimeError
let result
let failedCount
let outStream
try {
await this.registerRequiredModules()
supportCodeLibraryBuilder.reset(this._cwd, this._newId, {
requireModules: this._cucumberOpts.requireModule,
requirePaths: this._cucumberOpts.require,
importPaths: this._cucumberOpts.import,
loaders: []
})
this.addWdioHooks(this._config, supportCodeLibraryBuilder)
await this.loadFiles()
this.wrapSteps(this._config)
setUserHookNames(supportCodeLibraryBuilder)
setDefaultTimeout(this._cucumberOpts.timeout)
const supportCodeLibrary = supportCodeLibraryBuilder.finalize()
// ... stream and event setup
const { runConfiguration } = await loadConfiguration(
{ profiles: this._cucumberOpts.profiles,
provided: this._cucumberOpts as Partial<IConfiguration>,
file: this._cucumberOpts.file },
environment
)
const { success } = await runCucumber(
{ ...runConfiguration,
support: supportCodeLibrary || runConfiguration.support },
environment
)
result = success ? 0 : 1
if (this._cucumberOpts.ignoreUndefinedDefinitions && result) {
result = failedCount
}
} catch (err) {
runtimeError = err
result = 1
}
await executeHooksWithArgs('after', this._config.after, [
runtimeError || result, this._capabilities, this._specs
])
if (runtimeError) {
throw runtimeError
}
return result
}
addWdioHooks()
Registers WDIO lifecycle hooks (BeforeAll, Before, BeforeStep, AfterStep, After, AfterAll) with the Cucumber support code library. These hooks call the corresponding WDIO config hooks (beforeFeature, beforeScenario, beforeStep, afterStep, afterScenario, afterFeature) via executeHooksWithArgs().
wrapSteps()
Uses setDefinitionFunctionWrapper() from @cucumber/cucumber to wrap all step definitions. The wrapper integrates each step with WDIO's beforeHook/afterHook lifecycle and adds retry support. WDIO-internal hooks (prefixed wdioHook) and steps without retry options are returned unwrapped for performance.
getGherkinDocuments()
Reads feature files and parses them into GherkinDocument objects using the Gherkin parser initialized in the constructor. Used by generateDynamicSkipTags() to extract tags for capability-based filtering.
CucumberFormatter (Companion Class)
The CucumberFormatter class (in cucumberFormatter.ts) extends Cucumber's Formatter base class and translates Cucumber envelope events into WDIO reporter events. It:
- Maintains maps of Gherkin documents, pickles, test cases, and hooks
- Tracks the current test case, scenario, and step for event correlation
- Adds keywords (Given/When/Then) to pickle steps for reporter display
- Handles status translation (PASSED, FAILED, UNDEFINED, AMBIGUOUS, PENDING, SKIPPED)
- Tracks the failed count and emits it via the event emitter at test run completion
- Supports both step-level and scenario-level reporting modes
Factory Export
// packages/wdio-cucumber-framework/src/index.ts (L569-581)
const _CucumberAdapter = CucumberAdapter
export const adapterFactory: { init?: Function } = {}
adapterFactory.init = async function (...args: unknown[]) {
const adapter = new _CucumberAdapter(...(args as unknown))
const instance = await adapter.init()
return instance
}
export default adapterFactory