import {createStore} from 'reflux'; import StreamManager from 'sentry/utils/streamManager'; describe('StreamManager', function () { let store; beforeEach(function () { store = createStore({ add() {}, getAllItems() {}, remove() {}, }); }); it('allows options configuration', function () { const options = {limit: 2}; const mgr = new StreamManager(store, options); expect(mgr.limit).toEqual(options.limit); }); describe('push()', function () { it('allows passing no items', function () { const mgr = new StreamManager(store); expect(() => mgr.push()).not.toThrow(); expect(() => mgr.push([])).not.toThrow(); expect(mgr.idList).toHaveLength(0); }); it('adds items', function () { const storeAdd = jest.spyOn(store, 'add'); const mgr = new StreamManager(store); const items = [{id: 1}]; mgr.push(items); expect(mgr.idList).toHaveLength(1); expect(storeAdd).toHaveBeenCalledWith(items); }); it('allows adding a single item', function () { const storeAdd = jest.spyOn(store, 'add'); const mgr = new StreamManager(store); const item = {id: 1}; mgr.push(item); expect(mgr.idList).toHaveLength(1); expect(storeAdd).toHaveBeenCalledWith([item]); }); it('trims after adding', function () { const mgr = new StreamManager(store, {limit: 1}); const storeRemove = jest.spyOn(store, 'remove'); const mgrTrim = jest.spyOn(mgr, 'trim'); mgr.push([{id: 1}, {id: 2}]); expect(mgr.idList).toHaveLength(1); expect(storeRemove).toHaveBeenCalledWith([2]); expect(mgrTrim).toHaveBeenCalled(); }); it('preserves NEW order of duplicates', function () { const mgr = new StreamManager(store); mgr.push([{id: 1}, {id: 3}]); mgr.push([{id: 1}, {id: 2}]); // New order of "1" if after "3" expect(mgr.idList).toEqual([3, 1, 2]); }); }); describe('trim()', function () { it('removes trailing items in excess of the limit', function () { const storeRemove = jest.spyOn(store, 'remove'); const mgr = new StreamManager(store, {limit: 1}); mgr.idList = [1, 2, 3]; mgr.trim(); expect(mgr.idList).toEqual([1]); expect(mgr.idList).toHaveLength(1); expect(storeRemove).toHaveBeenCalledWith([2, 3]); }); it('does nothing with fewer items than limit', function () { const storeRemove = jest.spyOn(store, 'remove'); const mgr = new StreamManager(store, {limit: 10}); mgr.idList = [1, 2, 3]; mgr.trim(); expect(mgr.idList).toEqual([1, 2, 3]); expect(mgr.idList).toHaveLength(3); expect(storeRemove).not.toHaveBeenCalled(); }); }); describe('getAllItems()', function () { it('retrives ordered items from store', function () { const storeGetAllItems = jest .spyOn(store, 'getAllItems') .mockImplementation(() => [{id: 1}, {id: 2}]); const mgr = new StreamManager(store); mgr.push({id: 2}); mgr.push({id: 1}); const items = mgr.getAllItems(); expect(items).toEqual([{id: 2}, {id: 1}]); expect(storeGetAllItems).toHaveBeenCalled(); }); it('does not mutate store', function () { const storeItems = [{id: 1}, {id: 2}]; jest.spyOn(store, 'getAllItems').mockImplementation(() => storeItems); const mgr = new StreamManager(store); mgr.push([{id: 2}, {id: 1}]); mgr.getAllItems(); expect(store.getAllItems()).toEqual([{id: 1}, {id: 2}]); }); }); describe('unshift()', function () { it('adds items to the start of the list', function () { const storeAdd = jest.spyOn(store, 'add'); const mgr = new StreamManager(store); mgr.unshift([{id: 2}]); mgr.unshift([{id: 1}]); expect(mgr.idList).toEqual([1, 2]); expect(storeAdd.mock.calls[0][0]).toEqual([{id: 2}]); expect(storeAdd.mock.calls[1][0]).toEqual([{id: 1}]); }); it('moves duplicates to the start of the list', function () { const mgr = new StreamManager(store); mgr.unshift([{id: 2}, {id: 1}]); mgr.unshift([{id: 1}]); expect(mgr.idList).toEqual([1, 2]); }); it('moves a duplicate array to the start of the list and preserves order', function () { const mgr = new StreamManager(store); mgr.unshift([{id: 3}, {id: 2}, {id: 1}]); mgr.unshift([{id: 2}, {id: 1}]); expect(mgr.idList).toEqual([2, 1, 3]); }); it('allows adding a single item', function () { const mgr = new StreamManager(store); mgr.unshift({id: 1}); expect(mgr.idList).toEqual([1]); }); }); });