import xhrMock from 'xhr-mock'; import qs from 'qs'; import { cleanObject } from '../utils/cleanObject'; type MockResponseCb = (request: { data?: any; method: string; params?: any; status: string; }) => any; type Mock = { url: string; method: string; status: number; response: any | MockResponseCb; } export class MockXHR { spy = jest.fn(); mocks: Mock[] = []; constructor(mocks?: Mock[]) { xhrMock.setup(); this.mocks = mocks || []; this.mocks.forEach((mock) => { this.add(mock); }); } add(mock: Mock) { const url = new RegExp( mock.url .replace('?', '\\?') ); xhrMock[mock.method.toLowerCase()](url, async (req, res) => { const params = req.url().query; const url = req.url().path; const request = cleanObject({ url, method: req.method(), data: JSON.parse(req.body() || '{}'), params: qs.parse( qs.stringify({ ...params, ...typeof params.request === 'string' ? { request: JSON.parse(params.request) } : {} }, {arrayFormat: 'repeat'} ) ) }); this.spy(request); return res.status(mock.status) .body( JSON.stringify( typeof mock.response === 'function' ? mock.response(request) : mock.response ) ); }); } destroy() { xhrMock.teardown(); this.mocks = []; } reset() { this.mocks = []; this.spy.mockClear(); xhrMock.reset(); } }