Implementation:Webdriverio Webdriverio FetchMock
| Knowledge Sources | |
|---|---|
| Domains | Testing, Mocking |
| Last Updated | 2026-02-12 00:00 GMT |
Overview
Comprehensive WebDriver protocol mock that intercepts global fetch calls for unit testing, simulating browser session management, element interactions, script execution, and error scenarios.
Description
The fetch.ts mock module replaces the global fetch function with a vi.fn() mock implementation (requestMock) that simulates a complete WebDriver server. It sets process.env.WDIO_UNIT_TESTS to 1 to indicate a test environment and stubs WDIO_RESQ_SCRIPT and WDIO_FAKER_SCRIPT globals. The mock handles session creation (supporting both W3C and JSONWP modes, mobile mode, native app mode, Windows/Mac app mode, and BiDi mode), element finding (single and multiple, including shadow DOM traversal), element properties (rect, size, location, CSS values, attributes, displayed state), script execution (sync and async, including React ResQ queries, custom locator strategies, DOM traversal, and scroll/focus detection), cookies, window handles, URL/title retrieval, screenshots, and print-to-PDF. It also simulates error scenarios including stale elements, connection refused retries, timeouts, 404/500 errors, and HTML gateway errors. Helper methods setMockResponse, customResponseFor, getSessionId, setSessionId, and resetSessionId allow test cases to customize behavior.
Usage
Use this mock in unit tests across the WebdriverIO monorepo by importing __mocks__/fetch.ts. It provides deterministic responses for all WebDriver protocol commands, enabling isolated testing of WebdriverIO internals without a real browser. Tests can override responses via setMockResponse for single-use values or customResponseFor for pattern-matched persistent overrides.
Code Reference
Source Location
- Repository: Webdriverio_Webdriverio
- File: __mocks__/fetch.ts
Signature
const requestMock: vi.fn() = vi.fn().mockImplementation(
(uri: string | URL, params?: { body?: string }) => Response
)
requestMock.retryCnt: number
requestMock.setMockResponse: (value: any) => void
requestMock.customResponseFor: (pattern: RegExp, response: any) => void
requestMock.getSessionId: () => string
requestMock.setSessionId: (newSessionId: any) => void
requestMock.resetSessionId: () => void
Import
// Automatically applied via Vitest module mocking
// The mock is registered by: vi.stubGlobal('fetch', requestMock)
// In test files, access the mock via:
import { vi } from 'vitest'
const fetchMock = globalThis.fetch as any
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| uri | string or URL | Yes | The WebDriver protocol endpoint URL to call |
| params | { body?: string } | No | Request parameters; body is a JSON string containing the request payload |
Outputs
| Name | Type | Description |
|---|---|---|
| Response | Response | A Response.json() object containing the WebDriver protocol response with value property (and optionally sessionId and status in JSONWP mode) |
Helper Methods
setMockResponse(value)
Sets a manual mock response that overrides the default routing logic for the next request(s). Accepts a single value or an array of values that are consumed sequentially. After all values are consumed, normal routing resumes.
customResponseFor(pattern, response)
Registers a persistent custom response for any URL pathname matching the given RegExp pattern. If a pattern already exists, it is replaced. Custom responses take priority over the default switch-case routing.
getSessionId()
Returns the current mock session ID (default: "foobar-123").
setSessionId(newSessionId)
Overrides the mock session ID used in URL path matching.
resetSessionId()
Resets the session ID back to the default value "foobar-123".
Simulated Endpoints
| Endpoint Pattern | Description |
|---|---|
| /session | Session creation with W3C/JSONWP/mobile/BiDi support |
| /session/{id}/element | Single element lookup by selector |
| /session/{id}/elements | Multiple element lookup |
| /session/{id}/element/{id}/element | Nested element lookup |
| /session/{id}/element/{id}/shadow | Shadow root retrieval |
| /session/{id}/shadow/{id}/element(s) | Shadow DOM element queries |
| /session/{id}/element/{id}/rect | Element position and dimensions |
| /session/{id}/element/{id}/css/* | CSS property values |
| /session/{id}/element/{id}/property/* | Element property values |
| /session/{id}/element/{id}/attribute/* | Element attribute values |
| /session/{id}/element/{id}/displayed | Element visibility |
| /session/{id}/element/{id}/screenshot | Element screenshot (base64) |
| /session/{id}/execute/sync | Synchronous script execution |
| /session/{id}/execute/async | Asynchronous script execution |
| /session/{id}/cookie | Cookie retrieval |
| /session/{id}/window | Current window handle |
| /session/{id}/window/handles | All window handles |
| /session/{id}/url | Current URL |
| /session/{id}/title | Page title |
| /session/{id}/screenshot | Full page screenshot (base64) |
| /session/{id}/print | Print to PDF (base64) |
Usage Examples
import { vi, describe, it, expect, beforeEach } from 'vitest'
// The fetch mock is auto-loaded via __mocks__/fetch.ts
const fetchMock = globalThis.fetch as any
describe('WebDriver commands', () => {
beforeEach(() => {
fetchMock.mockClear()
fetchMock.retryCnt = 0
fetchMock.resetSessionId()
})
it('should override response for a single request', async () => {
fetchMock.setMockResponse({ value: 'custom-value' })
const res = await fetch(new URL('http://localhost/session/foobar-123/url'))
const json = await res.json()
expect(json.value).toBe('custom-value')
})
it('should register a custom response by pattern', async () => {
fetchMock.customResponseFor(
/\/session\/.*\/title/,
{ value: 'Custom Title' }
)
const res = await fetch(new URL('http://localhost/session/foobar-123/title'))
const json = await res.json()
expect(json.value).toBe('Custom Title')
})
})