Intercept Service
wdio-intercept-service is a 3rd party package, for more information please see GitHub | npm
🕸 Capture and assert HTTP ajax calls in webdriver.io
This is a plugin for webdriver.io. If you don't know it yet, check it out, it's pretty cool.
Although selenium and webdriver are used for e2e and especially UI testing, you might want to assess HTTP requests done by your client code (e.g. when you don't have immediate UI feedback, like in metrics or tracking calls). With wdio-intercept-service you can intercept ajax HTTP calls initiated by some user action (e.g. a button press, etc.) and make assertions about the request and corresponding responses later.
There's one catch though: you can't intercept HTTP calls that are initiated on page load (like in most SPAs), as it requires some setup work that can only be done after the page is loaded (due to limitations in selenium). That means you can just capture requests that were initiated inside a test. If you're fine with that, this plugin might be for you, so read on.
Prerequisites
- webdriver.io v5.x or newer.
Heads up! If you're still using webdriver.io v4, please use the v2.x branch of this plugin!
Installation
npm install wdio-intercept-service -D
Usage
Usage with WebDriver CLI
It should be as easy as adding wdio-intercept-service to your wdio.conf.js
:
exports.config = {
// ...
services: ['intercept']
// ...
};
and you're all set.
Usage with WebDriver Standalone
When using WebdriverIO Standalone, the before
and beforeTest
/ beforeScenario
functions need to be called manually.
import { remote } from 'webdriverio';
import WebdriverAjax from 'wdio-intercept-service'
const WDIO_OPTIONS = {
port: 9515,
path: '/',
capabilities: {
browserName: 'chrome'
},
}
let browser;
const interceptServiceLauncher = WebdriverAjax();
beforeAll(async () => {
browser = await remote(WDIO_OPTIONS)
interceptServiceLauncher.before(null, null, browser)
})
beforeEach(async () => {
interceptServiceLauncher.beforeTest()
})
afterAll(async () => {
await client.deleteSession()
});
describe('', async () => {
... // See example usage
});
Once initialized, some related functions are added to your browser command chain (see API).
Quickstart
Example usage:
browser.url('http://foo.bar');
browser.setupInterceptor(); // capture ajax calls
browser.expectRequest('GET', '/api/foo', 200); // expect GET request to /api/foo with 200 statusCode
browser.expectRequest('POST', '/api/foo', 400); // expect POST request to /api/foo with 400 statusCode
browser.expectRequest('GET', /\/api\/foo/, 200); // can validate a URL with regex, too
browser.click('#button'); // button that initiates ajax request
browser.pause(1000); // maybe wait a bit until request is finished
browser.assertRequests(); // validate the requests
Get details about requests:
browser.url('http://foo.bar')
browser.setupInterceptor();
browser.click('#button')
browser.pause(1000);
var request = browser.getRequest(0);
assert.equal(request.method, 'GET');
assert.equal(request.response.headers['content-length'], '42');
Supported browsers
It should work with somewhat newer versions of all browsers. Please report an issue if it doesn't seem to work with yours.
API
Consult the TypeScript declaration file for the the full syntax of the custom commands added to the WebdriverIO browser object. In general, any method that takes an "options" object as a parameter can be called without that parameter to obtain the default behavior. These "optional options" objects are followed by ?: = {}
and the default values inferred are described for each method.
Option Descriptions
This library offers a small amount of configuration when issuing commands. Configuration options that are used by multiple methods are described here (see each method definition to determine specific support).
orderBy
('START' | 'END'
): This option controls the ordering of requests captured by the interceptor, when returned to your test. For backwards compatibility with existing versions of this library, the default ordering is'END'
, which corresponds to when the request was completed. If you set theorderBy
option to'START'
, then the requests will be ordered according to the time that they were started.includePending
(boolean
): This option controls whether not-yet-completed requests will be returned. For backwards compatibility with existing versions of this library, the default value isfalse
, and only completed requests will be returned.
browser.setupInterceptor()
Captures ajax calls in the browser. You always have to call the setup function in order to assess requests later.
browser.disableInterceptor()
Prevents further capture of ajax calls in the browser. All captured request information is removed. Most users will not need to disable the interceptor, but if a test is particularly long-running or exceeds the session storage capacity, then disabling the interceptor can be helpful.
browser.excludeUrls(urlRegexes: (string | RegExp)[])
Excludes requests from certain urls from being recorded. It takes an array of strings or regular expressions. Before writing to storage, tests the url of the request against each string or regex. If it does, the request is not written to storage. Like disableInterceptor, this can be helpful if running into problems with session storage exceeding capacity.
browser.expectRequest(method: string, url: string, statusCode: number)
Make expectations about the ajax requests that are going to be initiated during the test. Can (and should) be chained. The order of the expectations should map to the order of the requests being made.
method
(String
): http method that is expected. Can be anythingxhr.open()
accepts as first argument.url
(String
|RegExp
): exact URL that is called in the request as a string or RegExp to matchstatusCode
(Number
): expected status code of the response
browser.getExpectations()
Helper method. Returns all the expectations you've made up until that point
browser.resetExpectations()
Helper method. Resets all the expectations you've made up until that point