Skip to main content

The Mock Object

The mock object is an object that represents a network mock and contains information about requests that were matching given url and filterOptions. It can be received using the mock command.

info

Note that using the mock command requires support for Chrome DevTools protocol. That support is given if you run tests locally in Chromium based browser or if you use a Selenium Grid v4 or higher. This command can not be used when running automated tests in the cloud. Find out more in the Automation Protocols section.

You can read more about mocking requests and responses in WebdriverIO in our Mocks and Spies guide.

Properties

A mock object contains the following properties:

NameTypeDetails
urlStringThe url passed into the mock command
filterOptionsObjectThe resource filter options passed into the mock command
browserObjectThe Browser Object used to get the mock object.
callsObject[]Information about matching browser requests, containing properties such as url, method, headers, initialPriority, referrerPolic, statusCode, responseHeaders and body

Methods

Mock objects provide various commands, listed in the mock section, that allow users to modify the behavior of the request or response.

Events

The mock object is an EventEmitter and a couple of events are emitted for your use cases.

Here is a list of events.

request

This event is being emitted when launching a network request that matches mock patterns. Request is passed in event callback.

Request interface:

interface RequestEvent {
requestId: number
request: Matches
responseStatusCode: number
responseHeaders: Record<string, string>
}

overwrite

This event is being emitted when network response is overwrited with respond or respondOnce. Response is passed in event callback.

Response interface:

interface OverwriteEvent {
requestId: number
responseCode: number
responseHeaders: Record<string, string>
body?: string | Record<string, any>
}

fail

This event is being emitted when network request is aborted with abort or abortOnce. Fail is passed in event callback.

Fail interface:

interface FailEvent {
requestId: number
errorReason: Protocol.Network.ErrorReason
}

match

This event is being emitted when new match is added, before continue or overwrite. Match is passed in event callback.

Match interface:

interface MatchEvent {
url: string // Request URL (without fragment).
urlFragment?: string // Fragment of the requested URL starting with hash, if present.
method: string // HTTP request method.
headers: Record<string, string> // HTTP request headers.
postData?: string // HTTP POST request data.
hasPostData?: boolean // True when the request has POST data.
mixedContentType?: MixedContentType // The mixed content export type of the request.
initialPriority: ResourcePriority // Priority of the resource request at the time request is sent.
referrerPolicy: ReferrerPolicy // The referrer policy of the request, as defined in https://www.w3.org/TR/referrer-policy/
isLinkPreload?: boolean // Whether is loaded via link preload.
body: string | Buffer | JsonCompatible // Body response of actual resource.
responseHeaders: Record<string, string> // HTTP response headers.
statusCode: number // HTTP response status code.
mockedResponse?: string | Buffer // If mock, emitting the event, also modified it's response.
}

continue

This event is being emitted when the network response has neither been overwritten nor interrupted, or if response was already sent by another mock. requestId is passed in event callback.

Examples

Getting a number of pending requests:

let pendingRequests = 0
const mock = await browser.mock('**') // it is important to match all requests otherwise, the resulting value can be very confusing.
mock.on('request', ({request}) => {
pendingRequests++
console.log(`matched request to ${request.url}, pending ${pendingRequests} requests`)
})
mock.on('match', ({url}) => {
pendingRequests--
console.log(`resolved request to ${url}, pending ${pendingRequests} requests`)
})

Throwing an error on 404 network fail:

browser.addCommand('loadPageWithout404', (url, {selector, predicate}) => new Promise(async (resolve, reject) => {
const mock = await this.mock('**')

mock.on('match', ({url, statusCode}) => {
if (statusCode === 404) {
reject(new Error(`request to ${url} failed with "Not Found"`))
}
})

await this.url(url).catch(reject)

// waiting here, because some requests can still be pending
if (selector) {
await this.$(selector).waitForExist().catch(reject)
}

if (predicate) {
await this.waitUntil(predicate).catch(reject)
}

resolve()
}))

await browser.loadPageWithout404(browser, 'some/url', { selector: 'main' })

Determining if mock respond value was used:

const firstMock = await browser.mock('**/foo/**')
const secondMock = await browser.mock('**/foo/bar/**')

firstMock.respondOnce({id: 3, title: 'three'})
secondMock.respond({id: 4, title: 'four'})

firstMock.on('overwrite', () => {
// triggers for first request to '**/foo/**'
}).on('continue', () => {
// triggers for rest requests to '**/foo/**'
})

secondMock.on('continue', () => {
// triggers for first request to '**/foo/bar/**'
}).on('overwrite', () => {
// triggers for rest requests to '**/foo/bar/**'
})

In this example, firstMock was defined first and has one respondOnce call, so the secondMock response value will not be used for the first request, but will be used for the rest of them.