Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Principle:Webdriverio Webdriverio Plugin Resolution

From Leeroopedia
Revision as of 17:39, 16 February 2026 by Admin (talk | contribs) (Auto-imported from principles/Webdriverio_Webdriverio_Plugin_Resolution.md)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Template:Metadata

Overview

A mechanism for dynamically discovering and loading WebdriverIO plugins at runtime using naming convention resolution.

Description

Plugin Resolution is the process of finding and importing plugin modules (services, reporters, framework adapters) at runtime based on naming conventions. When a user specifies a plugin by short name (e.g., 'browserstack'), the resolver tries multiple naming patterns to locate the corresponding npm package. This convention-over-configuration approach simplifies plugin registration while supporting both scoped (@wdio/) and community (wdio-) package naming.

The resolution mechanism solves a fundamental plugin ecosystem challenge: allowing users to reference plugins by short, memorable names while the actual npm packages may follow different naming conventions depending on whether they are official (@wdio/ scoped) or community-maintained (wdio- prefixed).

The plugin resolution system handles three categories of plugins:

  • Services -- Extensions that hook into the test lifecycle (e.g., 'browserstack' resolves to @wdio/browserstack-service)
  • Reporters -- Test result formatters (e.g., 'allure' resolves to @wdio/allure-reporter)
  • Runners -- Test execution engines (e.g., 'local' resolves to @wdio/local-runner)

The resolution is lazy -- plugins are only loaded when the test runner initializes, not when the configuration file is parsed. This means misconfigured plugin names only produce errors at runtime, but it also means unused plugins do not consume resources.

Beyond name resolution, the plugin system handles three distinct registration forms:

  1. String names -- Resolved via initializePlugin using the naming convention chain
  2. Class references -- Used directly without any resolution (e.g., passing an imported class)
  3. Object literals -- Used as-is as hook containers (e.g., inline { beforeTest: fn } objects)

This flexibility allows users to mix published npm packages with local custom implementations in the same configuration.

Usage

Plugin resolution happens automatically when WDIO loads configuration. Users specify plugins by short name in services/reporters arrays. The resolver handles the actual module import. Understanding the resolution order helps debug plugin loading failures.

Standard usage -- short names:

// wdio.conf.ts
export const config: WebdriverIO.Config = {
    // 'browserstack' → tries @wdio/browserstack-service, then wdio-browserstack-service
    services: ['browserstack'],

    // 'allure' → tries @wdio/allure-reporter, then wdio-allure-reporter
    reporters: ['allure'],

    // 'local' → tries @wdio/local-runner, then wdio-local-runner
    runner: 'local'
}

Scoped package names (direct import):

// wdio.conf.ts
export const config: WebdriverIO.Config = {
    // Starts with '@', so imported directly (no naming convention applied)
    services: ['@wdio/browserstack-service'],
    reporters: ['@my-org/custom-reporter']
}

Absolute paths (direct import):

// wdio.conf.ts
export const config: WebdriverIO.Config = {
    // Absolute paths are imported directly via file:// URL
    services: ['/home/user/project/my-service.js']
}

Debugging resolution failures:

When a plugin cannot be found, WDIO throws a descriptive error listing all attempted names:

Couldn't find plugin "custom" service, neither as wdio scoped package
"@wdio/custom-service" nor as community package "wdio-custom-service".
Please make sure you have it installed!

When to use:

  • Referencing any WDIO plugin by its short name in configuration
  • Understanding why a plugin fails to load

When not to use:

  • When passing class references or object literals directly (these bypass resolution entirely)

Theoretical Basis

The resolver follows a Chain of Responsibility pattern with a fixed resolution order:

  1. Direct import -- If the name starts with @ (scoped package) or is an absolute path, import it directly. This is the first link in the chain because scoped names and absolute paths are unambiguous.
  2. Scoped convention -- Try @wdio/{name}-{type} (e.g., @wdio/browserstack-service). This is tried second because official WDIO packages use this convention.
  3. Community convention -- Try wdio-{name}-{type} (e.g., wdio-browserstack-service). This is the fallback for backward compatibility with the pre-monorepo naming convention.

The first successful import wins. If all attempts fail, a descriptive error is thrown listing all attempted package names.

This pattern provides several benefits:

Property Benefit
Convention over configuration Users write 'browserstack' instead of '@wdio/browserstack-service'
Backward compatibility Community packages using the old wdio- prefix still work
Explicit override Scoped names and absolute paths bypass convention resolution entirely
Safe import The safeImport utility catches import errors (like missing packages) without crashing, allowing the chain to continue

The resolution is combined with an initialization pipeline that handles the three registration forms:

User Config → sanitizeServiceArray → initializeServices → initializeLauncherService / initializeWorkerService
                                          ↓
                                    For each service:
                                    1. Object? → use directly
                                    2. Function? → instantiate with new
                                    3. String? → initializePlugin() → import → instantiate

The separation between launcher services and worker services is also handled during initialization. If a resolved plugin has no default export (only a launcher export), it is added to ignoredWorkerServices so worker processes do not attempt to load it.

Related Pages

Implementation:Webdriverio_Webdriverio_InitializePlugin_Function

Page Connections

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