savedSearchesStore.spec.jsx 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. import {
  2. deleteSavedSearch,
  3. fetchSavedSearches,
  4. pinSearch,
  5. unpinSearch,
  6. } from 'sentry/actionCreators/savedSearches';
  7. import {Client} from 'sentry/api';
  8. import SavedSearchesStore from 'sentry/stores/savedSearchesStore';
  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('failed fetches do not corrupt store', async function () {
  49. Client.addMockResponse({
  50. url: '/organizations/org-1/searches/',
  51. body: '',
  52. });
  53. await fetchSavedSearches(api, 'org-1', {});
  54. await tick();
  55. expect(SavedSearchesStore.get().savedSearches).toHaveLength(0);
  56. expect(SavedSearchesStore.get().isLoading).toBe(false);
  57. });
  58. it('creates a new pin search', async function () {
  59. await fetchSavedSearches(api, 'org-1', {});
  60. await tick();
  61. Client.addMockResponse({
  62. url: '/organizations/org-1/pinned-searches/',
  63. method: 'PUT',
  64. body: {
  65. id: '123',
  66. query: 'level:info',
  67. sort: 'freq',
  68. isPinned: true,
  69. },
  70. });
  71. pinSearch(api, 'org-1', 0, 'level:info', 'freq');
  72. await tick();
  73. await tick();
  74. expect(SavedSearchesStore.get().savedSearches).toHaveLength(3);
  75. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  76. expect.objectContaining({
  77. id: '123',
  78. isPinned: true,
  79. type: 0,
  80. query: 'level:info',
  81. name: 'My Pinned Search',
  82. sort: 'freq',
  83. })
  84. );
  85. });
  86. it('changes pinned search from a custom search to an existing search', async function () {
  87. const searches = TestStubs.Searches();
  88. Client.addMockResponse({
  89. url: '/organizations/org-1/searches/',
  90. body: [
  91. {
  92. id: null,
  93. isPinned: true,
  94. type: 0,
  95. query: 'assigned:me',
  96. sort: 'date',
  97. },
  98. ...searches,
  99. ],
  100. });
  101. Client.addMockResponse({
  102. url: '/organizations/org-1/pinned-searches/',
  103. method: 'PUT',
  104. body: {
  105. id: '1',
  106. isDefault: false,
  107. isGlobal: true,
  108. isOrgCustom: false,
  109. isPinned: true,
  110. query: 'is:unresolved',
  111. sort: 'date',
  112. name: 'Unresolved Issues',
  113. type: 0,
  114. },
  115. });
  116. await fetchSavedSearches(api, 'org-1', {});
  117. await tick();
  118. pinSearch(api, 'org-1', 0, searches[1].query, 'date');
  119. await tick();
  120. await tick();
  121. // Order should remain the same
  122. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  123. expect.objectContaining({
  124. id: '1',
  125. isDefault: false,
  126. isGlobal: true,
  127. isOrgCustom: false,
  128. isPinned: true,
  129. type: 0,
  130. name: 'Unresolved Issues',
  131. query: 'is:unresolved',
  132. sort: 'date',
  133. })
  134. );
  135. // Saved custom search should be removed
  136. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  137. });
  138. it('changes pinned search from an existing search to another existing search', async function () {
  139. const searches = TestStubs.Searches();
  140. Client.addMockResponse({
  141. url: '/organizations/org-1/searches/',
  142. body: [{...searches[0], isPinned: true}, searches[1]],
  143. });
  144. Client.addMockResponse({
  145. url: '/organizations/org-1/pinned-searches/',
  146. method: 'PUT',
  147. body: {
  148. id: '1',
  149. isDefault: false,
  150. isGlobal: true,
  151. isOrgCustom: false,
  152. isPinned: true,
  153. query: 'is:unresolved',
  154. sort: 'date',
  155. name: 'Unresolved Issues',
  156. type: 0,
  157. },
  158. });
  159. await fetchSavedSearches(api, 'org-1', {});
  160. await tick();
  161. pinSearch(api, 'org-1', 0, searches[1].query, 'date');
  162. await tick();
  163. await tick();
  164. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  165. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  166. expect.objectContaining({
  167. id: '2',
  168. isPinned: false,
  169. type: 0,
  170. name: 'Needs Triage',
  171. query: 'is:unresolved is:unassigned',
  172. sort: 'date',
  173. })
  174. );
  175. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  176. expect.objectContaining({
  177. id: '1',
  178. isDefault: false,
  179. isGlobal: true,
  180. isOrgCustom: false,
  181. isPinned: true,
  182. type: 0,
  183. name: 'Unresolved Issues',
  184. query: 'is:unresolved',
  185. sort: 'date',
  186. })
  187. );
  188. });
  189. it('unpins a user custom search (not global, and not org custom)', async function () {
  190. const searches = TestStubs.Searches();
  191. Client.addMockResponse({
  192. url: '/organizations/org-1/searches/',
  193. body: [
  194. {
  195. id: null,
  196. isPinned: true,
  197. type: 0,
  198. query: 'assigned:me',
  199. sort: 'date',
  200. },
  201. ...searches,
  202. ],
  203. });
  204. await fetchSavedSearches(api, 'org-1', {});
  205. await tick();
  206. unpinSearch(api, 'org-1', 0, searches[0]);
  207. await tick();
  208. await tick();
  209. // Saved custom search should be removed
  210. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  211. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  212. expect.objectContaining({
  213. id: '2',
  214. isPinned: false,
  215. type: 0,
  216. name: 'Needs Triage',
  217. query: 'is:unresolved is:unassigned',
  218. sort: 'date',
  219. })
  220. );
  221. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  222. expect.objectContaining({
  223. id: '1',
  224. isPinned: false,
  225. type: 0,
  226. name: 'Unresolved Issues',
  227. query: 'is:unresolved',
  228. sort: 'date',
  229. })
  230. );
  231. });
  232. it('unpins an existing global saved search', async function () {
  233. const searches = TestStubs.Searches();
  234. Client.addMockResponse({
  235. url: '/organizations/org-1/searches/',
  236. body: [{...searches[0], isPinned: true}, searches[1]],
  237. });
  238. await fetchSavedSearches(api, 'org-1', {});
  239. await tick();
  240. unpinSearch(api, 'org-1', 0, searches[0]);
  241. await tick();
  242. await tick();
  243. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  244. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  245. expect.objectContaining({
  246. id: '2',
  247. isPinned: false,
  248. type: 0,
  249. name: 'Needs Triage',
  250. query: 'is:unresolved is:unassigned',
  251. sort: 'date',
  252. })
  253. );
  254. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  255. expect.objectContaining({
  256. id: '1',
  257. isPinned: false,
  258. type: 0,
  259. name: 'Unresolved Issues',
  260. query: 'is:unresolved',
  261. sort: 'date',
  262. })
  263. );
  264. });
  265. it('unpins an existing org saved search', async function () {
  266. const searches = TestStubs.Searches();
  267. Client.addMockResponse({
  268. url: '/organizations/org-1/searches/',
  269. body: [
  270. {...searches[0], isOrgCustom: true, isGlobal: false, isPinned: true},
  271. searches[1],
  272. ],
  273. });
  274. await fetchSavedSearches(api, 'org-1', {});
  275. await tick();
  276. unpinSearch(api, 'org-1', 0, searches[0]);
  277. await tick();
  278. await tick();
  279. expect(SavedSearchesStore.get().savedSearches).toHaveLength(2);
  280. expect(SavedSearchesStore.get().savedSearches[0]).toEqual(
  281. expect.objectContaining({
  282. id: '2',
  283. isPinned: false,
  284. type: 0,
  285. name: 'Needs Triage',
  286. query: 'is:unresolved is:unassigned',
  287. sort: 'date',
  288. })
  289. );
  290. expect(SavedSearchesStore.get().savedSearches[1]).toEqual(
  291. expect.objectContaining({
  292. id: '1',
  293. isPinned: false,
  294. type: 0,
  295. name: 'Unresolved Issues',
  296. query: 'is:unresolved',
  297. sort: 'date',
  298. })
  299. );
  300. });
  301. it('removes deleted saved searches', async function () {
  302. await fetchSavedSearches(api, 'org-1', {});
  303. await tick();
  304. const searches = SavedSearchesStore.get().savedSearches;
  305. Client.addMockResponse({
  306. url: `/organizations/org-1/searches/${searches[0].id}/`,
  307. method: 'DELETE',
  308. body: {},
  309. });
  310. await deleteSavedSearch(api, 'org-1', searches[0]);
  311. await tick();
  312. const newSearches = SavedSearchesStore.get().savedSearches;
  313. expect(newSearches.length).toBeLessThan(searches.length);
  314. expect(newSearches[0].id).not.toBe(searches[0].id);
  315. });
  316. });