Creating a Custom HTTP Request Hook

You can create your own request hook to handle HTTP requests. This topic describes request hooks and how to create a custom hook.

Understand How TestCafe Request Hooks Operate

  • All TestCafe request hooks inherit from the RequestHook class.

    import { RequestHook } from 'testcafe';
    
    class MyRequestHook extends RequestHook {
        // ...
    }
    

    This class has the following public interface:

    class RequestHook {
        constructor (requestFilterRules, responseEventConfigureOpts) {
            // ...
        }
    
        async onRequest (event) {
            // ...
        }
    
        async onResponse (event) {
            // ...
        }
    }
    
  • The base class constructor receives an array of filter rules as the first parameter to determine which requests the hook handles. All requests are handled if no rules are passed.

    class RequestHook {
        constructor (requestFilterRules, /* other params */) {
            console.log(requestFilterRules[0]); // http://example.com
            console.log(requestFilterRules[1]); // /\/api\/users\//
        }
    }
    
  • The onRequest asynchronous method is called before the request is sent. Use this method to handle sending the request. You can change the request parameters before it is sent.

    This method is abstract in the base class and needs to be overriden in the subclass.

    async onRequest (/*RequestEvent event*/) {
        throw new Error('Not implemented');
    }
    
  • When a response is received, the hook starts preparing to call the onResponse method that handles the response.

    At this moment, the hook processes settings that define whether to pass the response headers and body to the onResponse method. These settings are specified in the second constructor parameter. This parameter takes an object with the includeHeaders and includeBody properties that have the false value by default.

    class RequestHook {
        constructor (requestFilterRules, responseEventConfigureOpts) {
            console.log(responseEventConfigureOpts.includeHeaders); // false
            console.log(responseEventConfigureOpts.includeBody);    // false
        }
    }
    
  • Finally, the onResponse asynchronous method is called. This an abstract method in the base class. Override it in the descendant to handle sending the request.

    async onResponse (/*ResponseEvent event*/) {
        throw new Error('Not implemented');
    }
    

Write a Hook

Do the following to write a custom hook:

  • inherit from the RequestHook class,
  • override the onRequest method to handle sending the request,
  • override the onResponse method to handle receiving the response.
import { RequestHook } from 'testcafe';

class MyRequestHook extends RequestHook {
    constructor (requestFilterRules, responseEventConfigureOpts) {
        super(requestFilterRules, responseEventConfigureOpts);
        // ...
    }
    async onRequest (event) {
        // ...
    }
    async onResponse (event) {
        // ...
    }
}

The onRequest and onResponse methods receive objects that contain the event parameters.

The onRequest Method

The onRequest method's event object exposes the following fields.

Property Type Description
requestOptions RequestOptions Contains the request parameters. You can use it to change the request parameters before the request is sent.
isAjax Boolean Specifies if the request is performed using AJAX.
async onRequest (event) {
    if(event.isAjax) {
        console.log(event.requestOptions.url);
        console.log(event.requestOptions.credentials.username);

        event.requestOptions.headers['custom-header'] = 'value';
    }
}

The onResponse Method

The onResponse method's event object exposes the following properties:

Property Type Description
statusCode Number The response status code.
headers Object The response headers in a property-value form.
body Buffer The response body.
async onResponse (event) {
    if(event.statusCode === 200)
        console.log(event.headers['Content-Type']);
}

Use the Hook

Attach the hook to a test or fixture in your test suite.

import { MyRequestHook } from './my-request-hook';

const customHook = new MyRequestHook(/https?:\/\/example.com/);

fixture `My fixture`
    .page('http://example.com')
    .requestHooks(customHook);

test('My test', async t => {
        // test actions
});

The hook now handles the requests sent during the test or fixture run.