groupStore.spec.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import GroupStore from 'sentry/stores/groupStore';
  2. import {Group, GroupStats, TimeseriesValue} from 'sentry/types';
  3. const MOCK_PROJECT = TestStubs.Project();
  4. const g = (id: string, params?: Partial<Group>): Group => {
  5. return TestStubs.Group({id, project: MOCK_PROJECT, ...params});
  6. };
  7. describe('GroupStore', function () {
  8. beforeEach(function () {
  9. GroupStore.reset();
  10. });
  11. describe('add()', function () {
  12. it('should add new entries', function () {
  13. GroupStore.items = [];
  14. GroupStore.add([g('1'), g('2')]);
  15. expect(GroupStore.items).toEqual([g('1'), g('2')]);
  16. });
  17. it('should update matching existing entries', function () {
  18. GroupStore.items = [g('1'), g('2')];
  19. GroupStore.add([g('1', {count: '1337'}), g('3')]);
  20. expect(GroupStore.getAllItemIds()).toEqual(['1', '2', '3']);
  21. expect(GroupStore.items[0]).toEqual(
  22. expect.objectContaining({id: '1', count: '1337'})
  23. );
  24. });
  25. it('should attempt to preserve order of ids', function () {
  26. GroupStore.add([g('2'), g('1'), g('3')]);
  27. expect(GroupStore.getAllItemIds()).toEqual(['2', '1', '3']);
  28. });
  29. });
  30. describe('addToFront()', function () {
  31. it('should add new entries to beginning of the list', function () {
  32. GroupStore.items = [g('2')];
  33. GroupStore.addToFront([g('1'), g('3')]);
  34. expect(GroupStore.items).toEqual([g('1'), g('3'), g('2')]);
  35. });
  36. it('should update matching existing entries', function () {
  37. GroupStore.items = [g('1'), g('2')];
  38. GroupStore.addToFront([g('1', {count: '1337'}), g('3')]);
  39. expect(GroupStore.getAllItems()).toEqual([
  40. expect.objectContaining({id: '1', count: '1337'}),
  41. g('3'),
  42. g('2'),
  43. ]);
  44. });
  45. it('should attempt to preserve order of ids', function () {
  46. GroupStore.addToFront([g('2'), g('1'), g('3')]);
  47. expect(GroupStore.getAllItemIds()).toEqual(['2', '1', '3']);
  48. });
  49. });
  50. describe('remove()', function () {
  51. it('should remove entry', function () {
  52. GroupStore.items = [g('1'), g('2')];
  53. GroupStore.remove(['1']);
  54. expect(GroupStore.items).toEqual([g('2')]);
  55. });
  56. it('should remove multiple entries', function () {
  57. GroupStore.items = [g('1'), g('2'), g('3')];
  58. GroupStore.remove(['1', '2']);
  59. expect(GroupStore.items).toEqual([g('3')]);
  60. });
  61. it('should not remove already removed item', function () {
  62. GroupStore.items = [g('1'), g('2')];
  63. GroupStore.remove(['0']);
  64. expect(GroupStore.items).toEqual([g('1'), g('2')]);
  65. });
  66. });
  67. describe('onMergeSuccess()', function () {
  68. it('should remove the non-parent merged ids', function () {
  69. GroupStore.items = [g('1'), g('2'), g('3'), g('4')];
  70. GroupStore.onMergeSuccess(
  71. '',
  72. ['2', '3', '4'], // items merged
  73. {merge: {parent: '3'}} // merge API response
  74. );
  75. expect(GroupStore.items).toEqual([
  76. g('1'),
  77. g('3'), // parent
  78. ]);
  79. });
  80. });
  81. describe('onPopulateStats()', function () {
  82. const stats: Record<string, TimeseriesValue[]> = {auto: [[1611576000, 10]]};
  83. beforeEach(function () {
  84. jest.spyOn(GroupStore, 'trigger');
  85. GroupStore.items = [g('1'), g('2'), g('3')];
  86. });
  87. afterEach(() => {
  88. jest.restoreAllMocks();
  89. });
  90. it('should merge stats into existing groups', function () {
  91. GroupStore.onPopulateStats(
  92. ['1', '2', '3'],
  93. [
  94. {id: '1', stats} as GroupStats,
  95. {id: '2', stats} as GroupStats,
  96. {id: '3', stats} as GroupStats,
  97. ]
  98. );
  99. const group = GroupStore.getAllItems()[0] as Group;
  100. expect(group.stats).toEqual(stats);
  101. expect(GroupStore.trigger).toHaveBeenCalledWith(new Set(['1', '2', '3']));
  102. });
  103. it('should not change current item ids', function () {
  104. GroupStore.onPopulateStats(
  105. ['2', '3'],
  106. [{id: '2', stats} as GroupStats, {id: '3', stats} as GroupStats]
  107. );
  108. const group1 = GroupStore.getAllItems()[0] as Group;
  109. const group2 = GroupStore.getAllItems()[1] as Group;
  110. expect(GroupStore.trigger).toHaveBeenCalledWith(new Set(['2', '3']));
  111. expect(group1.stats).not.toEqual(stats);
  112. expect(group2.stats).toEqual(stats);
  113. });
  114. });
  115. describe('getAllItems()', function () {
  116. it('Merges pending changes into items', function () {
  117. GroupStore.items = [];
  118. GroupStore.add([g('1'), g('2')]);
  119. GroupStore.onUpdate('1337', ['1'], {someChange: true});
  120. expect(GroupStore.get('1')).toEqual(
  121. expect.objectContaining({id: '1', someChange: true})
  122. );
  123. });
  124. });
  125. describe('update methods', function () {
  126. beforeEach(function () {
  127. jest.spyOn(GroupStore, 'trigger');
  128. GroupStore.items = [g('1'), g('2'), g('3')];
  129. });
  130. afterEach(() => {
  131. jest.restoreAllMocks();
  132. });
  133. describe('onUpdate()', function () {
  134. it("should treat undefined itemIds argument as 'all'", function () {
  135. GroupStore.onUpdate('1337', undefined, {});
  136. expect(GroupStore.trigger).toHaveBeenCalledTimes(1);
  137. expect(GroupStore.trigger).toHaveBeenCalledWith(new Set(['1', '2', '3']));
  138. });
  139. it('should apply optimistic updates', function () {
  140. GroupStore.items = [g('1'), g('2')];
  141. GroupStore.add([g('1'), g('2')]);
  142. // Resolve 2 issues
  143. const itemIds = ['1', '2'];
  144. const data = {status: 'resolved', statusDetails: {}};
  145. GroupStore.onUpdate('12345', itemIds, data);
  146. expect(GroupStore.pendingChanges).toEqual(new Map([['12345', {itemIds, data}]]));
  147. expect(GroupStore.get('1')).toEqual({...g('1'), ...data});
  148. expect(GroupStore.get('2')).toEqual({...g('2'), ...data});
  149. });
  150. });
  151. describe('onUpdateSuccess()', function () {
  152. it("should treat undefined itemIds argument as 'all'", function () {
  153. GroupStore.onUpdateSuccess('1337', undefined, {});
  154. expect(GroupStore.trigger).toHaveBeenCalledTimes(1);
  155. expect(GroupStore.trigger).toHaveBeenCalledWith(new Set(['1', '2', '3']));
  156. });
  157. });
  158. describe('onUpdateError()', function () {
  159. it("should treat undefined itemIds argument as 'all'", function () {
  160. GroupStore.onUpdateError('1337', undefined, false);
  161. expect(GroupStore.trigger).toHaveBeenCalledTimes(1);
  162. expect(GroupStore.trigger).toHaveBeenCalledWith(new Set(['1', '2', '3']));
  163. });
  164. });
  165. describe('onDeleteSuccess()', function () {
  166. it("should treat undefined itemIds argument as 'all'", function () {
  167. GroupStore.onDeleteSuccess('1337', undefined, {});
  168. expect(GroupStore.trigger).toHaveBeenCalledTimes(1);
  169. expect(GroupStore.trigger).toHaveBeenCalledWith(new Set(['1', '2', '3']));
  170. });
  171. });
  172. describe('onAssignToSuccess()', function () {
  173. it("should treat undefined itemIds argument as 'all'", function () {
  174. GroupStore.items = [g('1')];
  175. const assignedGroup = g('1', {assignedTo: TestStubs.User({type: 'user'})});
  176. GroupStore.onAssignToSuccess('1337', '1', assignedGroup);
  177. expect(GroupStore.trigger).toHaveBeenCalledTimes(1);
  178. expect(GroupStore.trigger).toHaveBeenCalledWith(new Set(['1']));
  179. expect(GroupStore.items[0]).toEqual(assignedGroup);
  180. });
  181. });
  182. });
  183. });