Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XMLHttpRequest testing in Jest

I want to test AJAX methods (vanilla XHR) and I can't find the way to do it with Jest framework. I found mock-ajax.js for Jasmine. The problem is I can't find the way to install it.

Is there maybe a better way to unit test Ajax functions in Jest?

like image 671
Tomasz Kasperek Avatar asked Feb 18 '15 13:02

Tomasz Kasperek


3 Answers

The jest api has changed a bit. This is what I use. It doesn't do anything but it's enough to render my components.

const xhrMockClass = () => ({
  open            : jest.fn(),
  send            : jest.fn(),
  setRequestHeader: jest.fn()
})

window.XMLHttpRequest = jest.fn().mockImplementation(xhrMockClass)

and in the test file:

import '../../__mock__/xhr-mock.js'

like image 197
ThaJay Avatar answered Oct 15 '22 08:10

ThaJay


You can test XHR in Jest without additional packages. This is helper function which creates mock object for XMLHttpRequest:

let open, send, onload, onerror;

function createXHRmock() {
    open = jest.genMockFn();

    // be aware we use *function* because we need to get *this* 
    // from *new XmlHttpRequest()* call
    send = jest.genMockFn().mockImpl(function(){   
        onload = this.onload.bind(this);
        onerror = this.onerror.bind(this);
    });

    const xhrMockClass = function () {
        return {
            open,
            send
        };
    };

    window.XMLHttpRequest = jest.genMockFn().mockImpl(xhrMockClass);
}

And you can use it in test as follows:

it('XHR success', () => {
    createXHRmock();

    // here you should call GET request

    expect(open).toBeCalledWith('GET', 'http://example.com', true);
    expect(send).toBeCalled();

    // call onload or onerror
    onload();

    // here you can make your assertions after onload
});
like image 19
Alexander Ivantsov Avatar answered Oct 15 '22 09:10

Alexander Ivantsov


Here's a TypeScript example working with Jest 26:

function performRequest(callback: any) {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://example.com/');
  xhr.onreadystatechange = () => {
    if (xhr.readyState !== 4 || xhr.status !== 200) return;
    callback(xhr.response);
  };
  xhr.responseType = 'json';
  xhr.setRequestHeader('Accept', 'application/json');
  xhr.send(null);
}

describe('request', () => {
  const xhrMock: Partial<XMLHttpRequest> = {
    open: jest.fn(),
    send: jest.fn(),
    setRequestHeader: jest.fn(),
    readyState: 4,
    status: 200,
    response: 'Hello World!'
  };

  jest.spyOn(window, 'XMLHttpRequest').mockImplementation(() => xhrMock as XMLHttpRequest);
  const callback = jest.fn();
  performRequest(callback);
  expect(xhrMock.open).toBeCalledWith('GET', 'https://example.com/');
  expect(xhrMock.setRequestHeader).toBeCalledWith('Accept', 'application/json');
  (xhrMock.onreadystatechange as EventListener)(new Event(''));
  expect(callback.mock.calls).toEqual([['Hello World!']]);
});
like image 13
simon04 Avatar answered Oct 15 '22 08:10

simon04