Check for failed http requests in the TestCafe fixture

Viewed 92

At times I encounter 500 and 502 errors when accessing parts of our application and we would like to be able to catch that error and fail the TestCafe test.

We currently have this setup https://stackoverflow.com/a/52443604/7551391 and it works fine when we call the waitForFailedRequest function and it's wrapped around the contents of the test but we would like to call it in the fixture or globally so that it will always look for 500, etc errors on each test.

My main question is what to use for the action param in failed_requests.waitForFailedRequest() so that it's called on every test.

failed_request_hooks.js

import EventEmitter from 'events'
import { RequestHook } from 'testcafe'


export class FailedRequestsLogger extends RequestHook {
    constructor (requestFilterRules, responseEventConfigureOpts) {
        super(requestFilterRules, responseEventConfigureOpts)

        this.events = new EventEmitter()
        this.failedRequestPromise = new Promise(resolve => this.events.once('failed-request', resolve))
    }

    async onRequest (event) {
    }

    async onResponse (event) {
        if (event.statusCode >= 500) {
            this.events.emit('failed-request', event.statusCode)
        }
    }

    async waitForFailedRequest (action) {                                                                                                          
        return Promise.race([                                                                                                                
                action(),                                                                                                                    
                this.failedRequestPromise.then(statusCode => Promise.reject(new Error(`Request failed with the ${statusCode} status code`))) 
        ])                                                                                                                
    }
}

test_file

import { ClientFunction, Selector } from 'testcafe'
import { FailedRequestsLogger } from '../../api/failed_request_hook'
import data from '../../data/data.json'
import EditUrlRedirectsObjects from '../../pom/sites/url_redirects/edit_redirects_page_repo'
import GooglePreviewPageObjects from '../../pom/sites/url_redirects/google_preview_page_repo'
import HelperObjects from '../../pom/helpers'
import LoginPageObjects from '../../pom/login/login_page_repo'
import SitesPageObjects from '../../pom/sites/sites_page_repo'
import URLRedirectsPageObjects from '../../pom/sites/url_redirects/url_redirects_page_repo'
import WorkspaceMainNavPageObjects from '../../pom/navigation/workspace_main_nav_page_repo'


const failed_requests = new FailedRequestsLogger(/.*reborncf\.com/)

fixture `sites - url redirects`
  .page `${HelperObjects.get_base_url()}`
  .requestHooks(failed_requests)
  .beforeEach(async t => {
    await LoginPageObjects.login_with_password()
    await failed_requests.waitForFailedRequest()
  })
1 Answers

There are a few ways to implement this in your use case. You can create a request hook globally and use it as illustrated here: https://stackoverflow.com/a/52443604/7551391:

//customRequestHook.js
const EventEmitter = require('events');
const { RequestHook } = require('testcafe');

class CustomRequestHook extends RequestHook {
    constructor (...args) {                                                                                                                  
        super(...args);                                                                                                                      

        this.events = new EventEmitter();                                                                                                    
        this.failedRequestPromise = new Promise(resolve => this.events.once('failed-request', resolve));                                     
    }                                                                                                                                        

    onRequest (request) {                                                                                                                    
    }                                                                                                                                        

    onResponse (response) {                                                                                                                  
        if (response.statusCode >= 500)                                                                                                      
            this.events.emit('failed-request', response.statusCode);                                                                         
    }                                                                                                                                        

    waitForFailedRequest (action) {                                                                                                          
        return Promise.race([                                                                                                                
                action(),                                                                                                                    
                this.failedRequestPromise.then(statusCode => Promise.reject(new Error(`Request failed with the ${statusCode} status code`))) 
        ])                                                                                                                                   
    }    
}

module.exports = new CustomRequestHook();
//.testcafers.js
const customRequestHook = require('./customRequestHook.js');

module.exports = {
  hooks: {
    request: customRequestHook,
  },
};
//test.js
import customRequestHook from './customRequestHook.js';

fixture`Fixture`
    .page('https://devexpress.github.io/testcafe/example/')
    .beforeEach(async t => {
        await customRequestHook.waitForFailedRequest(5000)
    });

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

If you don't want to cover your custom code, you can reorganize waitForFailedRequest and insert a timeout into it:

//customRequestHook.js
const EventEmitter = require('events');
const { RequestHook } = require('testcafe');

class CustomRequestHook extends RequestHook {
    constructor (...args) {                                                                                                                  
        super(...args);                                                                                                                      

        this.events = new EventEmitter();                                                                                                    
        this.failedRequestPromise = new Promise(resolve => this.events.once('failed-request', resolve));                                     
    }                                                                                                                                        

    onRequest (request) {                                                                                                                    
    }                                                                                                                                        

    onResponse (response) {                                                                                                                  
        if (response.statusCode >= 500)                                                                                                      
            this.events.emit('failed-request', response.statusCode);                                                                         
    }                                                                                                                                        

    waitForFailedRequest(timeout) {
        return Promise.race([
            new Promise(resolve => setTimeout(resolve, timeout)),
            this.failedRequestPromise.then(statusCode => Promise.reject(new Error(`Request failed with the ${statusCode} status code`)))
        ])
    } 
}

module.exports = new CustomRequestHook();
//.testcafers.js
const customRequestHook = require('./customRequestHook.js');

module.exports = {
  hooks: {
    request: customRequestHook,
  },
};
//test.js
import customRequestHook from './customRequestHook.js';

fixture`Fixture`
    .page('https://devexpress.github.io/testcafe/example/')
    .beforeEach(async t => {
        await customRequestHook.waitForFailedRequest(5000)
    });

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

Keep in mind that you can change the waitForFailedRequest method as you want because it isn't a TestCafe method. Only JS syntax limits you.

Related