UNPKG

@pkyeck/storybook-addon-mock

Version:
734 lines (675 loc) 25.2 kB
"use strict"; var _faker = require("./faker"); function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } // import { newMockXhr } from 'mock-xmlhttprequest'; // function setRealRequestInterceptors(realRequestInterceptor) { // global.XMLHttpRequest = newMockXhr(); // global.XMLHttpRequest.onSend = realRequestInterceptor; // return () => { // delete global.XMLHttpRequest; // }; // } var mockFaker = null; function setupMockFaker(mockFakerRequests) { if (!mockFaker) { mockFaker = new _faker.Faker(); } if (mockFakerRequests) { mockFaker.makeInitialRequestMap(mockFakerRequests); } var resetMock = function resetMock() { mockFaker.restore(); }; return [mockFaker, resetMock]; } // function setupMocks(mockFakerRequests, realRequestInterceptor) { // let disposers = []; // if (realRequestInterceptor) { // disposers.push(setRealRequestInterceptors(realRequestInterceptor)); // } // const [faker, fakerDisposer] = setupMockFaker(mockFakerRequests); // disposers.push(fakerDisposer); // return { // faker, // dispose: () => { // disposers.forEach((fn) => fn()); // disposers = []; // }, // }; // } // async function getEntangledFakeAndRealXHRs(options) { // let realXHR = {}; // let setHeaderSpy = undefined; // const originalXHR = global.realXMLHttpRequest; // global.realXMLHttpRequest = new Proxy(originalXHR, { // construct(target, args, newTarget) { // realXHR = Reflect.construct(target, args, newTarget); // setHeaderSpy = jest.spyOn(realXHR, 'setRequestHeader'); // return realXHR; // }, // }); // const fakeXhr = new XMLHttpRequest(); // const fakeXhrFinished = () => // new Promise((resolve) => fakeXhr.addEventListener('loadend', resolve)); // options.events?.forEach((event) => { // const mockFn = jest.fn().mockName(event.name); // event.listener = mockFn; // if (event.isPropertyHandler) { // fakeXhr[`on${event.name}`] = mockFn; // } else { // fakeXhr.addEventListener(event.name, mockFn); // } // }); // fakeXhr.open(options.method, options.url); // fakeXhr.timeout = options.timeout; // fakeXhr.withCredentials = options.withCredentials; // if (options.headers) { // Object.entries(options.headers).forEach(([header, value]) => // fakeXhr.setRequestHeader(header, value) // ); // } // fakeXhr.send(JSON.stringify(options.body)); // await fakeXhrFinished(); // return { // fakeXhr, // realXHR, // setHeaderSpy, // events: options.events, // dispose() { // global.realXMLHttpRequest = originalXHR; // }, // }; // } // function assertEventListeners(realXHR, events) { // events.forEach((event) => { // if (event.isPropertyHandler) { // const eventName = `on${event.name}`; // if (!event.shouldTransfer) { // expect(realXHR[eventName]).toBeFalsy(); // } else { // expect(realXHR[eventName]).toBe(event.listener); // } // } // if (event.shouldBeCalledTimes === -1) { // expect(event.listener).toHaveBeenCalled(); // } else { // expect(event.listener).toHaveBeenCalledTimes( // event.shouldBeCalledTimes // ); // } // }); // } describe('Faker - getKey', function () { var _setupMockFaker = setupMockFaker(), _setupMockFaker2 = _slicedToArray(_setupMockFaker, 2), faker = _setupMockFaker2[0], resetMock = _setupMockFaker2[1]; afterAll(function () { resetMock(); }); it('should return empty string if url and method are empty strings', function () { var actual = faker.getKey('', [], ''); expect(actual).toEqual(''); }); it('should return a string binding url and method with underscore if searchParamKeys is empty', function () { var actual = faker.getKey('google.com', [], 'GET'); expect(actual).toEqual('google.com_get'); }); it('should return a string binding url, search params keys, and method with underscore', function () { var actual = faker.getKey('google.com', ['all', 'only'], 'GET'); expect(actual).toEqual('google.com_all_only_get'); }); }); describe('Faker - makeInitialRequestMap', function () { var _setupMockFaker3 = setupMockFaker(), _setupMockFaker4 = _slicedToArray(_setupMockFaker3, 2), faker = _setupMockFaker4[0], resetMock = _setupMockFaker4[1]; afterAll(function () { resetMock(); }); it('should not call add method if request is empty', function () { var addSpy = jest.spyOn(faker, 'add'); faker.makeInitialRequestMap(); expect(addSpy).toHaveBeenCalledTimes(0); }); it('should not call add method if request is not an array', function () { var addSpy = jest.spyOn(faker, 'add'); faker.makeInitialRequestMap({}); expect(addSpy).toHaveBeenCalledTimes(0); }); it('should call add method if request is an array', function () { var addSpy = jest.spyOn(faker, 'add'); var requests = [{ url: 'http://request.com', method: 'GET', status: 200, response: {}, delay: 0 }, { url: 'http://request1.com/1', method: 'PUT', status: 201, response: {}, delay: 0 }]; faker.makeInitialRequestMap(requests); expect(addSpy).toHaveBeenCalledTimes(2); }); }); describe('Faker - matchMock', function () { var requests = [{ url: 'http://request.com', method: 'GET', status: 200, response: {}, delay: 0 }, { url: 'http://request1.com/1', method: 'PUT', status: 201, response: {}, delay: 0 }, { url: 'http://request2.com/:id', method: 'POST', status: 404, response: {}, delay: 0 }, { url: 'http://request3.com?foo=1&bar=2', method: 'GET', status: 200, response: {}, delay: 0 }, { url: 'http://request4.com', method: 'GET', status: 200, response: {}, delay: 0, ignoreQueryParams: true }, { url: 'http://request5.com?foo=1&bar=2', method: 'GET', status: 200, response: {}, delay: 0, ignoreQueryParams: true }]; var _setupMockFaker5 = setupMockFaker(), _setupMockFaker6 = _slicedToArray(_setupMockFaker5, 2), faker = _setupMockFaker6[0], resetMock = _setupMockFaker6[1]; beforeEach(function () { faker.makeInitialRequestMap(requests); }); afterEach(function () { resetMock(); }); it('should return request if url matches', function () { var actual = faker.matchMock('http://request.com', 'GET'); expect(actual.url).toEqual(requests[0].url); expect(actual.method).toEqual(requests[0].method); expect(actual.skip).toEqual(false); }); it('should return request if url matches but method only b/c GET=get', function () { var actual = faker.matchMock('http://request.com', 'get'); expect(actual.url).toEqual(requests[0].url); expect(actual.method).toEqual(requests[0].method); expect(actual.skip).toEqual(false); }); it('should return null if url does not match', function () { var actual = faker.matchMock('http://notmatched.com', 'GET'); expect(actual).toBeNull(); }); it('should return request if url matches with the regex', function () { var actual = faker.matchMock('http://request2.com/3', 'POST'); expect(actual.url).toEqual(requests[2].url); expect(actual.method).toEqual(requests[2].method); expect(actual.skip).toEqual(false); }); it('should return request if url and query parameters match', function () { var actual = faker.matchMock('http://request3.com?foo=1&bar=2', 'GET'); expect(actual.url).toEqual(requests[3].url); expect(actual.method).toEqual(requests[3].method); expect(actual.skip).toEqual(false); }); it('should return request if url and query parameters match with different order', function () { var actual = faker.matchMock('http://request3.com?bar=2&foo=1', 'GET'); expect(actual.url).toEqual(requests[3].url); expect(actual.method).toEqual(requests[3].method); expect(actual.skip).toEqual(false); }); it('should return null if unexpected query parameters are provided', function () { var actual = faker.matchMock('http://request.com?foo=1', 'GET'); expect(actual).toBeNull(); }); it('should return null if query parameters are missing', function () { var actual = faker.matchMock('http://request3.com?baz=1', 'GET'); expect(actual).toBeNull(); }); it('should return request if unexpected query parameters are provided but are globally ignored', function () { faker.setIgnoreQueryParams(true); var actual = faker.matchMock('http://request.com?foo=1', 'GET'); expect(actual.url).toEqual(requests[0].url); expect(actual.method).toEqual(requests[0].method); expect(actual.skip).toEqual(false); }); it('should return request if query parameters are missing but are globally ignored', function () { faker.setIgnoreQueryParams(true); var actual = faker.matchMock('http://request3.com?baz=1', 'GET'); expect(actual.url).toEqual(requests[3].url); expect(actual.method).toEqual(requests[3].method); expect(actual.skip).toEqual(false); }); }); describe('Faker - matchQueryParams', function () { var _setupMockFaker7 = setupMockFaker(), _setupMockFaker8 = _slicedToArray(_setupMockFaker7, 2), faker = _setupMockFaker8[0], resetMock = _setupMockFaker8[1]; afterEach(function () { resetMock(); }); it('should return true if query parameters match', function () { var actual = faker.matchQueryParams(['foo', 'bar'], ['foo', 'bar'], false); expect(actual).toBe(true); }); it('should return true if query parameters match with different order', function () { var actual = faker.matchQueryParams(['foo', 'bar'], ['bar', 'foo'], false); expect(actual).toBe(true); }); it('should return false if unexpected query parameters are provided', function () { var actual = faker.matchQueryParams([], ['foo'], false); expect(actual).toBe(false); }); it('should return false if query parameters are missing', function () { var actual = faker.matchQueryParams(['foo', 'bar'], ['baz'], false); expect(actual).toBe(false); }); it('should return true if unexpected query parameters are provided but are globally ignored', function () { faker.setIgnoreQueryParams(true); var actual = faker.matchQueryParams([], ['foo'], false); expect(actual).toBe(true); }); it('should return true if query parameters are missing but are globally ignored', function () { faker.setIgnoreQueryParams(true); var actual = faker.matchQueryParams([], ['foo'], false); expect(actual).toBe(true); }); }); describe('restore', function () { var requests = [{ url: 'http://request.com', method: 'GET', status: 200, response: {} }, { url: 'http://request1.com/1', method: 'PUT', status: 201, response: {} }, { url: 'http://request2.com/:id', method: 'POST', status: 404, response: {} }]; var _setupMockFaker9 = setupMockFaker(), _setupMockFaker10 = _slicedToArray(_setupMockFaker9, 2), faker = _setupMockFaker10[0], resetMock = _setupMockFaker10[1]; afterAll(function () { resetMock(); }); it('should clear the request map', function () { faker.makeInitialRequestMap(requests); expect(faker.getRequests().length).toEqual(3); faker.restore(); expect(faker.getRequests().length).toEqual(0); }); }); describe('Faker - abort signal', function () { var _setupMockFaker11 = setupMockFaker(), _setupMockFaker12 = _slicedToArray(_setupMockFaker11, 2), faker = _setupMockFaker12[0], resetMock = _setupMockFaker12[1]; beforeAll(function () { var requests = [{ url: 'http://request.com', method: 'GET', status: 200, response: {} }]; faker.makeInitialRequestMap(requests); }); afterAll(function () { resetMock(); }); it('should abort request if abort is called', function (done) { var abortController = new AbortController(); fetch('http://request.com', { method: 'GET', signal: abortController.signal }).then(function () { done('should have aborted, preventing resolve from being called'); })["catch"](function (err) { expect(err.name).toEqual('AbortError'); expect(err.message).toEqual('The reason for aborting'); done(); }); abortController.abort('The reason for aborting'); }); it('should not abort request if aborted signal is not supplied as fetch option', function (done) { var abortController = new AbortController(); fetch('http://request.com', { method: 'GET', delay: 1000 // <- NOTE signal is not provided }).then(function (res) { expect(res.status).toEqual(200); done(); })["catch"](function () { done.fail('should not catch'); }); abortController.abort('The reason for aborting'); }); }); // describe('Faker - real XHR behaviour', () => { // const requests = [ // { // url: 'http://request.com', // method: 'GET', // status: 200, // response: {}, // }, // ]; // it('should reflect with 200', async () => { // // Data // const response = { data: 'mock data' }; // const responseJSON = JSON.stringify(response); // const options = { // method: 'GET', // url: 'http://foo.bar', // timeout: 2000, // withCredentials: true, // events: [ // { // name: 'abort', // isPropertyHandler: true, // shouldBeCalledTimes: 0, // shouldTransfer: true, // }, // { // name: 'error', // isPropertyHandler: true, // shouldBeCalledTimes: 0, // shouldTransfer: true, // }, // { // name: 'load', // isPropertyHandler: true, // shouldBeCalledTimes: 1, // shouldTransfer: true, // }, // { // name: 'loadend', // isPropertyHandler: true, // shouldBeCalledTimes: 1, // shouldTransfer: true, // }, // { // name: 'loadstart', // isPropertyHandler: true, // shouldBeCalledTimes: 1, // shouldTransfer: false, // }, // { // name: 'progress', // isPropertyHandler: true, // shouldBeCalledTimes: -1, // shouldTransfer: true, // }, // { // name: 'readystatechange', // isPropertyHandler: true, // shouldBeCalledTimes: 4, // shouldTransfer: true, // }, // { // name: 'timeout', // isPropertyHandler: true, // shouldBeCalledTimes: 0, // shouldTransfer: true, // }, // { // name: 'readystatechange', // isPropertyHandler: false, // shouldBeCalledTimes: 4, // shouldTransfer: true, // }, // ], // headers: { // foo: 'bar', // }, // }; // // Setup // const { dispose } = setupMocks(requests, (request) => { // request.respond( // 200, // { 'Content-Type': 'application/json' }, // responseJSON // ); // }); // const { // fakeXhr, // realXHR, // setHeaderSpy, // events, // dispose: disposeFake, // } = await getEntangledFakeAndRealXHRs(options); // // Assert // expect(realXHR.timeout).toEqual(2000); // expect(realXHR.withCredentials).toEqual(true); // assertEventListeners(realXHR, events); // expect(setHeaderSpy).toHaveBeenCalledWith('foo', 'bar'); // expect(fakeXhr.status).toEqual(200); // expect(fakeXhr.responseText).toEqual(responseJSON); // expect(fakeXhr.getResponseHeader('Content-Type')).toEqual( // 'application/json' // ); // expect(fakeXhr.statusText).toEqual('OK'); // expect(fakeXhr.readyState).toEqual(fakeXhr.DONE); // expect( // events.find( // (e) => // e.isPropertyHandler === false && // e.name === 'readystatechange' // ).listener // ).toHaveBeenCalledTimes(4); // // Teardown // dispose(); // disposeFake(); // }); // it('should reflect with 202', async () => { // // Data // const response = { response: 'ok' }; // const responseJSON = JSON.stringify(response); // const options = { // method: 'POST', // url: 'http://foo.com/api/user/1', // body: { // name: 'yossi', // age: '30', // }, // timeout: 100, // withCredentials: false, // events: [ // { // name: 'load', // isPropertyHandler: true, // shouldBeCalledTimes: 1, // shouldTransfer: true, // }, // { // name: 'readystatechange', // isPropertyHandler: false, // shouldBeCalledTimes: 4, // shouldTransfer: true, // }, // ], // headers: { // foo: 'bar', // }, // }; // // Setup // const { dispose } = setupMocks(requests, (request) => { // request.respond( // 202, // { 'Content-Type': 'application/json' }, // responseJSON // ); // }); // const { // fakeXhr, // realXHR, // setHeaderSpy, // events, // dispose: disposeFake, // } = await getEntangledFakeAndRealXHRs(options); // // Assert // expect(realXHR.timeout).toEqual(100); // expect(realXHR.withCredentials).toEqual(false); // assertEventListeners(realXHR, events); // expect(setHeaderSpy).toHaveBeenCalledWith('foo', 'bar'); // expect(fakeXhr.status).toEqual(202); // expect(fakeXhr.responseText).toEqual(responseJSON); // expect(fakeXhr.getResponseHeader('Content-Type')).toEqual( // 'application/json' // ); // expect(fakeXhr.statusText).toEqual('Accepted'); // expect(fakeXhr.readyState).toEqual(fakeXhr.DONE); // expect( // events.find( // (e) => // e.isPropertyHandler === false && // e.name === 'readystatechange' // ).listener // ).toHaveBeenCalledTimes(4); // // Teardown // dispose(); // disposeFake(); // }); // it('should reflect with 301', async () => { // // Data // const options = { // method: 'GET', // url: 'http://foo.com/', // timeout: 100, // withCredentials: true, // events: [ // { // name: 'readystatechange', // isPropertyHandler: false, // shouldBeCalledTimes: 4, // shouldTransfer: true, // }, // ], // headers: { // foo: 'bar', // }, // }; // // Setup // const { dispose } = setupMocks(requests, (request) => { // request.respond(301, { Location: 'http://bar.com' }, ''); // }); // const { // fakeXhr, // realXHR, // setHeaderSpy, // events, // dispose: disposeFake, // } = await getEntangledFakeAndRealXHRs(options); // // Assert // expect(realXHR.timeout).toEqual(100); // expect(realXHR.withCredentials).toEqual(true); // assertEventListeners(realXHR, events); // expect(setHeaderSpy).toHaveBeenCalledWith('foo', 'bar'); // expect(fakeXhr.status).toEqual(301); // expect(fakeXhr.responseText).toEqual(''); // expect(fakeXhr.getResponseHeader('Location')).toEqual('http://bar.com'); // expect(fakeXhr.statusText).toEqual('Moved Permanently'); // expect(fakeXhr.readyState).toEqual(fakeXhr.DONE); // expect( // events.find( // (e) => // e.isPropertyHandler === false && // e.name === 'readystatechange' // ).listener // ).toHaveBeenCalledTimes(4); // // Teardown // dispose(); // disposeFake(); // }); // it('should reflect with 404', async () => { // // Data // const options = { // method: 'GET', // url: 'http://foo.com/', // timeout: 100, // withCredentials: true, // }; // // Setup // const { dispose } = setupMocks(requests, (request) => { // request.respond(404, {}, ''); // }); // const { // fakeXhr, // realXHR, // dispose: disposeFake, // } = await getEntangledFakeAndRealXHRs(options); // // Assert // expect(realXHR.timeout).toEqual(100); // expect(realXHR.withCredentials).toEqual(true); // expect(fakeXhr.status).toEqual(404); // expect(fakeXhr.responseText).toEqual(''); // expect(fakeXhr.statusText).toEqual('Not Found'); // expect(fakeXhr.readyState).toEqual(fakeXhr.DONE); // // Teardown // dispose(); // disposeFake(); // }); // it('should reflect with 500', async () => { // // Data // const options = { // method: 'GET', // url: 'http://foo.com/', // timeout: 100, // withCredentials: true, // }; // // Setup // const { dispose } = setupMocks(requests, (request) => { // request.respond(500, {}, ''); // }); // const { // fakeXhr, // realXHR, // dispose: disposeFake, // } = await getEntangledFakeAndRealXHRs(options); // // Assert // expect(realXHR.timeout).toEqual(100); // expect(realXHR.withCredentials).toEqual(true); // expect(fakeXhr.status).toEqual(500); // expect(fakeXhr.responseText).toEqual(''); // expect(fakeXhr.statusText).toEqual('Internal Server Error'); // expect(fakeXhr.readyState).toEqual(fakeXhr.DONE); // // Teardown // dispose(); // disposeFake(); // }); // });