Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Webdriverio Webdriverio Shim

From Leeroopedia
Knowledge Sources
Domains Core_Architecture, Command_Wrapping
Last Updated 2026-02-12 00:00 GMT

Overview

Provides command wrapping with before/after hook execution, chainable element query proxying, and async test execution with retry and timeout support.

Description

The Shim module is a central piece of WebdriverIO's command execution pipeline. executeHooksWithArgs runs an array of hook functions concurrently, catching errors and handling Mocha/Jasmine skip signals gracefully. wrapCommand wraps each protocol or element command with beforeCommand and afterCommand hook invocation, and for element query commands ($, $$, etc.) returns a Proxy-based chainable promise that intercepts property access to enable fluent chaining like $('foo').$('bar').getText(). The proxy handles numeric indexing for element arrays with automatic waitUntil for out-of-bounds access, iterator protocol support, and delegation to pIteration methods for array operations. executeAsync runs spec or hook functions with a timeout race and retry logic, respecting framework-specific timeouts from Mocha and Jasmine. A module-level inCommandHook flag prevents recursive hook execution.

Usage

Use wrapCommand when registering protocol commands on the WebdriverIO client to ensure hooks are executed and element chaining works. Use executeHooksWithArgs to run lifecycle hooks (beforeTest, afterTest, etc.) from framework adapters. Use executeAsync within test framework wrappers to execute spec and hook functions with timeout and retry support.

Code Reference

Source Location

Signature

export async function executeHooksWithArgs<T>(
    this: unknown,
    hookName: string,
    hooks?: Function | Function[],
    args?: unknown[]
): Promise<(T | Error)[]>

export function wrapCommand<T>(
    commandName: string,
    fn: Function
): (...args: unknown[]) => Promise<T>

export async function executeAsync(
    this: WebdriverIOInstance,
    fn: Function,
    retries: Frameworks.TestRetries,
    args?: unknown[],
    timeout?: number
): Promise<unknown>

Import

import { executeHooksWithArgs, wrapCommand, executeAsync } from '@wdio/utils'

I/O Contract

Inputs

Name Type Required Description
hookName string Yes (executeHooksWithArgs) Name of the hook being executed (e.g., "beforeCommand", "afterTest"), used for logging.
hooks Function or Function[] No Single hook function or array of hook functions to execute concurrently.
args unknown[] No Arguments to pass to each hook function via apply.
commandName string Yes (wrapCommand) Name of the command being wrapped (e.g., "getTitle", "$").
fn Function Yes The original command or spec function to wrap.
retries Frameworks.TestRetries Yes (executeAsync) Object with limit (max retries) and attempts (current attempt count).
timeout number No (executeAsync) Maximum time in milliseconds to wait for function completion. Defaults to 20000ms minus a 3ms buffer.

Outputs

Name Type Description
executeHooksWithArgs result Promise<(T or Error)[]> Array of hook return values or Error objects for hooks that threw (errors are caught, not re-thrown).
wrapCommand result (...args) => Promise<T> A wrapped function that executes beforeCommand hooks, runs the command, executes afterCommand hooks, and supports element chaining via Proxy.
executeAsync result Promise<unknown> The resolved value of the spec/hook function, or throws after all retries are exhausted or timeout occurs.

Usage Examples

import { executeHooksWithArgs, wrapCommand, executeAsync } from '@wdio/utils'

// Execute before hooks
const hookResults = await executeHooksWithArgs.call(
    browser,
    'beforeCommand',
    [
        (commandName, args) => console.log(`Running ${commandName}`),
        (commandName, args) => analytics.track(commandName)
    ],
    ['click', [{ x: 100, y: 200 }]]
)

// Wrap a protocol command
const wrappedGetTitle = wrapCommand('getTitle', async function () {
    const response = await this.execute('getTitle')
    return response.value
})

// Execute a test function with retries
const result = await executeAsync.call(
    testContext,
    async () => {
        const title = await browser.getTitle()
        expect(title).toBe('My Page')
    },
    { limit: 2, attempts: 0 },
    [],
    30000
)

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment