initDashboard.test.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import configureMockStore from 'redux-mock-store';
  2. import thunk from 'redux-thunk';
  3. import { initDashboard, InitDashboardArgs } from './initDashboard';
  4. import { DashboardRouteInfo } from 'app/types';
  5. import { getBackendSrv } from 'app/core/services/backend_srv';
  6. import { dashboardInitFetching, dashboardInitCompleted, dashboardInitServices } from './actions';
  7. import { resetExploreAction } from 'app/features/explore/state/actionTypes';
  8. jest.mock('app/core/services/backend_srv');
  9. const mockStore = configureMockStore([thunk]);
  10. interface ScenarioContext {
  11. args: InitDashboardArgs;
  12. timeSrv: any;
  13. annotationsSrv: any;
  14. unsavedChangesSrv: any;
  15. variableSrv: any;
  16. dashboardSrv: any;
  17. loaderSrv: any;
  18. keybindingSrv: any;
  19. backendSrv: any;
  20. setup: (fn: () => void) => void;
  21. actions: any[];
  22. storeState: any;
  23. }
  24. type ScenarioFn = (ctx: ScenarioContext) => void;
  25. function describeInitScenario(description: string, scenarioFn: ScenarioFn) {
  26. describe(description, () => {
  27. const timeSrv = { init: jest.fn() };
  28. const annotationsSrv = { init: jest.fn() };
  29. const unsavedChangesSrv = { init: jest.fn() };
  30. const variableSrv = { init: jest.fn() };
  31. const dashboardSrv = { setCurrent: jest.fn() };
  32. const keybindingSrv = { setupDashboardBindings: jest.fn() };
  33. const loaderSrv = {
  34. loadDashboard: jest.fn(() => ({
  35. meta: {
  36. canStar: false,
  37. canShare: false,
  38. isNew: true,
  39. folderId: 0,
  40. },
  41. dashboard: {
  42. title: 'My cool dashboard',
  43. panels: [
  44. {
  45. type: 'add-panel',
  46. gridPos: { x: 0, y: 0, w: 12, h: 9 },
  47. title: 'Panel Title',
  48. id: 2,
  49. targets: [
  50. {
  51. refId: 'A',
  52. expr: 'old expr',
  53. },
  54. ],
  55. },
  56. ],
  57. },
  58. })),
  59. };
  60. const injectorMock = {
  61. get: (name: string) => {
  62. switch (name) {
  63. case 'timeSrv':
  64. return timeSrv;
  65. case 'annotationsSrv':
  66. return annotationsSrv;
  67. case 'dashboardLoaderSrv':
  68. return loaderSrv;
  69. case 'unsavedChangesSrv':
  70. return unsavedChangesSrv;
  71. case 'dashboardSrv':
  72. return dashboardSrv;
  73. case 'variableSrv':
  74. return variableSrv;
  75. case 'keybindingSrv':
  76. return keybindingSrv;
  77. default:
  78. throw { message: 'Unknown service ' + name };
  79. }
  80. },
  81. };
  82. let setupFn = () => {};
  83. const ctx: ScenarioContext = {
  84. args: {
  85. $injector: injectorMock,
  86. $scope: {},
  87. fixUrl: false,
  88. routeInfo: DashboardRouteInfo.Normal,
  89. },
  90. backendSrv: getBackendSrv(),
  91. timeSrv,
  92. annotationsSrv,
  93. unsavedChangesSrv,
  94. variableSrv,
  95. dashboardSrv,
  96. keybindingSrv,
  97. loaderSrv,
  98. actions: [],
  99. storeState: {
  100. location: {
  101. query: {},
  102. },
  103. user: {},
  104. explore: {
  105. left: {
  106. originPanelId: undefined,
  107. queries: [],
  108. },
  109. },
  110. },
  111. setup: (fn: () => void) => {
  112. setupFn = fn;
  113. },
  114. };
  115. beforeEach(async () => {
  116. setupFn();
  117. const store = mockStore(ctx.storeState);
  118. // @ts-ignore
  119. await store.dispatch(initDashboard(ctx.args));
  120. ctx.actions = store.getActions();
  121. });
  122. scenarioFn(ctx);
  123. });
  124. }
  125. describeInitScenario('Initializing new dashboard', ctx => {
  126. ctx.setup(() => {
  127. ctx.storeState.user.orgId = 12;
  128. ctx.args.routeInfo = DashboardRouteInfo.New;
  129. });
  130. it('Should send action dashboardInitFetching', () => {
  131. expect(ctx.actions[0].type).toBe(dashboardInitFetching.type);
  132. });
  133. it('Should send action dashboardInitServices ', () => {
  134. expect(ctx.actions[1].type).toBe(dashboardInitServices.type);
  135. });
  136. it('Should update location with orgId query param', () => {
  137. expect(ctx.actions[2].type).toBe('UPDATE_LOCATION');
  138. expect(ctx.actions[2].payload.query.orgId).toBe(12);
  139. });
  140. it('Should send action dashboardInitCompleted', () => {
  141. expect(ctx.actions[3].type).toBe(dashboardInitCompleted.type);
  142. expect(ctx.actions[3].payload.title).toBe('New dashboard');
  143. });
  144. it('Should initialize services', () => {
  145. expect(ctx.timeSrv.init).toBeCalled();
  146. expect(ctx.annotationsSrv.init).toBeCalled();
  147. expect(ctx.variableSrv.init).toBeCalled();
  148. expect(ctx.unsavedChangesSrv.init).toBeCalled();
  149. expect(ctx.keybindingSrv.setupDashboardBindings).toBeCalled();
  150. expect(ctx.dashboardSrv.setCurrent).toBeCalled();
  151. });
  152. });
  153. describeInitScenario('Initializing home dashboard', ctx => {
  154. ctx.setup(() => {
  155. ctx.args.routeInfo = DashboardRouteInfo.Home;
  156. ctx.backendSrv.get.mockReturnValue(
  157. Promise.resolve({
  158. redirectUri: '/u/123/my-home',
  159. })
  160. );
  161. });
  162. it('Should redirect to custom home dashboard', () => {
  163. expect(ctx.actions[1].type).toBe('UPDATE_LOCATION');
  164. expect(ctx.actions[1].payload.path).toBe('/u/123/my-home');
  165. });
  166. });
  167. describeInitScenario('Initializing existing dashboard', ctx => {
  168. const mockQueries = [
  169. {
  170. context: 'explore',
  171. key: 'jdasldsa98dsa9',
  172. refId: 'A',
  173. expr: 'new expr',
  174. },
  175. {
  176. context: 'explore',
  177. key: 'fdsjkfds78fd',
  178. refId: 'B',
  179. },
  180. ];
  181. const expectedQueries = mockQueries.map(query => ({ refId: query.refId, expr: query.expr }));
  182. ctx.setup(() => {
  183. ctx.storeState.user.orgId = 12;
  184. ctx.storeState.explore.left.originPanelId = 2;
  185. ctx.storeState.explore.left.queries = mockQueries;
  186. });
  187. it('Should send action dashboardInitFetching', () => {
  188. expect(ctx.actions[0].type).toBe(dashboardInitFetching.type);
  189. });
  190. it('Should send action dashboardInitServices ', () => {
  191. expect(ctx.actions[1].type).toBe(dashboardInitServices.type);
  192. });
  193. it('Should update location with orgId query param', () => {
  194. expect(ctx.actions[2].type).toBe('UPDATE_LOCATION');
  195. expect(ctx.actions[2].payload.query.orgId).toBe(12);
  196. });
  197. it('Should send resetExploreAction when coming from explore', () => {
  198. expect(ctx.actions[3].type).toBe(resetExploreAction.type);
  199. expect(ctx.actions[3].payload.force).toBe(true);
  200. expect(ctx.dashboardSrv.setCurrent).lastCalledWith(
  201. expect.objectContaining({
  202. panels: expect.arrayContaining([
  203. expect.objectContaining({
  204. targets: expectedQueries,
  205. }),
  206. ]),
  207. })
  208. );
  209. });
  210. it('Should send action dashboardInitCompleted', () => {
  211. expect(ctx.actions[4].type).toBe(dashboardInitCompleted.type);
  212. expect(ctx.actions[4].payload.title).toBe('My cool dashboard');
  213. });
  214. it('Should initialize services', () => {
  215. expect(ctx.timeSrv.init).toBeCalled();
  216. expect(ctx.annotationsSrv.init).toBeCalled();
  217. expect(ctx.variableSrv.init).toBeCalled();
  218. expect(ctx.unsavedChangesSrv.init).toBeCalled();
  219. expect(ctx.keybindingSrv.setupDashboardBindings).toBeCalled();
  220. expect(ctx.dashboardSrv.setCurrent).toBeCalled();
  221. });
  222. });