globalSelection.spec.jsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. import {
  2. initializeUrlState,
  3. updateDateTime,
  4. updateEnvironments,
  5. updateParams,
  6. updateParamsWithoutHistory,
  7. updateProjects,
  8. } from 'app/actionCreators/globalSelection';
  9. import GlobalSelectionActions from 'app/actions/globalSelectionActions';
  10. import localStorage from 'app/utils/localStorage';
  11. jest.mock('app/utils/localStorage');
  12. describe('GlobalSelection ActionCreators', function () {
  13. const organization = TestStubs.Organization();
  14. beforeEach(function () {
  15. localStorage.getItem.mockClear();
  16. jest.spyOn(GlobalSelectionActions, 'updateProjects');
  17. jest.spyOn(GlobalSelectionActions, 'initializeUrlState').mockImplementation();
  18. GlobalSelectionActions.updateProjects.mockClear();
  19. });
  20. describe('initializeUrlState', function () {
  21. let router;
  22. beforeEach(() => {
  23. router = TestStubs.router();
  24. });
  25. it('loads from local storage when no query params', function () {
  26. const key = `global-selection:${organization.slug}`;
  27. localStorage.setItem(key, JSON.stringify({environments: [], projects: [1]}));
  28. initializeUrlState({
  29. organization,
  30. queryParams: {},
  31. router,
  32. });
  33. expect(localStorage.getItem).toHaveBeenCalledWith(
  34. `global-selection:${organization.slug}`
  35. );
  36. expect(GlobalSelectionActions.initializeUrlState).toHaveBeenCalledWith(
  37. expect.objectContaining({
  38. environments: [],
  39. projects: [1],
  40. })
  41. );
  42. expect(router.replace).toHaveBeenCalledWith(
  43. expect.objectContaining({
  44. query: {
  45. environment: [],
  46. project: [1],
  47. },
  48. })
  49. );
  50. });
  51. it('does not load from local storage when no query params and `skipLoadLastUsed` is true', function () {
  52. jest.spyOn(localStorage, 'getItem');
  53. initializeUrlState({
  54. organization,
  55. queryParams: {},
  56. skipLoadLastUsed: true,
  57. router,
  58. });
  59. expect(localStorage.getItem).not.toHaveBeenCalled();
  60. });
  61. it('does not change dates with no query params or defaultSelection', function () {
  62. initializeUrlState({
  63. organization,
  64. queryParams: {
  65. project: '1',
  66. },
  67. router,
  68. });
  69. expect(GlobalSelectionActions.initializeUrlState).toHaveBeenCalledWith(
  70. expect.objectContaining({
  71. datetime: {
  72. start: null,
  73. end: null,
  74. period: '14d',
  75. utc: null,
  76. },
  77. })
  78. );
  79. });
  80. it('does changes to default dates with defaultSelection and no query params', function () {
  81. initializeUrlState({
  82. organization,
  83. queryParams: {
  84. project: '1',
  85. },
  86. defaultSelection: {
  87. datetime: {
  88. period: '3h',
  89. },
  90. },
  91. router,
  92. });
  93. expect(GlobalSelectionActions.initializeUrlState).toHaveBeenCalledWith(
  94. expect.objectContaining({
  95. datetime: {
  96. start: null,
  97. end: null,
  98. period: '3h',
  99. utc: null,
  100. },
  101. })
  102. );
  103. });
  104. it('uses query params statsPeriod over defaults', function () {
  105. initializeUrlState({
  106. organization,
  107. queryParams: {
  108. statsPeriod: '1h',
  109. project: '1',
  110. },
  111. defaultSelection: {
  112. datetime: {
  113. period: '24h',
  114. },
  115. },
  116. router,
  117. });
  118. expect(router.replace).toHaveBeenCalledWith(
  119. expect.objectContaining({
  120. query: {
  121. cursor: undefined,
  122. project: [1],
  123. environment: [],
  124. statsPeriod: '1h',
  125. },
  126. })
  127. );
  128. });
  129. it('uses absolute dates over defaults', function () {
  130. initializeUrlState({
  131. organization,
  132. queryParams: {
  133. start: '2020-03-22T00:53:38',
  134. end: '2020-04-21T00:53:38',
  135. project: '1',
  136. },
  137. defaultSelection: {
  138. datetime: {
  139. period: '24h',
  140. },
  141. },
  142. router,
  143. });
  144. expect(router.replace).toHaveBeenCalledWith(
  145. expect.objectContaining({
  146. query: {
  147. cursor: undefined,
  148. project: [1],
  149. environment: [],
  150. start: '2020-03-22T00:53:38',
  151. end: '2020-04-21T00:53:38',
  152. },
  153. })
  154. );
  155. });
  156. it('does not load from local storage when there are query params', function () {
  157. initializeUrlState({
  158. organization,
  159. queryParams: {
  160. project: '1',
  161. },
  162. router,
  163. });
  164. expect(localStorage.getItem).not.toHaveBeenCalled();
  165. expect(GlobalSelectionActions.initializeUrlState).toHaveBeenCalledWith({
  166. datetime: {
  167. start: null,
  168. end: null,
  169. period: '14d',
  170. utc: null,
  171. },
  172. projects: [1],
  173. environments: [],
  174. });
  175. expect(router.replace).toHaveBeenCalledWith(
  176. expect.objectContaining({
  177. query: {
  178. environment: [],
  179. project: [1],
  180. },
  181. })
  182. );
  183. });
  184. });
  185. describe('updateProjects()', function () {
  186. it('updates', function () {
  187. updateProjects([1, 2]);
  188. expect(GlobalSelectionActions.updateProjects).toHaveBeenCalledWith(
  189. [1, 2],
  190. undefined
  191. );
  192. });
  193. it('does not update invalid projects', function () {
  194. updateProjects(['1']);
  195. expect(GlobalSelectionActions.updateProjects).not.toHaveBeenCalled();
  196. });
  197. });
  198. describe('updateEnvironments()', function () {
  199. it('updates single', function () {
  200. const router = TestStubs.router({
  201. location: {
  202. pathname: '/test/',
  203. query: {environment: 'test'},
  204. },
  205. });
  206. updateEnvironments(['new-env'], router);
  207. expect(router.push).toHaveBeenCalledWith({
  208. pathname: '/test/',
  209. query: {environment: ['new-env']},
  210. });
  211. });
  212. it('updates multiple', function () {
  213. const router = TestStubs.router({
  214. location: {
  215. pathname: '/test/',
  216. query: {environment: 'test'},
  217. },
  218. });
  219. updateEnvironments(['new-env', 'another-env'], router);
  220. expect(router.push).toHaveBeenCalledWith({
  221. pathname: '/test/',
  222. query: {environment: ['new-env', 'another-env']},
  223. });
  224. });
  225. it('removes environment', function () {
  226. const router = TestStubs.router({
  227. location: {
  228. pathname: '/test/',
  229. query: {environment: 'test'},
  230. },
  231. });
  232. updateEnvironments(null, router);
  233. expect(router.push).toHaveBeenCalledWith({
  234. pathname: '/test/',
  235. query: {},
  236. });
  237. });
  238. });
  239. describe('updateDateTime()', function () {
  240. it('updates statsPeriod when there is no existing stats period', function () {
  241. const router = TestStubs.router({
  242. location: {
  243. pathname: '/test/',
  244. query: {},
  245. },
  246. });
  247. updateDateTime({statsPeriod: '24h'}, router);
  248. expect(router.push).toHaveBeenCalledWith({
  249. pathname: '/test/',
  250. query: {
  251. statsPeriod: '24h',
  252. },
  253. });
  254. });
  255. it('updates statsPeriod when there is an existing stats period', function () {
  256. const router = TestStubs.router({
  257. location: {
  258. pathname: '/test/',
  259. query: {statsPeriod: '14d'},
  260. },
  261. });
  262. updateDateTime({statsPeriod: '24h'}, router);
  263. expect(router.push).toHaveBeenCalledWith({
  264. pathname: '/test/',
  265. query: {
  266. statsPeriod: '24h',
  267. },
  268. });
  269. });
  270. it('updates `statsPeriod` when given a new `period`', function () {
  271. const router = TestStubs.router({
  272. location: {
  273. pathname: '/test/',
  274. query: {},
  275. },
  276. });
  277. updateDateTime({period: '24h'}, router);
  278. expect(router.push).toHaveBeenCalledWith({
  279. pathname: '/test/',
  280. query: {
  281. statsPeriod: '24h',
  282. },
  283. });
  284. });
  285. it('changes to absolute date', function () {
  286. const router = TestStubs.router({
  287. location: {
  288. pathname: '/test/',
  289. query: {statsPeriod: '24h'},
  290. },
  291. });
  292. updateDateTime({start: '2020-03-22T00:53:38', end: '2020-04-21T00:53:38'}, router);
  293. expect(router.push).toHaveBeenCalledWith({
  294. pathname: '/test/',
  295. query: {
  296. start: '2020-03-22T00:53:38',
  297. end: '2020-04-21T00:53:38',
  298. },
  299. });
  300. });
  301. });
  302. describe('updateParams()', function () {
  303. it('updates history when queries are different', function () {
  304. const router = TestStubs.router({
  305. location: {
  306. pathname: '/test/',
  307. query: {project: '2'},
  308. },
  309. });
  310. // this can be passed w/ `project` as an array (e.g. multiple projects being selected)
  311. // however react-router will treat it as a string if there is only one param
  312. updateParams(
  313. {project: [1]},
  314. // Mock router
  315. router
  316. );
  317. expect(router.push).toHaveBeenCalledWith({
  318. pathname: '/test/',
  319. query: {project: [1]},
  320. });
  321. });
  322. it('does not update history when queries are the same', function () {
  323. const router = TestStubs.router({
  324. location: {
  325. pathname: '/test/',
  326. query: {project: '1'},
  327. },
  328. });
  329. // this can be passed w/ `project` as an array (e.g. multiple projects being selected)
  330. // however react-router will treat it as a string if there is only one param
  331. updateParams(
  332. {project: [1]},
  333. // Mock router
  334. router
  335. );
  336. expect(router.push).not.toHaveBeenCalled();
  337. });
  338. });
  339. describe('updateParamsWithoutHistory()', function () {
  340. it('updates history when queries are different', function () {
  341. const router = TestStubs.router({
  342. location: {
  343. pathname: '/test/',
  344. query: {project: '2'},
  345. },
  346. });
  347. // this can be passed w/ `project` as an array (e.g. multiple projects being selected)
  348. // however react-router will treat it as a string if there is only one param
  349. updateParamsWithoutHistory(
  350. {project: [1]},
  351. // Mock router
  352. router
  353. );
  354. expect(router.replace).toHaveBeenCalledWith({
  355. pathname: '/test/',
  356. query: {project: [1]},
  357. });
  358. });
  359. it('does not update history when queries are the same', function () {
  360. const router = TestStubs.router({
  361. location: {
  362. pathname: '/test/',
  363. query: {project: '1'},
  364. },
  365. });
  366. // this can be passed w/ `project` as an array (e.g. multiple projects being selected)
  367. // however react-router will treat it as a string if there is only one param
  368. updateParamsWithoutHistory(
  369. {project: [1]},
  370. // Mock router
  371. router
  372. );
  373. expect(router.replace).not.toHaveBeenCalled();
  374. });
  375. });
  376. });