SoloPanelPage.test.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import { render, screen } from '@testing-library/react';
  2. import React from 'react';
  3. import { DashboardRoutes } from 'app/types';
  4. import { getRouteComponentProps } from '../../../core/navigation/__mocks__/routeProps';
  5. import { Props as DashboardPanelProps } from '../dashgrid/DashboardPanel';
  6. import { DashboardModel } from '../state';
  7. import { Props, SoloPanelPage } from './SoloPanelPage';
  8. jest.mock('app/features/dashboard/components/DashboardSettings/GeneralSettings', () => ({}));
  9. jest.mock('app/features/dashboard/dashgrid/DashboardPanel', () => {
  10. class DashboardPanel extends React.Component<DashboardPanelProps> {
  11. render() {
  12. // In this test we only check whether a new panel has arrived in the props
  13. return <>{this.props.panel?.title}</>;
  14. }
  15. }
  16. return { DashboardPanel };
  17. });
  18. interface ScenarioContext {
  19. dashboard?: DashboardModel | null;
  20. secondaryDashboard?: DashboardModel | null;
  21. setDashboard: (overrides?: any, metaOverrides?: any) => void;
  22. setSecondaryDashboard: (overrides?: any, metaOverrides?: any) => void;
  23. mount: (propOverrides?: Partial<Props>) => void;
  24. rerender: (propOverrides?: Partial<Props>) => void;
  25. setup: (fn: () => void) => void;
  26. }
  27. function getTestDashboard(overrides?: any, metaOverrides?: any): DashboardModel {
  28. const data = Object.assign(
  29. {
  30. title: 'My dashboard',
  31. panels: [
  32. {
  33. id: 1,
  34. type: 'graph',
  35. title: 'My graph',
  36. gridPos: { x: 0, y: 0, w: 1, h: 1 },
  37. },
  38. ],
  39. },
  40. overrides
  41. );
  42. const meta = Object.assign({ canSave: true, canEdit: true }, metaOverrides);
  43. return new DashboardModel(data, meta);
  44. }
  45. function soloPanelPageScenario(description: string, scenarioFn: (ctx: ScenarioContext) => void) {
  46. describe(description, () => {
  47. let setupFn: () => void;
  48. const ctx: ScenarioContext = {
  49. setup: (fn) => {
  50. setupFn = fn;
  51. },
  52. setDashboard: (overrides?: any, metaOverrides?: any) => {
  53. ctx.dashboard = getTestDashboard(overrides, metaOverrides);
  54. },
  55. setSecondaryDashboard: (overrides?: any, metaOverrides?: any) => {
  56. ctx.secondaryDashboard = getTestDashboard(overrides, metaOverrides);
  57. },
  58. mount: (propOverrides?: Partial<Props>) => {
  59. const props: Props = {
  60. ...getRouteComponentProps({
  61. match: {
  62. params: { slug: 'my-dash', uid: '11' },
  63. } as any,
  64. queryParams: {
  65. panelId: '1',
  66. },
  67. route: { routeName: DashboardRoutes.Normal } as any,
  68. }),
  69. initDashboard: jest.fn(),
  70. dashboard: null,
  71. };
  72. Object.assign(props, propOverrides);
  73. ctx.dashboard = props.dashboard;
  74. let { rerender } = render(<SoloPanelPage {...props} />);
  75. // prop updates will be submitted by rerendering the same component with different props
  76. ctx.rerender = (newProps?: Partial<Props>) => {
  77. Object.assign(props, newProps);
  78. rerender(<SoloPanelPage {...props} />);
  79. };
  80. },
  81. rerender: () => {
  82. // will be replaced while mount() is called
  83. },
  84. };
  85. beforeEach(() => {
  86. setupFn();
  87. });
  88. scenarioFn(ctx);
  89. });
  90. }
  91. describe('SoloPanelPage', () => {
  92. soloPanelPageScenario('Given initial state', (ctx) => {
  93. ctx.setup(() => {
  94. ctx.mount();
  95. });
  96. it('Should render nothing', () => {
  97. expect(screen.queryByText(/Loading/)).not.toBeNull();
  98. });
  99. });
  100. soloPanelPageScenario('Dashboard init completed ', (ctx) => {
  101. ctx.setup(() => {
  102. // Needed for AutoSizer to work in test
  103. Object.defineProperty(HTMLElement.prototype, 'offsetHeight', { configurable: true, value: 500 });
  104. Object.defineProperty(HTMLElement.prototype, 'offsetWidth', { configurable: true, value: 500 });
  105. ctx.mount();
  106. ctx.setDashboard();
  107. expect(ctx.dashboard).not.toBeNull();
  108. // the componentDidMount will change the dashboard prop to the new dashboard
  109. // emulate this by rerendering with new props
  110. ctx.rerender({ dashboard: ctx.dashboard });
  111. });
  112. it('Should render dashboard grid', async () => {
  113. // check if the panel title has arrived in the DashboardPanel mock
  114. expect(screen.queryByText(/My graph/)).not.toBeNull();
  115. });
  116. });
  117. soloPanelPageScenario('When user navigates to other SoloPanelPage', (ctx) => {
  118. ctx.setup(() => {
  119. ctx.mount();
  120. ctx.setDashboard({ uid: 1, panels: [{ id: 1, type: 'graph', title: 'Panel 1' }] });
  121. ctx.setSecondaryDashboard({ uid: 2, panels: [{ id: 1, type: 'graph', title: 'Panel 2' }] });
  122. });
  123. it('Should show other graph', () => {
  124. // check that the title in the DashboardPanel has changed
  125. ctx.rerender({ dashboard: ctx.dashboard });
  126. expect(screen.queryByText(/Panel 1/)).not.toBeNull();
  127. ctx.rerender({ dashboard: ctx.secondaryDashboard });
  128. expect(screen.queryByText(/Panel 1/)).toBeNull();
  129. expect(screen.queryByText(/Panel 2/)).not.toBeNull();
  130. });
  131. });
  132. });