VersionsSettings.test.tsx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import { within } from '@testing-library/dom';
  2. import { render, screen, waitFor } from '@testing-library/react';
  3. import userEvent from '@testing-library/user-event';
  4. import { UserEvent } from '@testing-library/user-event/dist/types/setup';
  5. import React from 'react';
  6. import { historySrv } from '../VersionHistory/HistorySrv';
  7. import { VersionsSettings, VERSIONS_FETCH_LIMIT } from './VersionsSettings';
  8. import { versions, diffs } from './__mocks__/versions';
  9. jest.mock('../VersionHistory/HistorySrv');
  10. const queryByFullText = (text: string) =>
  11. screen.queryByText((_, node: Element | undefined | null) => {
  12. if (node) {
  13. const nodeHasText = (node: HTMLElement | Element) => node.textContent?.includes(text);
  14. const currentNodeHasText = nodeHasText(node);
  15. const childrenDontHaveText = Array.from(node.children).every((child) => !nodeHasText(child));
  16. return Boolean(currentNodeHasText && childrenDontHaveText);
  17. }
  18. return false;
  19. });
  20. describe('VersionSettings', () => {
  21. const dashboard: any = {
  22. id: 74,
  23. version: 11,
  24. formatDate: jest.fn(() => 'date'),
  25. getRelativeTime: jest.fn(() => 'time ago'),
  26. };
  27. let user: UserEvent;
  28. beforeEach(() => {
  29. // Need to use delay: null here to work with fakeTimers
  30. // see https://github.com/testing-library/user-event/issues/833
  31. user = userEvent.setup({ delay: null });
  32. jest.resetAllMocks();
  33. jest.useFakeTimers();
  34. });
  35. afterEach(() => {
  36. jest.useRealTimers();
  37. });
  38. test('renders a header and a loading indicator followed by results in a table', async () => {
  39. // @ts-ignore
  40. historySrv.getHistoryList.mockResolvedValue(versions);
  41. render(<VersionsSettings dashboard={dashboard} />);
  42. expect(screen.getByRole('heading', { name: /versions/i })).toBeInTheDocument();
  43. expect(screen.queryByText(/fetching history list/i)).toBeInTheDocument();
  44. await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
  45. const tableBodyRows = within(screen.getAllByRole('rowgroup')[1]).getAllByRole('row');
  46. expect(tableBodyRows.length).toBe(versions.length);
  47. const firstRow = within(screen.getAllByRole('rowgroup')[1]).getAllByRole('row')[0];
  48. expect(within(firstRow).getByText(/latest/i)).toBeInTheDocument();
  49. expect(within(screen.getByRole('table')).getAllByText(/latest/i)).toHaveLength(1);
  50. });
  51. test('does not render buttons if versions === 1', async () => {
  52. // @ts-ignore
  53. historySrv.getHistoryList.mockResolvedValue(versions.slice(0, 1));
  54. render(<VersionsSettings dashboard={dashboard} />);
  55. expect(screen.queryByRole('button', { name: /show more versions/i })).not.toBeInTheDocument();
  56. expect(screen.queryByRole('button', { name: /compare versions/i })).not.toBeInTheDocument();
  57. await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
  58. expect(screen.queryByRole('button', { name: /show more versions/i })).not.toBeInTheDocument();
  59. expect(screen.queryByRole('button', { name: /compare versions/i })).not.toBeInTheDocument();
  60. });
  61. test('does not render show more button if versions < VERSIONS_FETCH_LIMIT', async () => {
  62. // @ts-ignore
  63. historySrv.getHistoryList.mockResolvedValue(versions.slice(0, VERSIONS_FETCH_LIMIT - 5));
  64. render(<VersionsSettings dashboard={dashboard} />);
  65. expect(screen.queryByRole('button', { name: /show more versions|/i })).not.toBeInTheDocument();
  66. expect(screen.queryByRole('button', { name: /compare versions/i })).not.toBeInTheDocument();
  67. await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
  68. expect(screen.queryByRole('button', { name: /show more versions/i })).not.toBeInTheDocument();
  69. expect(screen.queryByRole('button', { name: /compare versions/i })).toBeInTheDocument();
  70. });
  71. test('renders buttons if versions >= VERSIONS_FETCH_LIMIT', async () => {
  72. // @ts-ignore
  73. historySrv.getHistoryList.mockResolvedValue(versions.slice(0, VERSIONS_FETCH_LIMIT));
  74. render(<VersionsSettings dashboard={dashboard} />);
  75. expect(screen.queryByRole('button', { name: /show more versions/i })).not.toBeInTheDocument();
  76. expect(screen.queryByRole('button', { name: /compare versions/i })).not.toBeInTheDocument();
  77. await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
  78. const compareButton = screen.getByRole('button', { name: /compare versions/i });
  79. const showMoreButton = screen.getByRole('button', { name: /show more versions/i });
  80. expect(showMoreButton).toBeInTheDocument();
  81. expect(showMoreButton).toBeEnabled();
  82. expect(compareButton).toBeInTheDocument();
  83. expect(compareButton).toBeDisabled();
  84. });
  85. test('clicking show more appends results to the table', async () => {
  86. historySrv.getHistoryList
  87. // @ts-ignore
  88. .mockImplementationOnce(() => Promise.resolve(versions.slice(0, VERSIONS_FETCH_LIMIT)))
  89. .mockImplementationOnce(
  90. () => new Promise((resolve) => setTimeout(() => resolve(versions.slice(VERSIONS_FETCH_LIMIT)), 1000))
  91. );
  92. render(<VersionsSettings dashboard={dashboard} />);
  93. expect(historySrv.getHistoryList).toBeCalledTimes(1);
  94. await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
  95. expect(within(screen.getAllByRole('rowgroup')[1]).getAllByRole('row').length).toBe(VERSIONS_FETCH_LIMIT);
  96. const showMoreButton = screen.getByRole('button', { name: /show more versions/i });
  97. await user.click(showMoreButton);
  98. expect(historySrv.getHistoryList).toBeCalledTimes(2);
  99. expect(screen.getByText(/Fetching more entries/i)).toBeInTheDocument();
  100. jest.advanceTimersByTime(1000);
  101. await waitFor(() => {
  102. expect(screen.queryByText(/Fetching more entries/i)).not.toBeInTheDocument();
  103. expect(within(screen.getAllByRole('rowgroup')[1]).getAllByRole('row').length).toBe(versions.length);
  104. });
  105. });
  106. test('selecting two versions and clicking compare button should render compare view', async () => {
  107. // @ts-ignore
  108. historySrv.getHistoryList.mockResolvedValue(versions.slice(0, VERSIONS_FETCH_LIMIT));
  109. historySrv.getDashboardVersion
  110. // @ts-ignore
  111. .mockImplementationOnce(() => Promise.resolve(diffs.lhs))
  112. .mockImplementationOnce(() => Promise.resolve(diffs.rhs));
  113. render(<VersionsSettings dashboard={dashboard} />);
  114. expect(historySrv.getHistoryList).toBeCalledTimes(1);
  115. await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
  116. const compareButton = screen.getByRole('button', { name: /compare versions/i });
  117. const tableBody = screen.getAllByRole('rowgroup')[1];
  118. await user.click(within(tableBody).getAllByRole('checkbox')[0]);
  119. await user.click(within(tableBody).getAllByRole('checkbox')[VERSIONS_FETCH_LIMIT - 1]);
  120. expect(compareButton).toBeEnabled();
  121. await user.click(compareButton);
  122. await waitFor(() => expect(screen.getByRole('heading', { name: /versions comparing 2 11/i })).toBeInTheDocument());
  123. expect(queryByFullText('Version 11 updated by admin')).toBeInTheDocument();
  124. expect(queryByFullText('Version 2 updated by admin')).toBeInTheDocument();
  125. expect(screen.queryByRole('button', { name: /restore to version 2/i })).toBeInTheDocument();
  126. expect(screen.queryAllByTestId('diffGroup').length).toBe(5);
  127. const diffGroups = screen.getAllByTestId('diffGroup');
  128. expect(queryByFullText('description added The dashboard description')).toBeInTheDocument();
  129. expect(queryByFullText('panels changed')).toBeInTheDocument();
  130. expect(within(diffGroups[1]).queryByRole('list')).toBeInTheDocument();
  131. expect(within(diffGroups[1]).queryByText(/added title/i)).toBeInTheDocument();
  132. expect(within(diffGroups[1]).queryByText(/changed id/i)).toBeInTheDocument();
  133. expect(queryByFullText('tags deleted item 0')).toBeInTheDocument();
  134. expect(queryByFullText('timepicker added 1 refresh_intervals')).toBeInTheDocument();
  135. expect(queryByFullText('version changed')).toBeInTheDocument();
  136. expect(screen.queryByText(/view json diff/i)).toBeInTheDocument();
  137. await user.click(screen.getByText(/view json diff/i));
  138. await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
  139. });
  140. });