npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

wdio-intercept-service

v4.4.1

Published

Capture and assert HTTP ajax calls in webdriver.io 🕸

Downloads

341,462

Readme

WebdriverIO Intercept Service

🕸 Capture and assert HTTP ajax calls in webdriver.io

Tests Join the chat at https://gitter.im/wdio-intercept-service/community

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 the orderBy 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 is false, 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 anything xhr.open() accepts as first argument.
  • url (String|RegExp): exact URL that is called in the request as a string or RegExp to match
  • statusCode (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

browser.assertRequests({ orderBy?: 'START' | 'END' }?: = {})

Call this method when all expected ajax requests are finished. It compares the expectations to the actual requests made and asserts the following:

  • Count of the requests that were made
  • The order of the requests
  • The method, the URL and the statusCode should match for every request made
  • The options object defaults to { orderBy: 'END' }, i.e. when the requests were completed, to be consistent with the behavior of v4.1.10 and earlier. When the orderBy option is set to 'START', the requests will be ordered by when they were initiated by the page.

browser.assertExpectedRequestsOnly({ inOrder?: boolean, orderBy?: 'START' | 'END' }?: = {})

Similar to browser.assertRequests, but validates only the requests you specify in your expectRequest directives, without having to map out all the network requests that might happen around that. If inOrder option is true (default), the requests are expected to be found in the same order as they were setup with expectRequest.

browser.getRequest(index: number, { includePending?: boolean, orderBy?: 'START' | 'END' }?: = {})

To make more sophisticated assertions about a specific request you can get details for a specific request. You have to provide the 0-based index of the request you want to access, in the order the requests were completed (default), or initiated (by passing the orderBy: 'START' option).

  • index (number): number of the request you want to access
  • options (object): Configuration options
  • options.includePending (boolean): Whether not-yet-completed requests should be returned. By default, this is false, to match the behavior of the library in v4.1.10 and earlier.
  • options.orderBy ('START' | 'END'): How the requests should be ordered. By default, this is 'END', to match the behavior of the library in v4.1.10 and earlier. If 'START', the requests will be ordered by the time of initiation, rather than the time of request completion. (Since a pending request has not yet completed, when ordering by 'END' all pending requests will come after all completed requests.)

Returns request object:

  • request.url: requested URL
  • request.method: used HTTP method
  • request.body: payload/body data used in request
  • request.headers: request http headers as JS object
  • request.pending: boolean flag for whether this request is complete (i.e. has a response property), or in-flight.
  • request.response: a JS object that is only present if the request is completed (i.e. request.pending === false), containing data about the response.
  • request.response?.headers: response http headers as JS object
  • request.response?.body: response body (will be parsed as JSON if possible)
  • request.response?.statusCode: response status code

A note on request.body: wdio-intercept-service will try to parse the request body as follows:

  • string: Just return the string ('value')
  • JSON: Parse the JSON object using JSON.parse() (({ key: value }))
  • FormData: Will output the FormData in the format { key: [value1, value2, ...] }
  • ArrayBuffer: Will try to convert the buffer to a string (experimental)
  • Anything else: Will use a brutal JSON.stringify() on your data. Good luck!

For the fetch API, we only support string and JSON data!

browser.getRequests({ includePending?: boolean, orderBy?: 'START' | 'END' }?: = {})

Get all captured requests as an array, supporting the same optional options as getRequest.

Returns array of request objects.

browser.hasPendingRequests()

A utility method that checks whether any HTTP requests are still pending. Can be used by tests to ensure all requests have completed within a reasonable amount of time, or to verify that a call to getRequests() or assertRequests() will include all of the desired HTTP requests.

Returns boolean

TypeScript support

This plugin provides its own TS types. Just point your tsconfig to the type extensions like mentioned here:

"compilerOptions": {
    // ..
    "types": ["node", "webdriverio", "wdio-intercept-service"]
},

Running the tests

Recent versions of Chrome and Firefox are required to run the tests locally. You may need to update the chromedriver and geckodriver dependencies to match the version installed on your system.

npm test

Contributing

I'm happy for every contribution. Just open an issue or directly file a PR.
Please note that this interceptor library is written to work with legacy browsers such as Internet Explorer. As such, any code used in lib/interceptor.js must at least be parseable by Internet Explorer's JavaScript runtime.

License

MIT