import GroupStore from 'sentry/stores/groupStore'; import SelectedGroupStore from 'sentry/stores/selectedGroupStore'; function setRecords(records: Record) { SelectedGroupStore.onGroupChange(new Set(Object.keys(records))); for (const [key, isSelected] of Object.entries(records)) { if (isSelected) { SelectedGroupStore.toggleSelect(key); } } } describe('SelectedGroupStore', function () { let trigger: jest.SpyInstance; beforeEach(function () { SelectedGroupStore.init(); trigger = jest.spyOn(SelectedGroupStore, 'trigger').mockImplementation(() => {}); }); afterEach(function () { trigger.mockRestore(); }); describe('prune()', function () { it('removes records no longer in the GroupStore', function () { jest.spyOn(GroupStore, 'getAllItemIds').mockImplementation(() => ['3']); setRecords({1: true, 2: true, 3: true}); SelectedGroupStore.prune(); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([['3', true]]); }); it("doesn't have any effect when already in sync", function () { jest.spyOn(GroupStore, 'getAllItemIds').mockImplementation(() => ['1', '2', '3']); setRecords({1: true, 2: true, 3: true}); SelectedGroupStore.prune(); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['1', true], ['2', true], ['3', true], ]); }); }); describe('add()', function () { it("defaults value of new ids to 'allSelected()'", function () { setRecords({1: true}); SelectedGroupStore.add(['2']); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['1', true], ['2', true], ]); }); it('does not update existing ids', function () { setRecords({1: false, 2: true}); SelectedGroupStore.add(['3']); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['1', false], ['2', true], ['3', false], ]); }); }); describe('onGroupChange()', function () { let prune: jest.SpyInstance; let add: jest.SpyInstance; beforeEach(function () { prune = jest.spyOn(SelectedGroupStore, 'prune'); add = jest.spyOn(SelectedGroupStore, 'add'); }); afterEach(function () {}); it('adds new ids', function () { SelectedGroupStore.onGroupChange(new Set()); expect(add).toHaveBeenCalled(); }); it('prunes stale records', function () { SelectedGroupStore.onGroupChange(new Set()); expect(prune).toHaveBeenCalled(); }); it('triggers an update', function () { SelectedGroupStore.onGroupChange(new Set()); expect(trigger).toHaveBeenCalled(); }); }); describe('allSelected()', function () { it('returns true when all ids are selected', function () { setRecords({1: true, 2: true}); expect(SelectedGroupStore.allSelected()).toBe(true); }); it('returns false when some ids are selected', function () { setRecords({1: true, 2: false}); expect(SelectedGroupStore.allSelected()).toBe(false); }); it('returns false when no ids are selected', function () { setRecords({1: false, 2: false}); expect(SelectedGroupStore.allSelected()).toBe(false); }); it('returns false when there are no ids', function () { expect(SelectedGroupStore.allSelected()).toBe(false); }); }); describe('anySelected()', function () { it('returns true if any ids are selected', function () { setRecords({1: true, 2: false}); expect(SelectedGroupStore.anySelected()).toBe(true); }); it('returns false when no ids are selected', function () { setRecords({1: false, 2: false}); expect(SelectedGroupStore.anySelected()).toBe(false); }); }); describe('multiSelected()', function () { it('returns true when multiple ids are selected', function () { setRecords({1: true, 2: true, 3: false}); expect(SelectedGroupStore.multiSelected()).toBe(true); }); it('returns false when a single id is selected', function () { setRecords({1: true, 2: false}); expect(SelectedGroupStore.multiSelected()).toBe(false); }); it('returns false when no ids are selected', function () { setRecords({1: false, 2: false}); expect(SelectedGroupStore.multiSelected()).toBe(false); }); }); describe('getSelectedIds()', function () { it('returns selected ids', function () { setRecords({1: true, 2: false, 3: true}); const ids = SelectedGroupStore.getSelectedIds(); expect(ids.has('1')).toBe(true); expect(ids.has('3')).toBe(true); expect(ids.size).toEqual(2); }); it('returns empty set with no selected ids', function () { setRecords({1: false}); const ids = SelectedGroupStore.getSelectedIds(); expect(ids.has('1')).toBe(false); expect(ids.size).toEqual(0); }); }); describe('isSelected()', function () { it('returns true if id is selected', function () { setRecords({1: true}); expect(SelectedGroupStore.isSelected('1')).toBe(true); }); it('returns false if id is unselected or unknown', function () { setRecords({1: false}); expect(SelectedGroupStore.isSelected('1')).toBe(false); expect(SelectedGroupStore.isSelected('2')).toBe(false); expect(SelectedGroupStore.isSelected('')).toBe(false); }); }); describe('deselectAll()', function () { it('sets all records to false', function () { setRecords({1: true, 2: true, 3: false}); SelectedGroupStore.deselectAll(); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['1', false], ['2', false], ['3', false], ]); }); it('triggers an update', function () { SelectedGroupStore.deselectAll(); expect(trigger).toHaveBeenCalled(); }); }); describe('toggleSelect()', function () { it('toggles state given pre-existing id', function () { setRecords({1: true}); SelectedGroupStore.toggleSelect('1'); expect(SelectedGroupStore.getState().records.get('1')).toBe(false); }); it('does not toggle state given unknown id', function () { SelectedGroupStore.toggleSelect('1'); SelectedGroupStore.toggleSelect(''); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([]); }); it('triggers an update given pre-existing id', function () { setRecords({1: true}); SelectedGroupStore.toggleSelect('1'); expect(trigger).toHaveBeenCalled(); }); it('does not trigger an update given unknown id', function () { SelectedGroupStore.toggleSelect(''); expect(trigger).not.toHaveBeenCalled(); }); }); describe('toggleSelectAll()', function () { it('selects all ids if any are unselected', function () { setRecords({1: true, 2: false}); SelectedGroupStore.toggleSelectAll(); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['1', true], ['2', true], ]); }); it('unselects all ids if all are selected', function () { setRecords({1: true, 2: true}); SelectedGroupStore.toggleSelectAll(); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['1', false], ['2', false], ]); }); it('triggers an update', function () { SelectedGroupStore.toggleSelectAll(); expect(trigger).toHaveBeenCalled(); }); }); describe('shiftSelectItems()', function () { it('toggles all between last selected and new selection', function () { const ids = ['11', '12', '13', '14', '15']; jest.spyOn(GroupStore, 'getAllItemIds').mockImplementation(() => ids); SelectedGroupStore.add(ids); SelectedGroupStore.toggleSelect('12'); SelectedGroupStore.shiftToggleItems('14'); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['11', false], ['12', true], ['13', true], ['14', true], ['15', false], ]); }); it('toggles all between last selected and new selection backwards', function () { const ids = ['11', '12', '13', '14', '15']; jest.spyOn(GroupStore, 'getAllItemIds').mockImplementation(() => ids); SelectedGroupStore.add(ids); SelectedGroupStore.toggleSelect('14'); SelectedGroupStore.shiftToggleItems('12'); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['11', false], ['12', true], ['13', true], ['14', true], ['15', false], ]); }); it('deslects after selecting', function () { const ids = ['11', '12', '13', '14', '15']; jest.spyOn(GroupStore, 'getAllItemIds').mockImplementation(() => ids); SelectedGroupStore.add(ids); SelectedGroupStore.toggleSelect('11'); // Select everything SelectedGroupStore.shiftToggleItems('15'); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['11', true], ['12', true], ['13', true], ['14', true], ['15', true], ]); // Deslect between 14 and 12 SelectedGroupStore.toggleSelect('14'); SelectedGroupStore.shiftToggleItems('12'); expect([...SelectedGroupStore.getState().records.entries()]).toEqual([ ['11', true], ['12', false], ['13', false], ['14', false], ['15', true], ]); }); }); it('returns a stable reference from getState', function () { setRecords({1: true, 2: true}); const state = SelectedGroupStore.getState(); expect(Object.is(state, SelectedGroupStore.getState())).toBe(true); }); });