You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

testUtils.tsx 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. import { render as rtlRender, RenderOptions } from '@testing-library/react';
  21. import userEvent from '@testing-library/user-event';
  22. import { Options as UserEventsOptions } from '@testing-library/user-event/dist/types/options';
  23. import { InitialEntry } from 'history';
  24. import { identity, kebabCase } from 'lodash';
  25. import React, { PropsWithChildren, ReactNode } from 'react';
  26. import { HelmetProvider } from 'react-helmet-async';
  27. import { IntlProvider } from 'react-intl';
  28. import { MemoryRouter, Route, Routes } from 'react-router-dom';
  29. export function render(
  30. ui: React.ReactElement,
  31. options?: RenderOptions,
  32. userEventOptions?: UserEventsOptions
  33. ) {
  34. return { ...rtlRender(ui, options), user: userEvent.setup(userEventOptions) };
  35. }
  36. type RenderContextOptions = Omit<RenderOptions, 'wrapper'> & {
  37. initialEntries?: InitialEntry[];
  38. userEventOptions?: UserEventsOptions;
  39. };
  40. export function renderWithContext(
  41. ui: React.ReactElement,
  42. { userEventOptions, ...options }: RenderContextOptions = {}
  43. ) {
  44. return render(ui, { ...options, wrapper: getContextWrapper() }, userEventOptions);
  45. }
  46. type RenderRouterOptions = { additionalRoutes?: ReactNode };
  47. export function renderWithRouter(
  48. ui: React.ReactElement,
  49. options: RenderContextOptions & RenderRouterOptions = {}
  50. ) {
  51. const { additionalRoutes, userEventOptions, ...renderOptions } = options;
  52. function RouterWrapper({ children }: React.PropsWithChildren<{}>) {
  53. return (
  54. <HelmetProvider>
  55. <MemoryRouter>
  56. <Routes>
  57. <Route element={children} path="/" />
  58. {additionalRoutes}
  59. </Routes>
  60. </MemoryRouter>
  61. </HelmetProvider>
  62. );
  63. }
  64. return render(ui, { ...renderOptions, wrapper: RouterWrapper }, userEventOptions);
  65. }
  66. function getContextWrapper() {
  67. return function ContextWrapper({ children }: React.PropsWithChildren<{}>) {
  68. return (
  69. <HelmetProvider>
  70. <IntlProvider defaultLocale="en" locale="en">
  71. {children}
  72. </IntlProvider>
  73. </HelmetProvider>
  74. );
  75. };
  76. }
  77. export function mockComponent(name: string, transformProps: (props: any) => any = identity) {
  78. function MockedComponent({ ...props }: PropsWithChildren<any>) {
  79. return React.createElement('mocked-' + kebabCase(name), transformProps(props));
  80. }
  81. MockedComponent.displayName = `mocked(${name})`;
  82. return MockedComponent;
  83. }
  84. export const debounceTimer = jest.fn().mockImplementation((callback, timeout) => {
  85. let timeoutId: number;
  86. const debounced = jest.fn((...args) => {
  87. window.clearTimeout(timeoutId);
  88. timeoutId = window.setTimeout(() => callback(...args), timeout);
  89. });
  90. (debounced as any).cancel = jest.fn(() => {
  91. window.clearTimeout(timeoutId);
  92. });
  93. return debounced;
  94. });
  95. export function flushPromises(usingFakeTime = false): Promise<void> {
  96. return new Promise((resolve) => {
  97. if (usingFakeTime) {
  98. jest.useRealTimers();
  99. }
  100. setTimeout(resolve, 0);
  101. if (usingFakeTime) {
  102. jest.useFakeTimers();
  103. }
  104. });
  105. }