richie-education 2.25.0-b2.dev148 → 2.25.0-b2.dev152

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/js/contexts/JoanieApiContext/index.spec.tsx +1 -1
  2. package/js/contexts/SessionContext/JoanieSessionProvider.spec.tsx +44 -37
  3. package/js/contexts/SessionContext/index.spec.tsx +42 -21
  4. package/js/contexts/SessionContext/no-authentication.spec.tsx +3 -2
  5. package/js/hooks/useCourseSearchParams/index.spec.tsx +0 -1
  6. package/js/hooks/useUnionResource/index.spec.tsx +11 -9
  7. package/js/utils/test/render.tsx +5 -1
  8. package/js/utils/test/wrappers/BaseAppWrapper.tsx +5 -8
  9. package/js/utils/test/wrappers/BaseJoanieAppWrapper.tsx +4 -7
  10. package/js/utils/test/wrappers/IntlWrapper.tsx +4 -2
  11. package/js/utils/test/wrappers/PresentationalAppWrapper.tsx +1 -1
  12. package/js/utils/test/wrappers/ReactQueryAppWrapper.tsx +16 -0
  13. package/js/widgets/Dashboard/components/DashboardAvatar/index.spec.tsx +8 -5
  14. package/js/widgets/Dashboard/components/DashboardBox/index.spec.tsx +3 -1
  15. package/js/widgets/Dashboard/components/DashboardItem/Certificate/index.spec.tsx +19 -39
  16. package/js/widgets/Dashboard/components/DashboardItem/CertificateStatus/index.spec.tsx +14 -12
  17. package/js/widgets/Dashboard/components/DashboardItem/Contract/index.spec.tsx +5 -43
  18. package/js/widgets/Dashboard/components/DashboardItem/CourseEnrolling/index.spec.tsx +16 -15
  19. package/js/widgets/Dashboard/components/DashboardItem/Enrollment/DashboardItemEnrollment.spec.tsx +8 -18
  20. package/js/widgets/Dashboard/components/DashboardItem/Enrollment/ProductCertificateFooter/index.spec.tsx +19 -51
  21. package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrder.spec.tsx +40 -70
  22. package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrderContract.spec.tsx +31 -32
  23. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateLearnerMessage/index.spec.tsx +19 -31
  24. package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateTeacherMessage/index.spec.tsx +26 -37
  25. package/js/widgets/Dashboard/components/DashboardItem/index.spec.tsx +28 -23
  26. package/js/widgets/Dashboard/components/DashboardLayoutRoute/index.spec.tsx +53 -51
  27. package/js/widgets/Dashboard/components/DashboardSidebar/components/ContractNavLink/index.spec.tsx +24 -49
  28. package/js/widgets/Dashboard/components/DashboardSidebar/components/MenuNavLink/index.spec.tsx +5 -14
  29. package/js/widgets/Dashboard/components/ProtectedOutlet/AuthenticatedOutlet.spec.tsx +62 -54
  30. package/js/widgets/Dashboard/components/ProtectedOutlet/ProtectedOutlet.spec.tsx +67 -42
  31. package/js/widgets/Dashboard/components/RouterButton/index.spec.tsx +12 -14
  32. package/js/widgets/Dashboard/components/TeacherDashboardOrganizationSidebar/index.spec.tsx +14 -39
  33. package/js/widgets/Dashboard/hooks/useDashboardRouter/index.spec.tsx +2 -4
  34. package/js/widgets/Dashboard/hooks/useEnroll/index.spec.tsx +7 -28
  35. package/js/widgets/Dashboard/hooks/useRouteInfo/index.spec.tsx +25 -33
  36. package/js/widgets/Dashboard/index.spec.tsx +49 -43
  37. package/js/widgets/LanguageSelector/index.spec.tsx +7 -7
  38. package/js/widgets/LtiConsumer/index.spec.tsx +46 -48
  39. package/js/widgets/RootSearchSuggestField/index.spec.tsx +8 -6
  40. package/js/widgets/Search/components/PaginateCourseSearch/index.spec.tsx +10 -3
  41. package/js/widgets/Search/components/SearchFilterGroup/index.spec.tsx +5 -3
  42. package/js/widgets/Search/components/SearchFilterGroupModal/index.spec.tsx +8 -4
  43. package/js/widgets/Search/components/SearchFilterValueLeaf/index.spec.tsx +7 -3
  44. package/js/widgets/Search/components/SearchFilterValueParent/index.spec.tsx +12 -7
  45. package/js/widgets/Search/components/SearchFiltersPane/index.spec.tsx +5 -1
  46. package/js/widgets/Search/hooks/useCourseSearch/index.spec.tsx +4 -12
  47. package/js/widgets/Search/hooks/useFilterValue/index.spec.tsx +0 -2
  48. package/js/widgets/Search/index.spec.tsx +14 -6
  49. package/js/widgets/SearchSuggestField/index.spec.tsx +14 -1
  50. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCertificateItem/index.spec.tsx +16 -31
  51. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCourseRuns/index.spec.tsx +46 -72
  52. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseRunItem/index.spec.tsx +5 -2
  53. package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.spec.tsx +147 -162
  54. package/js/widgets/SyllabusCourseRunsList/components/CourseRunEnrollment/CourseRunUnenrollmentButton/index.spec.tsx +6 -4
  55. package/js/widgets/SyllabusCourseRunsList/components/CourseRunEnrollment/index.joanie.spec.tsx +22 -99
  56. package/js/widgets/SyllabusCourseRunsList/components/CourseRunEnrollment/index.openedx.spec.tsx +27 -83
  57. package/js/widgets/SyllabusCourseRunsList/components/CourseRunItem/index.spec.tsx +4 -1
  58. package/js/widgets/SyllabusCourseRunsList/components/CourseRunItemWithEnrollment/index.spec.tsx +28 -35
  59. package/js/widgets/SyllabusCourseRunsList/components/CourseWishButton/hooks/useCourseWish/index.spec.tsx +9 -28
  60. package/js/widgets/SyllabusCourseRunsList/components/CourseWishButton/index.login.spec.tsx +23 -48
  61. package/js/widgets/SyllabusCourseRunsList/components/CourseWishButton/index.logout.spec.tsx +20 -29
  62. package/js/widgets/SyllabusCourseRunsList/components/SyllabusSimpleCourseRunsList/index.spec.tsx +9 -4
  63. package/js/widgets/SyllabusCourseRunsList/hooks/useCourseEnrollment/index.spec.tsx +8 -10
  64. package/js/widgets/SyllabusCourseRunsList/index.spec.tsx +28 -39
  65. package/js/widgets/UserLogin/components/UserMenu/index.spec.tsx +9 -6
  66. package/js/widgets/UserLogin/index.not.isJoanieEnabled.spec.tsx +21 -32
  67. package/js/widgets/UserLogin/index.spec.tsx +15 -37
  68. package/js/widgets/index.spec.tsx +12 -17
  69. package/package.json +1 -1
@@ -1,6 +1,8 @@
1
- import { render, screen } from '@testing-library/react';
2
- import { IntlProvider } from 'react-intl';
1
+ import { screen } from '@testing-library/react';
3
2
  import { userEvent } from '@storybook/testing-library';
3
+ import { PropsWithChildren } from 'react';
4
+ import { render } from 'utils/test/render';
5
+ import { IntlWrapper } from 'utils/test/wrappers/IntlWrapper';
4
6
  import { DashboardSubItemsList } from './DashboardSubItemsList';
5
7
  import { DashboardSubItem } from './DashboardSubItem';
6
8
  import { DashboardItem, DEMO_IMAGE_URL } from '.';
@@ -14,6 +16,7 @@ describe('<DashboardItem />', () => {
14
16
  imageUrl={DEMO_IMAGE_URL}
15
17
  footer="Hi, i'm the footer"
16
18
  />,
19
+ { wrapper: null },
17
20
  );
18
21
 
19
22
  expect(screen.getByText('Become a React pro')).toBeInTheDocument();
@@ -34,6 +37,7 @@ describe('<DashboardItem />', () => {
34
37
  footer="Hi, i'm the footer"
35
38
  mode="compact"
36
39
  />,
40
+ { wrapper: null },
37
41
  );
38
42
 
39
43
  expect(screen.getByText("Hi, i'm the footer")).toBeInTheDocument();
@@ -54,6 +58,7 @@ describe('<DashboardItem />', () => {
54
58
  ]}
55
59
  />
56
60
  </DashboardItem>,
61
+ { wrapper: null },
57
62
  );
58
63
 
59
64
  screen.getByText('Sub 1');
@@ -63,27 +68,27 @@ describe('<DashboardItem />', () => {
63
68
 
64
69
  it('renders a DashboardItem with more dropdown', async () => {
65
70
  render(
66
- <IntlProvider locale="en">
67
- <DashboardItem
68
- title="Become a React pro"
69
- code="Ref. 123"
70
- imageUrl={DEMO_IMAGE_URL}
71
- more={
72
- <>
73
- <li>
74
- <div className="selector__list__link">Copy</div>
75
- </li>
76
- <li>
77
- <div className="selector__list__link">Duplicate</div>
78
- </li>
79
- <li>
80
- <div className="selector__list__link">Delete</div>
81
- </li>
82
- </>
83
- }
84
- />
85
- ,
86
- </IntlProvider>,
71
+ <DashboardItem
72
+ title="Become a React pro"
73
+ code="Ref. 123"
74
+ imageUrl={DEMO_IMAGE_URL}
75
+ more={
76
+ <>
77
+ <li>
78
+ <div className="selector__list__link">Copy</div>
79
+ </li>
80
+ <li>
81
+ <div className="selector__list__link">Duplicate</div>
82
+ </li>
83
+ <li>
84
+ <div className="selector__list__link">Delete</div>
85
+ </li>
86
+ </>
87
+ }
88
+ />,
89
+ {
90
+ wrapper: ({ children }: PropsWithChildren) => <IntlWrapper>{children}</IntlWrapper>,
91
+ },
87
92
  );
88
93
 
89
94
  expect(screen.queryByText('Copy')).not.toBeInTheDocument();
@@ -1,13 +1,9 @@
1
- import { createMemoryRouter, RouterProvider } from 'react-router-dom';
2
- import { render, screen } from '@testing-library/react';
3
- import { IntlProvider } from 'react-intl';
4
- import { QueryClientProvider } from '@tanstack/react-query';
5
- import {
6
- RichieContextFactory as mockRichieContextFactory,
7
- UserFactory,
8
- } from 'utils/test/factories/richie';
9
- import { createTestQueryClient } from 'utils/test/createTestQueryClient';
10
- import JoanieSessionProvider from 'contexts/SessionContext/JoanieSessionProvider';
1
+ import { screen } from '@testing-library/react';
2
+ import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
3
+ import { render } from 'utils/test/render';
4
+ import { RouterWrapper } from 'utils/test/wrappers/RouterWrapper';
5
+ import { BaseJoanieAppWrapper } from 'utils/test/wrappers/BaseJoanieAppWrapper';
6
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
11
7
  import { DashboardLayoutRoute } from '.';
12
8
 
13
9
  jest.mock('utils/context', () => ({
@@ -18,56 +14,62 @@ jest.mock('utils/context', () => ({
18
14
  }).one(),
19
15
  }));
20
16
 
21
- const renderDashboardLayoutRoute = ({ renderLayout }: { renderLayout: boolean }) => {
22
- const user = UserFactory().one();
23
- const routes = [
24
- {
25
- path: '/',
26
- children: [
27
- {
28
- path: '/dashboard',
29
- handle: {
30
- renderLayout: false,
31
- },
32
- element: <DashboardLayoutRoute />,
33
- children: [
34
- {
35
- path: '/dashboard/page',
36
- handle: {
37
- renderLayout,
38
- },
39
- element: (
40
- <div>
41
- <h1>Awesome page title</h1>
42
- </div>
43
- ),
44
- },
45
- ],
17
+ const getRoutes = ({ renderLayout }: { renderLayout: boolean }) => [
18
+ {
19
+ path: '/',
20
+ children: [
21
+ {
22
+ path: '/dashboard',
23
+ handle: {
24
+ renderLayout: false,
46
25
  },
47
- ],
48
- },
49
- ];
50
- const router = createMemoryRouter(routes, { initialEntries: ['/dashboard/page'] });
51
- return render(
52
- <IntlProvider locale="en">
53
- <QueryClientProvider client={createTestQueryClient({ user })}>
54
- <JoanieSessionProvider>
55
- <RouterProvider router={router} />
56
- </JoanieSessionProvider>
57
- </QueryClientProvider>
58
- </IntlProvider>,
59
- );
60
- };
26
+ element: <DashboardLayoutRoute />,
27
+ children: [
28
+ {
29
+ path: '/dashboard/page',
30
+ handle: {
31
+ renderLayout,
32
+ },
33
+ element: (
34
+ <div>
35
+ <h1>Awesome page title</h1>
36
+ </div>
37
+ ),
38
+ },
39
+ ],
40
+ },
41
+ ],
42
+ },
43
+ ];
61
44
 
62
45
  describe('<DashboardLayoutRoute/>', () => {
46
+ setupJoanieSession();
47
+
63
48
  it('should display DashboardLayout', async () => {
64
- renderDashboardLayoutRoute({ renderLayout: false });
49
+ render(
50
+ <RouterWrapper
51
+ initialEntries={['/dashboard/page']}
52
+ routes={getRoutes({ renderLayout: false })}
53
+ />,
54
+ {
55
+ wrapper: BaseJoanieAppWrapper,
56
+ },
57
+ );
58
+
65
59
  expect(await screen.findByRole('heading', { name: 'Awesome page title' })).toBeInTheDocument();
66
60
  expect(screen.queryByTestId('location-display-/dashboard/page')).toBeInTheDocument();
67
61
  });
68
62
 
69
63
  it('should not display DashboardLayout', async () => {
70
- renderDashboardLayoutRoute({ renderLayout: true });
64
+ render(
65
+ <RouterWrapper
66
+ initialEntries={['/dashboard/page']}
67
+ routes={getRoutes({ renderLayout: true })}
68
+ />,
69
+ {
70
+ wrapper: BaseJoanieAppWrapper,
71
+ },
72
+ );
71
73
  expect(await screen.findByRole('heading', { name: 'Awesome page title' })).toBeInTheDocument();
72
74
  expect(screen.queryByTestId('location-display-/dashboard/page')).not.toBeInTheDocument();
73
75
  });
@@ -1,18 +1,14 @@
1
- import { render, screen } from '@testing-library/react';
2
- import { PropsWithChildren } from 'react';
3
- import { MemoryRouter } from 'react-router-dom';
4
- import { QueryClientProvider } from '@tanstack/react-query';
5
- import { IntlProvider } from 'react-intl';
1
+ import { screen } from '@testing-library/react';
6
2
  import fetchMock from 'fetch-mock';
7
3
  import { faker } from '@faker-js/faker';
8
4
  import queryString from 'query-string';
9
5
  import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
10
- import JoanieSessionProvider from 'contexts/SessionContext/JoanieSessionProvider';
11
- import { createTestQueryClient } from 'utils/test/createTestQueryClient';
12
6
  import { PER_PAGE } from 'settings';
13
7
  import { ContractResourceQuery, ContractState } from 'types/Joanie';
14
8
  import { ContractFactory } from 'utils/test/factories/joanie';
15
9
  import { ContractActions } from 'utils/AbilitiesHelper/types';
10
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
11
+ import { render } from 'utils/test/render';
16
12
  import { MenuLink } from '../..';
17
13
  import ContractNavLink from '.';
18
14
 
@@ -25,25 +21,11 @@ jest.mock('utils/context', () => ({
25
21
  }));
26
22
 
27
23
  describe('<ContractNavLink />', () => {
28
- const Wrapper = ({ children }: PropsWithChildren) => (
29
- <QueryClientProvider client={createTestQueryClient({ user: true })}>
30
- <IntlProvider locale="en">
31
- <JoanieSessionProvider>
32
- <MemoryRouter>{children}</MemoryRouter>
33
- </JoanieSessionProvider>
34
- </IntlProvider>
35
- </QueryClientProvider>
36
- );
24
+ setupJoanieSession();
37
25
 
38
26
  beforeEach(() => {
39
- // JoanieSessionProvider queries
40
- fetchMock.get('https://joanie.endpoint/api/v1.0/addresses/', []);
41
- fetchMock.get('https://joanie.endpoint/api/v1.0/orders/', []);
42
- fetchMock.get('https://joanie.endpoint/api/v1.0/credit-cards/', []);
43
- });
44
-
45
- afterEach(() => {
46
- fetchMock.restore();
27
+ // useDefaultOrganization hook request organization list
28
+ fetchMock.get('https://joanie.endpoint/api/v1.0/organizations/', []);
47
29
  });
48
30
 
49
31
  it('should render a ContractNavLink with route and label when neither organizationId and courseProductRelationId are given', () => {
@@ -52,11 +34,7 @@ describe('<ContractNavLink />', () => {
52
34
  label: 'My contract navigation link',
53
35
  };
54
36
 
55
- render(
56
- <Wrapper>
57
- <ContractNavLink link={link} />
58
- </Wrapper>,
59
- );
37
+ render(<ContractNavLink link={link} />);
60
38
 
61
39
  expect(screen.getByRole('link', { name: 'My contract navigation link' })).toBeInTheDocument();
62
40
  expect(screen.queryByTestId('badge')).not.toBeInTheDocument();
@@ -108,17 +86,16 @@ describe('<ContractNavLink />', () => {
108
86
  results: [ContractFactory({ abilities: contractAbilities }).one()],
109
87
  },
110
88
  );
89
+
111
90
  render(
112
- <Wrapper>
113
- <ContractNavLink
114
- link={{
115
- to: '/dummy/url/',
116
- label: 'My contract navigation link',
117
- }}
118
- organizationId={organizationId}
119
- courseProductRelationId={courseProductRelationId}
120
- />
121
- </Wrapper>,
91
+ <ContractNavLink
92
+ link={{
93
+ to: '/dummy/url/',
94
+ label: 'My contract navigation link',
95
+ }}
96
+ organizationId={organizationId}
97
+ courseProductRelationId={courseProductRelationId}
98
+ />,
122
99
  );
123
100
 
124
101
  expect(
@@ -216,16 +193,14 @@ describe('<ContractNavLink />', () => {
216
193
  },
217
194
  );
218
195
  render(
219
- <Wrapper>
220
- <ContractNavLink
221
- link={{
222
- to: '/dummy/url/',
223
- label: 'My contract navigation link',
224
- }}
225
- organizationId={organizationId}
226
- courseProductRelationId={courseProductRelationId}
227
- />
228
- </Wrapper>,
196
+ <ContractNavLink
197
+ link={{
198
+ to: '/dummy/url/',
199
+ label: 'My contract navigation link',
200
+ }}
201
+ organizationId={organizationId}
202
+ courseProductRelationId={courseProductRelationId}
203
+ />,
229
204
  );
230
205
 
231
206
  expect(
@@ -1,22 +1,17 @@
1
- import { render, screen } from '@testing-library/react';
2
- import { PropsWithChildren } from 'react';
3
- import { MemoryRouter } from 'react-router-dom';
1
+ import { screen } from '@testing-library/react';
2
+ import { render } from 'utils/test/render';
3
+ import { RouterWrapper } from 'utils/test/wrappers/RouterWrapper';
4
4
  import { MenuLink } from '../..';
5
5
  import MenuNavLink from '.';
6
6
 
7
7
  describe('<MenuNavLink />', () => {
8
- const Wrapper = ({ children }: PropsWithChildren) => <MemoryRouter>{children} </MemoryRouter>;
9
8
  it('should render a MenuNavLink with route and label', () => {
10
9
  const link: MenuLink = {
11
10
  to: '/dummy/url/',
12
11
  label: 'My navigation link',
13
12
  };
14
13
 
15
- render(
16
- <Wrapper>
17
- <MenuNavLink link={link} />
18
- </Wrapper>,
19
- );
14
+ render(<MenuNavLink link={link} />, { wrapper: RouterWrapper });
20
15
 
21
16
  expect(screen.getByRole('link', { name: 'My navigation link' })).toBeInTheDocument();
22
17
  expect(screen.queryByTestId('badge')).not.toBeInTheDocument();
@@ -28,11 +23,7 @@ describe('<MenuNavLink />', () => {
28
23
  label: 'My navigation link',
29
24
  };
30
25
 
31
- render(
32
- <Wrapper>
33
- <MenuNavLink link={link} badgeCount={999} />
34
- </Wrapper>,
35
- );
26
+ render(<MenuNavLink link={link} badgeCount={999} />, { wrapper: RouterWrapper });
36
27
 
37
28
  expect(screen.getByRole('link', { name: 'My navigation link' })).toBeInTheDocument();
38
29
  expect(screen.getByText('999')).toBeInTheDocument();
@@ -1,10 +1,10 @@
1
- import { render, screen } from '@testing-library/react';
2
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
- import { createMemoryRouter, RouterProvider } from 'react-router-dom';
1
+ import { screen } from '@testing-library/react';
4
2
  import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
5
- import BaseSessionProvider from 'contexts/SessionContext/BaseSessionProvider';
6
3
  import { location } from 'utils/indirection/window';
7
4
  import { createTestQueryClient } from 'utils/test/createTestQueryClient';
5
+ import { render } from 'utils/test/render';
6
+ import { BaseAppWrapper } from 'utils/test/wrappers/BaseAppWrapper';
7
+ import { RouterWrapper } from 'utils/test/wrappers/RouterWrapper';
8
8
  import AuthenticatedOutlet from './AuthenticatedOutlet';
9
9
 
10
10
  jest.mock('utils/context', () => ({
@@ -19,58 +19,32 @@ jest.mock('utils/indirection/window', () => ({
19
19
  }));
20
20
 
21
21
  describe('<AuthenticatedOutlet />', () => {
22
- const AuthenticatedRouter = ({
23
- redirectTo,
24
- client,
25
- ...routerOptions
26
- }: {
27
- redirectTo?: string;
28
- client: QueryClient;
29
- [key: PropertyKey]: any;
30
- }) => {
31
- const routes = [
32
- {
33
- path: '/',
34
- element: <AuthenticatedOutlet redirectTo="/forbidden" />,
35
- children: [
36
- {
37
- path: '/restricted',
38
- element: <div data-testid="route-restricted" />,
39
- },
40
- ],
41
- },
42
- {
43
- path: '*',
44
- element: <div data-testid="route-forbidden" />,
45
- },
46
- ];
47
-
48
- const router = createMemoryRouter(routes, { ...routerOptions });
49
-
50
- return (
51
- <QueryClientProvider client={client}>
52
- <BaseSessionProvider>
53
- <RouterProvider router={router} />
54
- </BaseSessionProvider>
55
- </QueryClientProvider>
56
- );
57
- };
58
-
59
- beforeEach(() => {
60
- jest.resetAllMocks();
61
- });
62
-
63
- it('should display child route if user is authenticated', () => {
22
+ it('should display child route if user is authenticated', async () => {
64
23
  render(
65
- <AuthenticatedRouter
66
- client={createTestQueryClient({ user: true })}
67
- redirectTo="/forbidden"
24
+ <RouterWrapper
68
25
  initialEntries={['/restricted']}
26
+ routes={[
27
+ {
28
+ path: '/',
29
+ element: <AuthenticatedOutlet redirectTo="/forbidden" />,
30
+ children: [
31
+ {
32
+ path: '/restricted',
33
+ element: <div data-testid="route-restricted" />,
34
+ },
35
+ ],
36
+ },
37
+ {
38
+ path: '*',
39
+ element: <div data-testid="route-forbidden" />,
40
+ },
41
+ ]}
69
42
  />,
43
+ { wrapper: BaseAppWrapper },
70
44
  );
71
45
 
72
46
  // The restricted route should be rendered
73
- screen.getByTestId('route-restricted');
47
+ await screen.findByTestId('route-restricted');
74
48
 
75
49
  // location.replace should not have been called
76
50
  expect(location.replace).not.toBeCalled();
@@ -78,11 +52,26 @@ describe('<AuthenticatedOutlet />', () => {
78
52
 
79
53
  it('should redirect to provided path if user is anonymous', () => {
80
54
  render(
81
- <AuthenticatedRouter
82
- client={createTestQueryClient()}
83
- redirectTo="/forbidden"
55
+ <RouterWrapper
84
56
  initialEntries={['/restricted']}
57
+ routes={[
58
+ {
59
+ path: '/',
60
+ element: <AuthenticatedOutlet redirectTo="/forbidden" />,
61
+ children: [
62
+ {
63
+ path: '/restricted',
64
+ element: <div data-testid="route-restricted" />,
65
+ },
66
+ ],
67
+ },
68
+ {
69
+ path: '*',
70
+ element: <div data-testid="route-forbidden" />,
71
+ },
72
+ ]}
85
73
  />,
74
+ { wrapper: BaseAppWrapper, queryOptions: { client: createTestQueryClient() } },
86
75
  );
87
76
 
88
77
  // The restricted route should not be rendered
@@ -94,7 +83,26 @@ describe('<AuthenticatedOutlet />', () => {
94
83
 
95
84
  it('should redirect to "/" if user is anonymous and no redirect path is provided', () => {
96
85
  render(
97
- <AuthenticatedRouter client={createTestQueryClient()} initialEntries={['/restricted']} />,
86
+ <RouterWrapper
87
+ initialEntries={['/restricted']}
88
+ routes={[
89
+ {
90
+ path: '/',
91
+ element: <AuthenticatedOutlet redirectTo="/forbidden" />,
92
+ children: [
93
+ {
94
+ path: '/restricted',
95
+ element: <div data-testid="route-restricted" />,
96
+ },
97
+ ],
98
+ },
99
+ {
100
+ path: '*',
101
+ element: <div data-testid="route-forbidden" />,
102
+ },
103
+ ]}
104
+ />,
105
+ { wrapper: BaseAppWrapper, queryOptions: { client: createTestQueryClient() } },
98
106
  );
99
107
 
100
108
  // The restricted route should not be rendered
@@ -1,6 +1,7 @@
1
- import { screen, render } from '@testing-library/react';
2
- import { createMemoryRouter, RouterProvider } from 'react-router-dom';
1
+ import { screen } from '@testing-library/react';
3
2
  import { location } from 'utils/indirection/window';
3
+ import { render } from 'utils/test/render';
4
+ import { RouterWrapper } from 'utils/test/wrappers/RouterWrapper';
4
5
  import ProtectedOutlet from './ProtectedOutlet';
5
6
 
6
7
  jest.mock('utils/indirection/window', () => ({
@@ -10,45 +11,28 @@ jest.mock('utils/indirection/window', () => ({
10
11
  }));
11
12
 
12
13
  describe('<ProtectedOutlet />', () => {
13
- const ProtectedRouter = ({
14
- isAllowed,
15
- redirectTo,
16
- ...routerOptions
17
- }: {
18
- isAllowed: Boolean;
19
- redirectTo?: string;
20
- [key: PropertyKey]: any;
21
- }) => {
22
- const router = createMemoryRouter(
23
- [
24
- {
25
- path: '/',
26
- element: <ProtectedOutlet isAllowed={isAllowed} redirectTo={redirectTo} />,
27
- children: [
28
- {
29
- path: '/restricted',
30
- element: <div data-testid="route-restricted" />,
31
- },
32
- ],
33
- },
34
- {
35
- path: '*',
36
- element: <div data-testid="route-forbidden" />,
37
- },
38
- ],
39
- { ...routerOptions },
40
- );
41
-
42
- return <RouterProvider router={router} />;
43
- };
44
-
45
- beforeEach(() => {
46
- jest.resetAllMocks();
47
- });
48
-
49
14
  it('should display child route if isAllowed is true', () => {
50
15
  render(
51
- <ProtectedRouter isAllowed={true} redirectTo="/forbidden" initialEntries={['/restricted']} />,
16
+ <RouterWrapper
17
+ initialEntries={['/restricted']}
18
+ routes={[
19
+ {
20
+ path: '/',
21
+ element: <ProtectedOutlet isAllowed={true} redirectTo="/forbidden" />,
22
+ children: [
23
+ {
24
+ path: '/restricted',
25
+ element: <div data-testid="route-restricted" />,
26
+ },
27
+ ],
28
+ },
29
+ {
30
+ path: '*',
31
+ element: <div data-testid="route-forbidden" />,
32
+ },
33
+ ]}
34
+ />,
35
+ { wrapper: null },
52
36
  );
53
37
 
54
38
  // The restricted route should be rendered
@@ -59,8 +43,28 @@ describe('<ProtectedOutlet />', () => {
59
43
  });
60
44
 
61
45
  it('should redirect to provided path if isAllowed is false', () => {
62
- render(<ProtectedRouter isAllowed={false} redirectTo="/forbidden" initialEntries={['/']} />);
63
-
46
+ render(
47
+ <RouterWrapper
48
+ initialEntries={['/']}
49
+ routes={[
50
+ {
51
+ path: '/',
52
+ element: <ProtectedOutlet isAllowed={false} redirectTo="/forbidden" />,
53
+ children: [
54
+ {
55
+ path: '/restricted',
56
+ element: <div data-testid="route-restricted" />,
57
+ },
58
+ ],
59
+ },
60
+ {
61
+ path: '*',
62
+ element: <div data-testid="route-forbidden" />,
63
+ },
64
+ ]}
65
+ />,
66
+ { wrapper: null },
67
+ );
64
68
  // The restricted route should not be rendered
65
69
  expect(screen.queryByTestId('route-restricted')).toBeNull();
66
70
 
@@ -69,7 +73,28 @@ describe('<ProtectedOutlet />', () => {
69
73
  });
70
74
 
71
75
  it('should redirect to "/" if isAllowed is false and no redirect path is provided', () => {
72
- render(<ProtectedRouter isAllowed={false} initialEntries={['/']} />);
76
+ render(
77
+ <RouterWrapper
78
+ initialEntries={['/']}
79
+ routes={[
80
+ {
81
+ path: '/',
82
+ element: <ProtectedOutlet isAllowed={false} />,
83
+ children: [
84
+ {
85
+ path: '/restricted',
86
+ element: <div data-testid="route-restricted" />,
87
+ },
88
+ ],
89
+ },
90
+ {
91
+ path: '*',
92
+ element: <div data-testid="route-forbidden" />,
93
+ },
94
+ ]}
95
+ />,
96
+ { wrapper: null },
97
+ );
73
98
 
74
99
  // The restricted route should not be rendered
75
100
  expect(screen.queryByTestId('route-restricted')).toBeNull();