testHelpers.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import React, { PropsWithChildren, ReactElement, useMemo } from 'react';
  2. import {
  3. MemoryRouter,
  4. MemoryRouterProps,
  5. Route,
  6. Routes,
  7. } from 'react-router-dom';
  8. import fetchMock from 'fetch-mock';
  9. import { Provider } from 'react-redux';
  10. import { ThemeProvider } from 'styled-components';
  11. import { theme } from 'theme/theme';
  12. import {
  13. render,
  14. renderHook,
  15. RenderOptions,
  16. waitFor,
  17. } from '@testing-library/react';
  18. import { AnyAction, Store } from 'redux';
  19. import { RootState } from 'redux/interfaces';
  20. import { configureStore } from '@reduxjs/toolkit';
  21. import rootReducer from 'redux/reducers';
  22. import {
  23. QueryClient,
  24. QueryClientProvider,
  25. UseQueryResult,
  26. } from '@tanstack/react-query';
  27. import { ConfirmContextProvider } from 'components/contexts/ConfirmContext';
  28. import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
  29. import { GlobalSettingsContext } from 'components/contexts/GlobalSettingsContext';
  30. import { UserInfoRolesAccessContext } from 'components/contexts/UserInfoRolesAccessContext';
  31. import { RolesType, modifyRolesData } from './permissions';
  32. interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
  33. preloadedState?: Partial<RootState>;
  34. store?: Store<Partial<RootState>, AnyAction>;
  35. initialEntries?: MemoryRouterProps['initialEntries'];
  36. userInfo?: {
  37. roles?: RolesType;
  38. rbacFlag: boolean;
  39. };
  40. }
  41. interface WithRouteProps {
  42. children: React.ReactNode;
  43. path: string;
  44. }
  45. export const expectQueryWorks = async (
  46. mock: fetchMock.FetchMockStatic,
  47. result: { current: UseQueryResult<unknown, unknown> }
  48. ) => {
  49. await waitFor(() => expect(result.current.isFetched).toBeTruthy());
  50. expect(mock.calls()).toHaveLength(1);
  51. expect(result.current.data).toBeDefined();
  52. };
  53. export const WithRoute: React.FC<WithRouteProps> = ({ children, path }) => {
  54. return (
  55. <Routes>
  56. <Route path={path} element={children} />
  57. </Routes>
  58. );
  59. };
  60. export const TestQueryClientProvider: React.FC<PropsWithChildren<unknown>> = ({
  61. children,
  62. }) => {
  63. // use new QueryClient instance for each test run to avoid issues with cache
  64. const queryClient = new QueryClient({
  65. defaultOptions: { queries: { retry: false } },
  66. });
  67. return (
  68. <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  69. );
  70. };
  71. /**
  72. * @description it will create a UserInfo Provider that will actually
  73. * disable the rbacFlag , to user if you can pass it as an argument
  74. * */
  75. const TestUserInfoProvider: React.FC<
  76. PropsWithChildren<{ data?: { roles?: RolesType; rbacFlag: boolean } }>
  77. > = ({ children, data }) => {
  78. const contextValue = useMemo(() => {
  79. const roles = modifyRolesData(data?.roles);
  80. return {
  81. username: 'test',
  82. rbacFlag: !!(typeof data?.rbacFlag === 'undefined'
  83. ? false
  84. : data?.rbacFlag),
  85. roles,
  86. };
  87. }, [data]);
  88. return (
  89. <UserInfoRolesAccessContext.Provider value={contextValue}>
  90. {children}
  91. </UserInfoRolesAccessContext.Provider>
  92. );
  93. };
  94. const customRender = (
  95. ui: ReactElement,
  96. {
  97. preloadedState,
  98. store = configureStore<RootState>({
  99. reducer: rootReducer,
  100. preloadedState,
  101. }),
  102. initialEntries,
  103. userInfo,
  104. ...renderOptions
  105. }: CustomRenderOptions = {}
  106. ) => {
  107. // overrides @testing-library/react render.
  108. const AllTheProviders: React.FC<PropsWithChildren<unknown>> = ({
  109. children,
  110. }) => (
  111. <TestQueryClientProvider>
  112. <GlobalSettingsContext.Provider value={{ hasDynamicConfig: false }}>
  113. <ThemeProvider theme={theme}>
  114. <TestUserInfoProvider data={userInfo}>
  115. <ConfirmContextProvider>
  116. <Provider store={store}>
  117. <MemoryRouter initialEntries={initialEntries}>
  118. <div>
  119. {children}
  120. <ConfirmationModal />
  121. </div>
  122. </MemoryRouter>
  123. </Provider>
  124. </ConfirmContextProvider>
  125. </TestUserInfoProvider>
  126. </ThemeProvider>
  127. </GlobalSettingsContext.Provider>
  128. </TestQueryClientProvider>
  129. );
  130. return render(ui, { wrapper: AllTheProviders, ...renderOptions });
  131. };
  132. const customRenderHook = (hook: () => UseQueryResult<unknown, unknown>) =>
  133. renderHook(hook, { wrapper: TestQueryClientProvider });
  134. export { customRender as render, customRenderHook as renderQueryHook };
  135. export class EventSourceMock {
  136. url: string;
  137. close: () => void;
  138. open: () => void;
  139. error: () => void;
  140. onmessage: () => void;
  141. constructor(url: string) {
  142. this.url = url;
  143. this.open = jest.fn();
  144. this.error = jest.fn();
  145. this.onmessage = jest.fn();
  146. this.close = jest.fn();
  147. }
  148. }