index.spec.jsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. import React from 'react';
  2. import {initializeOrg} from 'app-test/helpers/initializeOrg';
  3. import {mockRouterPush} from 'app-test/helpers/mockRouterPush';
  4. import {mount} from 'enzyme';
  5. import {setActiveOrganization} from 'app/actionCreators/organizations';
  6. import GlobalSelectionStore from 'app/stores/globalSelectionStore';
  7. import OrganizationEventsContainer from 'app/views/organizationEvents';
  8. describe('OrganizationEvents', function() {
  9. let wrapper;
  10. const {organization, router, routerContext} = initializeOrg({
  11. projects: [{isMember: true}, {isMember: true, slug: 'new-project', id: 3}],
  12. organization: {
  13. features: ['events', 'global-views'],
  14. },
  15. router: {
  16. location: {
  17. pathname: '/organizations/org-slug/events/',
  18. query: {},
  19. },
  20. },
  21. });
  22. beforeAll(async function() {
  23. MockApiClient.addMockResponse({
  24. url: '/organizations/org-slug/tags/',
  25. body: [{count: 1, tag: 'transaction'}, {count: 2, tag: 'mechanism'}],
  26. });
  27. MockApiClient.addMockResponse({
  28. url: `/organizations/${organization.slug}/environments/`,
  29. body: TestStubs.Environments(),
  30. });
  31. setActiveOrganization(organization);
  32. await tick();
  33. });
  34. describe('Header', function() {
  35. beforeEach(function() {
  36. GlobalSelectionStore.reset();
  37. router.location = {
  38. pathname: '/organizations/org-slug/events/',
  39. query: {},
  40. };
  41. wrapper = mount(
  42. <OrganizationEventsContainer
  43. router={router}
  44. organization={organization}
  45. location={router.location}
  46. >
  47. <div />
  48. </OrganizationEventsContainer>,
  49. routerContext
  50. );
  51. mockRouterPush(wrapper, router);
  52. });
  53. it('renders', function() {
  54. expect(wrapper.find('PageContent')).toHaveLength(1);
  55. });
  56. it('updates router when changing environments', async function() {
  57. expect(wrapper.find('MultipleEnvironmentSelector').prop('value')).toEqual([]);
  58. wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  59. await tick();
  60. wrapper.update();
  61. wrapper
  62. .find('EnvironmentSelectorItem')
  63. .at(0)
  64. .simulate('click');
  65. await tick();
  66. wrapper.update();
  67. expect(router.push).toHaveBeenLastCalledWith({
  68. pathname: '/organizations/org-slug/events/',
  69. query: {
  70. environment: ['production'],
  71. statsPeriod: '14d',
  72. },
  73. });
  74. await tick();
  75. wrapper.update();
  76. expect(wrapper.find('MultipleEnvironmentSelector').prop('value')).toEqual([
  77. 'production',
  78. ]);
  79. // Select a second environment, "staging"
  80. wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  81. await tick();
  82. wrapper.update();
  83. wrapper
  84. .find('EnvironmentSelectorItem')
  85. .at(1)
  86. .find('MultiSelect')
  87. .simulate('click');
  88. expect(wrapper.find('MultipleEnvironmentSelector').prop('value')).toEqual([
  89. 'production',
  90. 'staging',
  91. ]);
  92. // close dropdown
  93. wrapper
  94. .find('MultipleEnvironmentSelector StyledInput')
  95. .simulate('keyDown', {key: 'Escape'});
  96. await tick();
  97. wrapper.update();
  98. expect(router.push).toHaveBeenLastCalledWith({
  99. pathname: '/organizations/org-slug/events/',
  100. query: {
  101. environment: ['production', 'staging'],
  102. statsPeriod: '14d',
  103. },
  104. });
  105. expect(wrapper.find('MultipleEnvironmentSelector').prop('value')).toEqual([
  106. 'production',
  107. 'staging',
  108. ]);
  109. // Can clear
  110. wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  111. await tick();
  112. wrapper.update();
  113. wrapper
  114. .find('MultipleEnvironmentSelector HeaderItem StyledClose')
  115. .simulate('click');
  116. await tick();
  117. wrapper.update();
  118. expect(wrapper.find('MultipleEnvironmentSelector').prop('value')).toEqual([]);
  119. expect(router.push).toHaveBeenCalledWith({
  120. pathname: '/organizations/org-slug/events/',
  121. query: {
  122. environment: [],
  123. statsPeriod: '14d',
  124. },
  125. });
  126. });
  127. it('updates router when changing projects', async function() {
  128. expect(wrapper.find('MultipleProjectSelector').prop('value')).toEqual([]);
  129. wrapper.find('MultipleProjectSelector HeaderItem').simulate('click');
  130. wrapper
  131. .find('MultipleProjectSelector AutoCompleteItem')
  132. .at(0)
  133. .simulate('click');
  134. await tick();
  135. wrapper.update();
  136. expect(router.push).toHaveBeenCalledWith({
  137. pathname: '/organizations/org-slug/events/',
  138. query: {
  139. project: [2],
  140. statsPeriod: '14d',
  141. },
  142. });
  143. expect(wrapper.find('MultipleProjectSelector').prop('value')).toEqual([2]);
  144. });
  145. it('selects multiple projects', async function() {
  146. expect(wrapper.find('MultipleProjectSelector').prop('value')).toEqual([]);
  147. wrapper.find('MultipleProjectSelector HeaderItem').simulate('click');
  148. wrapper
  149. .find('MultipleProjectSelector AutoCompleteItem MultiSelectWrapper')
  150. .at(0)
  151. .simulate('click');
  152. expect(wrapper.find('MultipleProjectSelector').prop('value')).toEqual([2]);
  153. wrapper
  154. .find('MultipleProjectSelector AutoCompleteItem MultiSelectWrapper')
  155. .at(1)
  156. .simulate('click');
  157. expect(wrapper.find('MultipleProjectSelector').prop('value')).toEqual([2, 3]);
  158. wrapper.find('MultipleProjectSelector StyledChevron').simulate('click');
  159. expect(router.push).toHaveBeenCalledWith({
  160. pathname: '/organizations/org-slug/events/',
  161. query: {
  162. project: [2, 3],
  163. statsPeriod: '14d',
  164. },
  165. });
  166. });
  167. it('changes to absolute time (utc is default)', async function() {
  168. const start = new Date('2017-10-01T00:00:00.000Z');
  169. const end = new Date('2017-10-01T23:59:59.000Z');
  170. wrapper.find('TimeRangeSelector HeaderItem').simulate('click');
  171. await wrapper.find('SelectorItem[value="absolute"]').simulate('click');
  172. // Oct 1st
  173. wrapper
  174. .find('DayCell')
  175. .at(0)
  176. .simulate('mouseUp');
  177. wrapper.find('TimeRangeSelector StyledChevron').simulate('click');
  178. await tick();
  179. wrapper.update();
  180. expect(router.push).toHaveBeenCalledWith({
  181. pathname: '/organizations/org-slug/events/',
  182. query: {
  183. start: '2017-10-01T00:00:00',
  184. end: '2017-10-01T23:59:59',
  185. utc: 'true',
  186. },
  187. });
  188. expect(wrapper.find('TimeRangeSelector').prop('start')).toEqual(start);
  189. expect(wrapper.find('TimeRangeSelector').prop('end')).toEqual(end);
  190. expect(wrapper.find('TimeRangeSelector').prop('relative')).toEqual(null);
  191. });
  192. it('does not update router when toggling environment selector without changes', async function() {
  193. const prevCallCount = router.push.mock.calls.length;
  194. wrapper.setProps({
  195. router: {
  196. ...router,
  197. location: {
  198. ...router.location,
  199. query: {
  200. environment: ['production'],
  201. statsPeriod: '14d',
  202. utc: 'true',
  203. },
  204. },
  205. },
  206. });
  207. // Toggle MultipleProjectSelector
  208. wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  209. wrapper
  210. .find('MultipleEnvironmentSelector StyledInput')
  211. .simulate('keyDown', {key: 'Escape'});
  212. expect(router.push).toHaveBeenCalledTimes(prevCallCount);
  213. });
  214. it('updates router when changing periods', async function() {
  215. expect(wrapper.find('TimeRangeSelector').prop('start')).toEqual(null);
  216. expect(wrapper.find('TimeRangeSelector').prop('end')).toEqual(null);
  217. expect(wrapper.find('TimeRangeSelector').prop('relative')).toEqual('14d');
  218. wrapper.find('TimeRangeSelector HeaderItem').simulate('click');
  219. expect(wrapper.find('[data-test-id="date-range"]')).toHaveLength(0);
  220. wrapper.find('SelectorItem[value="absolute"]').simulate('click');
  221. wrapper.find('TimeRangeSelector HeaderItem').simulate('click');
  222. await tick();
  223. wrapper.update();
  224. expect(router.push).toHaveBeenCalledWith({
  225. pathname: '/organizations/org-slug/events/',
  226. query: {
  227. end: '2017-10-17T02:41:20',
  228. start: '2017-10-03T02:41:20',
  229. utc: 'true',
  230. },
  231. });
  232. expect(wrapper.find('TimeRangeSelector').props()).toEqual(
  233. expect.objectContaining({
  234. end: new Date('2017-10-17T02:41:20.000Z'),
  235. start: new Date('2017-10-03T02:41:20.000Z'),
  236. utc: true,
  237. })
  238. );
  239. // Can switch back to relative date
  240. wrapper.find('TimeRangeSelector HeaderItem').simulate('click');
  241. wrapper.find('SelectorItem[value="7d"]').simulate('click');
  242. wrapper.find('TimeRangeSelector HeaderItem').simulate('click');
  243. await tick();
  244. wrapper.update();
  245. expect(wrapper.find('TimeRangeSelector').prop('relative')).toEqual('7d');
  246. expect(router.push).toHaveBeenCalledWith({
  247. pathname: '/organizations/org-slug/events/',
  248. query: {
  249. statsPeriod: '7d',
  250. utc: 'true',
  251. },
  252. });
  253. expect(wrapper.find('TimeRangeSelector').props()).toEqual(
  254. expect.objectContaining({
  255. end: null,
  256. start: null,
  257. relative: '7d',
  258. utc: true,
  259. })
  260. );
  261. });
  262. it('updates TimeRangeSelector when changing routes', async function() {
  263. let newRouter = {
  264. router: {
  265. ...router,
  266. location: {
  267. pathname: '/organizations/org-slug/events2/',
  268. query: {
  269. end: '2017-10-17T02:41:20',
  270. start: '2017-10-03T02:41:20',
  271. utc: 'true',
  272. },
  273. },
  274. },
  275. };
  276. wrapper.setProps(newRouter);
  277. wrapper.setContext(newRouter);
  278. await tick();
  279. wrapper.update();
  280. expect(wrapper.find('TimeRangeSelector').text()).toEqual(
  281. 'Oct 3, 201702:41toOct 17, 201702:41'
  282. );
  283. newRouter = {
  284. router: {
  285. ...router,
  286. location: {
  287. pathname: '/organizations/org-slug/events/',
  288. query: {
  289. statsPeriod: '7d',
  290. end: null,
  291. start: null,
  292. utc: 'true',
  293. },
  294. },
  295. },
  296. };
  297. wrapper.setProps(newRouter);
  298. wrapper.setContext(newRouter);
  299. await tick();
  300. wrapper.update();
  301. expect(wrapper.find('TimeRangeSelector').text()).toEqual('Last 7 days');
  302. });
  303. });
  304. });