Implementation:Webdriverio Webdriverio Given When Then Functions
Metadata
| Field | Value |
|---|---|
| Page ID | Given_When_Then_Functions |
| Page Type | Implementation |
| Implementation Type | Wrapper Doc |
| Repository | webdriverio/webdriverio |
| Package | @wdio/cucumber-framework (re-exports from @cucumber/cucumber) |
| Source | packages/wdio-cucumber-framework/src/index.ts (L584: re-export), examples/wdio/cucumber/step-definitions.ts (L12-42), packages/wdio-cucumber-framework/src/index.ts (L443-521: wrapSteps/wrapStep)
|
| External Reference | Cucumber Step Definitions Documentation |
| Related Pages | implements Principle:Webdriverio_Webdriverio_Step_Definition_Binding |
Overview
Wrapper documentation for Cucumber step definition functions re-exported through the @wdio/cucumber-framework package.
Description
The Given(), When(), and Then() functions are re-exported from @cucumber/cucumber via the @wdio/cucumber-framework package. The adapter's wrapStep() method integrates each step with WDIO's beforeHook/afterHook lifecycle. Within step functions, the browser, $, $$, and expect globals are available for browser automation.
The re-export is a wildcard re-export at the bottom of the adapter's entry file:
// packages/wdio-cucumber-framework/src/index.ts (L584)
export * from '@cucumber/cucumber'
This makes all Cucumber exports (including Given, When, Then, Before, After, BeforeAll, AfterAll, BeforeStep, AfterStep, setDefaultTimeout, World, etc.) available when importing from @wdio/cucumber-framework.
Signatures
Given(pattern: string | RegExp, fn: (...args: any[]) => Promise<void> | void): void
When(pattern: string | RegExp, fn: (...args: any[]) => Promise<void> | void): void
Then(pattern: string | RegExp, fn: (...args: any[]) => Promise<void> | void): void
All three functions have identical signatures. The keyword distinction (Given/When/Then) is semantic only and exists for readability in step definition files. Cucumber treats them identically at the matching level -- a step defined with Given can match a When step in a feature file.
Import
import { Given, When, Then } from '@wdio/cucumber-framework'
Inputs
| Parameter | Type | Description |
|---|---|---|
pattern |
RegExp | Pattern to match against step text. Strings use Cucumber Expression syntax (e.g., '{string}', '{int}'). RegExp uses JavaScript regex with capture groups.
|
fn |
void | Async step function. Arguments are the captured groups from the pattern match. For data table steps, a DataTable object is appended as the last argument. WDIO globals (browser, $, $$, expect) are available in scope.
|
Outputs
- Registered step definitions bound to the Cucumber runtime via
supportCodeLibraryBuilder. - At runtime, each step function is wrapped with WDIO hooks via
setDefinitionFunctionWrapper(). - Step execution results are emitted to WDIO reporters through the
CucumberFormatter.
Step Wrapping Mechanism
The adapter's wrapSteps() method uses setDefinitionFunctionWrapper() to intercept all step definitions:
// packages/wdio-cucumber-framework/src/index.ts (L443-481)
wrapSteps(config: WebdriverIO.Config) {
const wrapStep = this.wrapStep
const cid = this._cid
let params: unknown
this._eventEmitter.on('getHookParams', (payload) => {
params = payload
})
const getHookParams = () => params
setDefinitionFunctionWrapper(
(fn: Function, options: StepDefinitionOptions = { retry: 0 }) => {
// hooks defined in wdio.conf are already wrapped
if (fn.name.startsWith('wdioHook')) {
return fn
}
const isStep = !fn.name.startsWith('userHook')
// Steps without retry options are returned as-is for performance
if (isStep && !options.retry) {
return fn
}
return wrapStep(fn, isStep, config, cid, options,
getHookParams, this._cucumberOpts.timeout)
}
)
}
The wrapStep() method wraps the step function with testFnWrapper from @wdio/utils, which handles:
- Invoking
config.beforeHookbefore step execution - Invoking
config.afterHookafter step execution - Retry logic based on
options.retry
Usage Example
From examples/wdio/cucumber/step-definitions.ts:
import { Given, When, Then } from '@wdio/cucumber-framework'
import { Key } from 'webdriverio'
Given(/^I go on the website "([^"]*)"$/, async (url) => {
await browser.url(url)
})
When(/^I add the following groceries$/, async (table) => {
const newTodo = await $('.new-todo')
table.rawTable.shift()
for (const [item, amount] of table.rawTable) {
await newTodo.addValue(`${item} (${amount}x)`)
await browser.keys(Key.Enter)
await browser.pause(100) // for demo purposes
}
})
Then(/^should the element "([^"]*)" be (\d+(?:\.\d+)?)px wide and (\d+(?:\.\d+)?)px high$/, async (selector, width, height) => {
const elemSize = await $(selector).getSize()
expect(elemSize.width).toBe(Number(width))
expect(elemSize.height).toBe(Number(height))
})
Then(/^should the title of the page be "([^"]*)"$/, async (expectedTitle) => {
await expect(browser).toHaveTitle(expectedTitle)
})
Then(/^I should have a list of (\d+) items$/, async (items) => {
await expect($$('.todo-list li')).toBeElementsArrayOfSize(items)
})
String Pattern (Cucumber Expression) Example
import { Given, Then } from '@wdio/cucumber-framework'
Given('I have {int} items in my cart', async (count) => {
// count is automatically parsed as a number
await expect($$('.cart-item')).toBeElementsArrayOfSize(count)
})
Then('the page title should be {string}', async (title) => {
await expect(browser).toHaveTitle(title)
})