import AjaxCache from '~/lib/utils/ajax_cache'; describe('AjaxCache', () => { const dummyEndpoint = '/AjaxCache/dummyEndpoint'; const dummyResponse = { important: 'dummy data', }; beforeEach(() => { AjaxCache.internalStorage = { }; AjaxCache.pendingRequests = { }; }); describe('get', () => { it('returns undefined if cache is empty', () => { const data = AjaxCache.get(dummyEndpoint); expect(data).toBe(undefined); }); it('returns undefined if cache contains no matching data', () => { AjaxCache.internalStorage['not matching'] = dummyResponse; const data = AjaxCache.get(dummyEndpoint); expect(data).toBe(undefined); }); it('returns matching data', () => { AjaxCache.internalStorage[dummyEndpoint] = dummyResponse; const data = AjaxCache.get(dummyEndpoint); expect(data).toBe(dummyResponse); }); }); describe('hasData', () => { it('returns false if cache is empty', () => { expect(AjaxCache.hasData(dummyEndpoint)).toBe(false); }); it('returns false if cache contains no matching data', () => { AjaxCache.internalStorage['not matching'] = dummyResponse; expect(AjaxCache.hasData(dummyEndpoint)).toBe(false); }); it('returns true if data is available', () => { AjaxCache.internalStorage[dummyEndpoint] = dummyResponse; expect(AjaxCache.hasData(dummyEndpoint)).toBe(true); }); }); describe('remove', () => { it('does nothing if cache is empty', () => { AjaxCache.remove(dummyEndpoint); expect(AjaxCache.internalStorage).toEqual({ }); }); it('does nothing if cache contains no matching data', () => { AjaxCache.internalStorage['not matching'] = dummyResponse; AjaxCache.remove(dummyEndpoint); expect(AjaxCache.internalStorage['not matching']).toBe(dummyResponse); }); it('removes matching data', () => { AjaxCache.internalStorage[dummyEndpoint] = dummyResponse; AjaxCache.remove(dummyEndpoint); expect(AjaxCache.internalStorage).toEqual({ }); }); }); describe('override', () => { it('overrides existing cache', () => { AjaxCache.internalStorage.endpoint = 'existing-endpoint'; AjaxCache.override('endpoint', 'new-endpoint'); expect(AjaxCache.internalStorage.endpoint).toEqual('new-endpoint'); }); }); describe('retrieve', () => { let ajaxSpy; beforeEach(() => { spyOn(jQuery, 'ajax').and.callFake(url => ajaxSpy(url)); }); it('stores and returns data from Ajax call if cache is empty', (done) => { ajaxSpy = (url) => { expect(url).toBe(dummyEndpoint); const deferred = $.Deferred(); deferred.resolve(dummyResponse); return deferred.promise(); }; AjaxCache.retrieve(dummyEndpoint) .then((data) => { expect(data).toBe(dummyResponse); expect(AjaxCache.internalStorage[dummyEndpoint]).toBe(dummyResponse); }) .then(done) .catch(fail); }); it('makes no Ajax call if request is pending', () => { const responseDeferred = $.Deferred(); ajaxSpy = (url) => { expect(url).toBe(dummyEndpoint); // neither reject nor resolve to keep request pending return responseDeferred.promise(); }; const unexpectedResponse = data => fail(`Did not expect response: ${data}`); AjaxCache.retrieve(dummyEndpoint) .then(unexpectedResponse) .catch(fail); AjaxCache.retrieve(dummyEndpoint) .then(unexpectedResponse) .catch(fail); expect($.ajax.calls.count()).toBe(1); }); it('returns undefined if Ajax call fails and cache is empty', (done) => { const dummyStatusText = 'exploded'; const dummyErrorMessage = 'server exploded'; ajaxSpy = (url) => { expect(url).toBe(dummyEndpoint); const deferred = $.Deferred(); deferred.reject(null, dummyStatusText, dummyErrorMessage); return deferred.promise(); }; AjaxCache.retrieve(dummyEndpoint) .then(data => fail(`Received unexpected data: ${JSON.stringify(data)}`)) .catch((error) => { expect(error.message).toBe(`${dummyEndpoint}: ${dummyErrorMessage}`); expect(error.textStatus).toBe(dummyStatusText); done(); }) .catch(fail); }); it('makes no Ajax call if matching data exists', (done) => { AjaxCache.internalStorage[dummyEndpoint] = dummyResponse; ajaxSpy = () => fail(new Error('expected no Ajax call!')); AjaxCache.retrieve(dummyEndpoint) .then((data) => { expect(data).toBe(dummyResponse); }) .then(done) .catch(fail); }); it('makes Ajax call even if matching data exists when forceRequest parameter is provided', (done) => { const oldDummyResponse = { important: 'old dummy data', }; AjaxCache.internalStorage[dummyEndpoint] = oldDummyResponse; ajaxSpy = (url) => { expect(url).toBe(dummyEndpoint); const deferred = $.Deferred(); deferred.resolve(dummyResponse); return deferred.promise(); }; // Call without forceRetrieve param AjaxCache.retrieve(dummyEndpoint) .then((data) => { expect(data).toBe(oldDummyResponse); }) .then(done) .catch(fail); // Call with forceRetrieve param AjaxCache.retrieve(dummyEndpoint, true) .then((data) => { expect(data).toBe(dummyResponse); }) .then(done) .catch(fail); }); }); });