orgDashboards.spec.tsx 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. import {browserHistory} from 'react-router';
  2. import {initializeOrg} from 'sentry-test/initializeOrg';
  3. import {render, screen, waitFor} from 'sentry-test/reactTestingLibrary';
  4. import DashboardDetail from 'sentry/views/dashboards/detail';
  5. import OrgDashboards from 'sentry/views/dashboards/orgDashboards';
  6. import {DashboardState} from 'sentry/views/dashboards/types';
  7. describe('OrgDashboards', () => {
  8. const api = new MockApiClient();
  9. const organization = TestStubs.Organization({
  10. features: ['dashboards-basic', 'dashboards-edit'],
  11. });
  12. let initialData;
  13. beforeEach(() => {
  14. initialData = initializeOrg({
  15. organization,
  16. projects: [],
  17. router: {
  18. location: TestStubs.location(),
  19. params: {orgId: 'org-slug'},
  20. },
  21. });
  22. const mockDashboard = {
  23. dateCreated: '2021-08-10T21:20:46.798237Z',
  24. id: '1',
  25. title: 'Test Dashboard',
  26. widgets: [],
  27. projects: [],
  28. filters: {},
  29. };
  30. MockApiClient.addMockResponse({
  31. url: `/organizations/org-slug/dashboards/1/`,
  32. method: 'GET',
  33. body: mockDashboard,
  34. });
  35. MockApiClient.addMockResponse({
  36. url: '/organizations/org-slug/dashboards/',
  37. body: [mockDashboard],
  38. });
  39. });
  40. afterEach(() => {
  41. MockApiClient.clearMockResponses();
  42. jest.clearAllMocks();
  43. });
  44. it('redirects to add query params for page filters if any are saved', async () => {
  45. const mockDashboardWithFilters = {
  46. dateCreated: '2021-08-10T21:20:46.798237Z',
  47. id: '1',
  48. title: 'Test Dashboard',
  49. widgets: [],
  50. projects: [1, 2],
  51. environment: ['alpha'],
  52. period: '7d',
  53. filters: {},
  54. };
  55. MockApiClient.addMockResponse({
  56. url: `/organizations/org-slug/dashboards/1/`,
  57. method: 'GET',
  58. body: mockDashboardWithFilters,
  59. });
  60. MockApiClient.addMockResponse({
  61. url: '/organizations/org-slug/dashboards/',
  62. body: [mockDashboardWithFilters],
  63. });
  64. render(
  65. <OrgDashboards
  66. api={api}
  67. location={TestStubs.location()}
  68. organization={initialData.organization}
  69. params={{orgId: 'org-slug', dashboardId: '1'}}
  70. >
  71. {({dashboard, dashboards}) => {
  72. return dashboard ? (
  73. <DashboardDetail
  74. api={api}
  75. initialState={DashboardState.VIEW}
  76. location={initialData.routerContext.location}
  77. router={initialData.router}
  78. dashboard={dashboard}
  79. dashboards={dashboards}
  80. {...initialData.router}
  81. />
  82. ) : (
  83. <div>loading</div>
  84. );
  85. }}
  86. </OrgDashboards>,
  87. {context: initialData.routerContext}
  88. );
  89. await waitFor(() =>
  90. expect(browserHistory.replace).toHaveBeenCalledWith(
  91. expect.objectContaining({
  92. query: expect.objectContaining({
  93. project: [1, 2],
  94. environment: ['alpha'],
  95. statsPeriod: '7d',
  96. }),
  97. })
  98. )
  99. );
  100. });
  101. it('ignores query params that are not page filters for redirection', async () => {
  102. const mockDashboardWithFilters = {
  103. dateCreated: '2021-08-10T21:20:46.798237Z',
  104. id: '1',
  105. title: 'Test Dashboard',
  106. widgets: [],
  107. projects: [1, 2],
  108. environment: ['alpha'],
  109. period: '7d',
  110. filters: {},
  111. };
  112. MockApiClient.addMockResponse({
  113. url: `/organizations/org-slug/dashboards/1/`,
  114. method: 'GET',
  115. body: mockDashboardWithFilters,
  116. });
  117. MockApiClient.addMockResponse({
  118. url: '/organizations/org-slug/dashboards/',
  119. body: [mockDashboardWithFilters],
  120. });
  121. render(
  122. <OrgDashboards
  123. api={api}
  124. location={{
  125. ...TestStubs.location(),
  126. query: {
  127. // This query param is not a page filter, so it should not interfere
  128. // with the redirect logic
  129. sort: 'recentlyViewed',
  130. },
  131. }}
  132. organization={initialData.organization}
  133. params={{orgId: 'org-slug', dashboardId: '1'}}
  134. >
  135. {({dashboard, dashboards}) => {
  136. return dashboard ? (
  137. <DashboardDetail
  138. api={api}
  139. initialState={DashboardState.VIEW}
  140. location={initialData.router.location}
  141. router={initialData.router}
  142. dashboard={dashboard}
  143. dashboards={dashboards}
  144. {...initialData.router}
  145. />
  146. ) : (
  147. <div>loading</div>
  148. );
  149. }}
  150. </OrgDashboards>,
  151. {context: initialData.routerContext}
  152. );
  153. await waitFor(() =>
  154. expect(browserHistory.replace).toHaveBeenCalledWith(
  155. expect.objectContaining({
  156. query: expect.objectContaining({
  157. project: [1, 2],
  158. environment: ['alpha'],
  159. statsPeriod: '7d',
  160. }),
  161. })
  162. )
  163. );
  164. });
  165. it('does not add query params for page filters if one of the filters is defined', () => {
  166. initialData = initializeOrg({
  167. organization,
  168. projects: [],
  169. router: {
  170. location: {
  171. ...TestStubs.location(),
  172. query: {
  173. // project is supplied in the URL, so we should avoid redirecting
  174. project: ['1'],
  175. },
  176. },
  177. params: {orgId: 'org-slug'},
  178. },
  179. });
  180. const mockDashboardWithFilters = {
  181. dateCreated: '2021-08-10T21:20:46.798237Z',
  182. id: '1',
  183. title: 'Test Dashboard',
  184. widgets: [],
  185. projects: [1, 2],
  186. environment: ['alpha'],
  187. period: '7d',
  188. filters: {},
  189. };
  190. MockApiClient.addMockResponse({
  191. url: `/organizations/org-slug/dashboards/1/`,
  192. method: 'GET',
  193. body: mockDashboardWithFilters,
  194. });
  195. MockApiClient.addMockResponse({
  196. url: '/organizations/org-slug/dashboards/',
  197. body: [mockDashboardWithFilters],
  198. });
  199. render(
  200. <OrgDashboards
  201. api={api}
  202. location={initialData.router.location}
  203. organization={initialData.organization}
  204. params={{orgId: 'org-slug', dashboardId: '1'}}
  205. >
  206. {({dashboard, dashboards}) => {
  207. return dashboard ? (
  208. <DashboardDetail
  209. api={api}
  210. initialState={DashboardState.VIEW}
  211. location={initialData.router.location}
  212. router={initialData.router}
  213. dashboard={dashboard}
  214. dashboards={dashboards}
  215. {...initialData.router}
  216. />
  217. ) : (
  218. <div>loading</div>
  219. );
  220. }}
  221. </OrgDashboards>,
  222. {context: initialData.routerContext}
  223. );
  224. expect(browserHistory.replace).not.toHaveBeenCalled();
  225. });
  226. it('does not add query params for page filters if none are saved', () => {
  227. render(
  228. <OrgDashboards
  229. api={api}
  230. location={TestStubs.location()}
  231. organization={initialData.organization}
  232. params={{orgId: 'org-slug', dashboardId: '1'}}
  233. >
  234. {({dashboard, dashboards}) => {
  235. return dashboard ? (
  236. <DashboardDetail
  237. api={api}
  238. initialState={DashboardState.VIEW}
  239. location={initialData.routerContext.location}
  240. router={initialData.router}
  241. dashboard={dashboard}
  242. dashboards={dashboards}
  243. {...initialData.router}
  244. />
  245. ) : (
  246. <div>loading</div>
  247. );
  248. }}
  249. </OrgDashboards>,
  250. {context: initialData.routerContext}
  251. );
  252. expect(browserHistory.replace).not.toHaveBeenCalled();
  253. });
  254. it('does not redirect to add query params if location is cleared manually', async () => {
  255. const mockDashboardWithFilters = {
  256. dateCreated: '2021-08-10T21:20:46.798237Z',
  257. id: '1',
  258. title: 'Test Dashboard',
  259. widgets: [],
  260. projects: [1],
  261. filters: {},
  262. };
  263. MockApiClient.addMockResponse({
  264. url: `/organizations/org-slug/dashboards/1/`,
  265. method: 'GET',
  266. body: mockDashboardWithFilters,
  267. });
  268. MockApiClient.addMockResponse({
  269. url: '/organizations/org-slug/dashboards/',
  270. body: [mockDashboardWithFilters],
  271. });
  272. const {rerender} = render(
  273. <OrgDashboards
  274. api={api}
  275. location={TestStubs.location()}
  276. organization={initialData.organization}
  277. params={{orgId: 'org-slug', dashboardId: '1'}}
  278. >
  279. {({dashboard, dashboards}) => {
  280. return dashboard ? (
  281. <DashboardDetail
  282. api={api}
  283. initialState={DashboardState.VIEW}
  284. location={initialData.routerContext.location}
  285. router={initialData.router}
  286. dashboard={dashboard}
  287. dashboards={dashboards}
  288. {...initialData.router}
  289. />
  290. ) : (
  291. <div>loading</div>
  292. );
  293. }}
  294. </OrgDashboards>,
  295. {context: initialData.routerContext}
  296. );
  297. await waitFor(() => expect(browserHistory.replace).toHaveBeenCalledTimes(1));
  298. rerender(
  299. <OrgDashboards
  300. api={api}
  301. location={{...initialData.routerContext.location, query: {}}}
  302. organization={initialData.organization}
  303. params={{orgId: 'org-slug', dashboardId: '1'}}
  304. >
  305. {({dashboard, dashboards}) => {
  306. return dashboard ? (
  307. <DashboardDetail
  308. api={api}
  309. initialState={DashboardState.VIEW}
  310. location={initialData.routerContext.location}
  311. router={initialData.router}
  312. dashboard={dashboard}
  313. dashboards={dashboards}
  314. {...initialData.router}
  315. />
  316. ) : (
  317. <div>loading</div>
  318. );
  319. }}
  320. </OrgDashboards>
  321. );
  322. expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument();
  323. expect(browserHistory.replace).toHaveBeenCalledTimes(1);
  324. });
  325. });