orgDashboards.spec.tsx 9.8 KB

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