groupStore.spec.tsx 8.0 KB

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