/* eslint-disable jasmine/no-unsafe-spy */ import Poll from '~/lib/utils/poll'; import { successCodes } from '~/lib/utils/http_status'; const waitForAllCallsToFinish = (service, waitForCount, successCallback) => { const timer = () => { setTimeout(() => { if (service.fetch.calls.count() === waitForCount) { successCallback(); } else { timer(); } }, 0); }; timer(); }; function mockServiceCall(service, response, shouldFail = false) { const action = shouldFail ? Promise.reject : Promise.resolve; const responseObject = response; if (!responseObject.headers) responseObject.headers = {}; service.fetch.and.callFake(action.bind(Promise, responseObject)); } describe('Poll', () => { const service = jasmine.createSpyObj('service', ['fetch']); const callbacks = jasmine.createSpyObj('callbacks', ['success', 'error', 'notification']); function setup() { return new Poll({ resource: service, method: 'fetch', successCallback: callbacks.success, errorCallback: callbacks.error, notificationCallback: callbacks.notification, }).makeRequest(); } afterEach(() => { callbacks.success.calls.reset(); callbacks.error.calls.reset(); callbacks.notification.calls.reset(); service.fetch.calls.reset(); }); it('calls the success callback when no header for interval is provided', done => { mockServiceCall(service, { status: 200 }); setup(); waitForAllCallsToFinish(service, 1, () => { expect(callbacks.success).toHaveBeenCalled(); expect(callbacks.error).not.toHaveBeenCalled(); done(); }); }); it('calls the error callback when the http request returns an error', done => { mockServiceCall(service, { status: 500 }, true); setup(); waitForAllCallsToFinish(service, 1, () => { expect(callbacks.success).not.toHaveBeenCalled(); expect(callbacks.error).toHaveBeenCalled(); done(); }); }); it('skips the error callback when request is aborted', done => { mockServiceCall(service, { status: 0 }, true); setup(); waitForAllCallsToFinish(service, 1, () => { expect(callbacks.success).not.toHaveBeenCalled(); expect(callbacks.error).not.toHaveBeenCalled(); expect(callbacks.notification).toHaveBeenCalled(); done(); }); }); it('should call the success callback when the interval header is -1', done => { mockServiceCall(service, { status: 200, headers: { 'poll-interval': -1 } }); setup() .then(() => { expect(callbacks.success).toHaveBeenCalled(); expect(callbacks.error).not.toHaveBeenCalled(); done(); }) .catch(done.fail); }); describe('for 2xx status code', () => { successCodes.forEach(httpCode => { it(`starts polling when http status is ${httpCode} and interval header is provided`, done => { mockServiceCall(service, { status: httpCode, headers: { 'poll-interval': 1 } }); const Polling = new Poll({ resource: service, method: 'fetch', data: { page: 1 }, successCallback: callbacks.success, errorCallback: callbacks.error, }); Polling.makeRequest(); waitForAllCallsToFinish(service, 2, () => { Polling.stop(); expect(service.fetch.calls.count()).toEqual(2); expect(service.fetch).toHaveBeenCalledWith({ page: 1 }); expect(callbacks.success).toHaveBeenCalled(); expect(callbacks.error).not.toHaveBeenCalled(); done(); }); }); }); }); describe('stop', () => { it('stops polling when method is called', done => { mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } }); const Polling = new Poll({ resource: service, method: 'fetch', data: { page: 1 }, successCallback: () => { Polling.stop(); }, errorCallback: callbacks.error, }); spyOn(Polling, 'stop').and.callThrough(); Polling.makeRequest(); waitForAllCallsToFinish(service, 1, () => { expect(service.fetch.calls.count()).toEqual(1); expect(service.fetch).toHaveBeenCalledWith({ page: 1 }); expect(Polling.stop).toHaveBeenCalled(); done(); }); }); }); describe('restart', () => { it('should restart polling when its called', done => { mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } }); const Polling = new Poll({ resource: service, method: 'fetch', data: { page: 1 }, successCallback: () => { Polling.stop(); setTimeout(() => { Polling.restart({ data: { page: 4 } }); }, 0); }, errorCallback: callbacks.error, }); spyOn(Polling, 'stop').and.callThrough(); spyOn(Polling, 'restart').and.callThrough(); Polling.makeRequest(); waitForAllCallsToFinish(service, 2, () => { Polling.stop(); expect(service.fetch.calls.count()).toEqual(2); expect(service.fetch).toHaveBeenCalledWith({ page: 4 }); expect(Polling.stop).toHaveBeenCalled(); expect(Polling.restart).toHaveBeenCalled(); expect(Polling.options.data).toEqual({ page: 4 }); done(); }); }); }); });