savedSearchesStore.spec.jsx 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. import SavedSearchesStore from 'app/stores/savedSearchesStore';
  2. import {
  3. fetchSavedSearches,
  4. deleteSavedSearch,
  5. pinSearch,
  6. unpinSearch,
  7. } from 'app/actionCreators/savedSearches';
  8. import {Client} from 'app/api';
  9. describe('SavedSearchesStore', function() {
  10. let api;
  11. beforeAll(async function() {
  12. api = new Client();
  13. await SavedSearchesStore.reset();
  14. });
  15. beforeEach(function() {
  16. Client.addMockResponse({
  17. url: '/organizations/org-1/searches/',
  18. body: TestStubs.Searches(),
  19. });
  20. Client.addMockResponse({
  21. url: '/organizations/org-1/pinned-searches/',
  22. method: 'PUT',
  23. body: {},
  24. });
  25. Client.addMockResponse({
  26. url: '/organizations/org-1/pinned-searches/',
  27. method: 'DELETE',
  28. });
  29. });
  30. afterEach(async function() {
  31. Client.clearMockResponses();
  32. SavedSearchesStore.reset();
  33. await tick();
  34. });
  35. it('get', function() {
  36. expect(SavedSearchesStore.get()).toEqual({
  37. hasError: false,
  38. isLoading: true,
  39. savedSearches: [],
  40. });
  41. });
  42. it('fetching saved searches updates store', async function() {
  43. await fetchSavedSearches(api, 'org-1', {});
  44. await tick();
  45. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  46. expect(SavedSearchesStore.get().isLoading).toBe(false);
  47. });
  48. it('creates a new pin search', async function() {
  49. await fetchSavedSearches(api, 'org-1', {});
  50. await tick();
  51. Client.addMockResponse({
  52. url: '/organizations/org-1/pinned-searches/',
  53. method: 'PUT',
  54. body: {
  55. id: '123',
  56. query: 'level:info',
  57. isPinned: true,
  58. },
  59. });
  60. pinSearch(api, 'org-1', 0, 'level:info');
  61. await tick();
  62. await tick();
  63. expect(SavedSearchesStore.get().savedSearches).toHaveLength(3);
  64. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  65. expect.objectContaining({
  66. id: '123',
  67. isPinned: true,
  68. type: 0,
  69. query: 'level:info',
  70. name: 'My Pinned Search',
  71. })
  72. );
  73. });
  74. it('changes pinned search from a custom search to an existing search', async function() {
  75. const searches = TestStubs.Searches();
  76. Client.addMockResponse({
  77. url: '/organizations/org-1/searches/',
  78. body: [
  79. {
  80. id: null,
  81. isPinned: true,
  82. type: 0,
  83. query: 'assigned:me',
  84. },
  85. ...searches,
  86. ],
  87. });
  88. Client.addMockResponse({
  89. url: '/organizations/org-1/pinned-searches/',
  90. method: 'PUT',
  91. body: {
  92. id: '1',
  93. isDefault: false,
  94. isGlobal: true,
  95. isOrgCustom: false,
  96. isPinned: true,
  97. query: 'is:unresolved',
  98. name: 'Unresolved Issues',
  99. type: 0,
  100. },
  101. });
  102. await fetchSavedSearches(api, 'org-1', {});
  103. await tick();
  104. pinSearch(api, 'org-1', 0, searches[1].query);
  105. await tick();
  106. await tick();
  107. // Order should remain the same
  108. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  109. expect.objectContaining({
  110. id: '1',
  111. isDefault: false,
  112. isGlobal: true,
  113. isOrgCustom: false,
  114. isPinned: true,
  115. type: 0,
  116. name: 'Unresolved Issues',
  117. query: 'is:unresolved',
  118. })
  119. );
  120. // Saved custom search should be removed
  121. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  122. });
  123. it('changes pinned search from an existing search to another existing search', async function() {
  124. const searches = TestStubs.Searches();
  125. Client.addMockResponse({
  126. url: '/organizations/org-1/searches/',
  127. body: [{...searches[0], isPinned: true}, searches[1]],
  128. });
  129. Client.addMockResponse({
  130. url: '/organizations/org-1/pinned-searches/',
  131. method: 'PUT',
  132. body: {
  133. id: '1',
  134. isDefault: false,
  135. isGlobal: true,
  136. isOrgCustom: false,
  137. isPinned: true,
  138. query: 'is:unresolved',
  139. name: 'Unresolved Issues',
  140. type: 0,
  141. },
  142. });
  143. await fetchSavedSearches(api, 'org-1', {});
  144. await tick();
  145. pinSearch(api, 'org-1', 0, searches[1].query);
  146. await tick();
  147. await tick();
  148. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  149. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  150. expect.objectContaining({
  151. id: '2',
  152. isPinned: false,
  153. type: 0,
  154. name: 'Needs Triage',
  155. query: 'is:unresolved is:unassigned',
  156. })
  157. );
  158. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  159. expect.objectContaining({
  160. id: '1',
  161. isDefault: false,
  162. isGlobal: true,
  163. isOrgCustom: false,
  164. isPinned: true,
  165. type: 0,
  166. name: 'Unresolved Issues',
  167. query: 'is:unresolved',
  168. })
  169. );
  170. });
  171. it('unpins a user custom search (not global, and not org custom)', async function() {
  172. const searches = TestStubs.Searches();
  173. Client.addMockResponse({
  174. url: '/organizations/org-1/searches/',
  175. body: [
  176. {
  177. id: null,
  178. isPinned: true,
  179. type: 0,
  180. query: 'assigned:me',
  181. },
  182. ...searches,
  183. ],
  184. });
  185. await fetchSavedSearches(api, 'org-1', {});
  186. await tick();
  187. unpinSearch(api, 'org-1', 0, searches[0]);
  188. await tick();
  189. await tick();
  190. // Saved custom search should be removed
  191. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  192. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  193. expect.objectContaining({
  194. id: '2',
  195. isPinned: false,
  196. type: 0,
  197. name: 'Needs Triage',
  198. query: 'is:unresolved is:unassigned',
  199. })
  200. );
  201. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  202. expect.objectContaining({
  203. id: '1',
  204. isPinned: false,
  205. type: 0,
  206. name: 'Unresolved Issues',
  207. query: 'is:unresolved',
  208. })
  209. );
  210. });
  211. it('unpins an existing global saved search', async function() {
  212. const searches = TestStubs.Searches();
  213. Client.addMockResponse({
  214. url: '/organizations/org-1/searches/',
  215. body: [{...searches[0], isPinned: true}, searches[1]],
  216. });
  217. await fetchSavedSearches(api, 'org-1', {});
  218. await tick();
  219. unpinSearch(api, 'org-1', 0, searches[0]);
  220. await tick();
  221. await tick();
  222. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  223. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  224. expect.objectContaining({
  225. id: '2',
  226. isPinned: false,
  227. type: 0,
  228. name: 'Needs Triage',
  229. query: 'is:unresolved is:unassigned',
  230. })
  231. );
  232. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  233. expect.objectContaining({
  234. id: '1',
  235. isPinned: false,
  236. type: 0,
  237. name: 'Unresolved Issues',
  238. query: 'is:unresolved',
  239. })
  240. );
  241. });
  242. it('unpins an existing org saved search', async function() {
  243. const searches = TestStubs.Searches();
  244. Client.addMockResponse({
  245. url: '/organizations/org-1/searches/',
  246. body: [
  247. {...searches[0], isOrgCustom: true, isGlobal: false, isPinned: true},
  248. searches[1],
  249. ],
  250. });
  251. await fetchSavedSearches(api, 'org-1', {});
  252. await tick();
  253. unpinSearch(api, 'org-1', 0, searches[0]);
  254. await tick();
  255. await tick();
  256. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  257. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  258. expect.objectContaining({
  259. id: '2',
  260. isPinned: false,
  261. type: 0,
  262. name: 'Needs Triage',
  263. query: 'is:unresolved is:unassigned',
  264. })
  265. );
  266. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  267. expect.objectContaining({
  268. id: '1',
  269. isPinned: false,
  270. type: 0,
  271. name: 'Unresolved Issues',
  272. query: 'is:unresolved',
  273. })
  274. );
  275. });
  276. it('removes deleted saved searches', async function() {
  277. await fetchSavedSearches(api, 'org-1', {});
  278. await tick();
  279. const searches = SavedSearchesStore.get().savedSearches;
  280. Client.addMockResponse({
  281. url: `/organizations/org-1/searches/${searches[0].id}/`,
  282. method: 'DELETE',
  283. body: {},
  284. });
  285. await deleteSavedSearch(api, 'org-1', searches[0]);
  286. await tick();
  287. const newSearches = SavedSearchesStore.get().savedSearches;
  288. expect(newSearches.length).toBeLessThan(searches.length);
  289. expect(newSearches[0].id).not.toBe(searches[0].id);
  290. });
  291. });