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.
- package/js/contexts/JoanieApiContext/index.spec.tsx +1 -1
- package/js/contexts/SessionContext/JoanieSessionProvider.spec.tsx +44 -37
- package/js/contexts/SessionContext/index.spec.tsx +42 -21
- package/js/contexts/SessionContext/no-authentication.spec.tsx +3 -2
- package/js/hooks/useCourseSearchParams/index.spec.tsx +0 -1
- package/js/hooks/useUnionResource/index.spec.tsx +11 -9
- package/js/utils/test/render.tsx +5 -1
- package/js/utils/test/wrappers/BaseAppWrapper.tsx +5 -8
- package/js/utils/test/wrappers/BaseJoanieAppWrapper.tsx +4 -7
- package/js/utils/test/wrappers/IntlWrapper.tsx +4 -2
- package/js/utils/test/wrappers/PresentationalAppWrapper.tsx +1 -1
- package/js/utils/test/wrappers/ReactQueryAppWrapper.tsx +16 -0
- package/js/widgets/Dashboard/components/DashboardAvatar/index.spec.tsx +8 -5
- package/js/widgets/Dashboard/components/DashboardBox/index.spec.tsx +3 -1
- package/js/widgets/Dashboard/components/DashboardItem/Certificate/index.spec.tsx +19 -39
- package/js/widgets/Dashboard/components/DashboardItem/CertificateStatus/index.spec.tsx +14 -12
- package/js/widgets/Dashboard/components/DashboardItem/Contract/index.spec.tsx +5 -43
- package/js/widgets/Dashboard/components/DashboardItem/CourseEnrolling/index.spec.tsx +16 -15
- package/js/widgets/Dashboard/components/DashboardItem/Enrollment/DashboardItemEnrollment.spec.tsx +8 -18
- package/js/widgets/Dashboard/components/DashboardItem/Enrollment/ProductCertificateFooter/index.spec.tsx +19 -51
- package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrder.spec.tsx +40 -70
- package/js/widgets/Dashboard/components/DashboardItem/Order/DashboardItemOrderContract.spec.tsx +31 -32
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateLearnerMessage/index.spec.tsx +19 -31
- package/js/widgets/Dashboard/components/DashboardItem/Order/OrderStateTeacherMessage/index.spec.tsx +26 -37
- package/js/widgets/Dashboard/components/DashboardItem/index.spec.tsx +28 -23
- package/js/widgets/Dashboard/components/DashboardLayoutRoute/index.spec.tsx +53 -51
- package/js/widgets/Dashboard/components/DashboardSidebar/components/ContractNavLink/index.spec.tsx +24 -49
- package/js/widgets/Dashboard/components/DashboardSidebar/components/MenuNavLink/index.spec.tsx +5 -14
- package/js/widgets/Dashboard/components/ProtectedOutlet/AuthenticatedOutlet.spec.tsx +62 -54
- package/js/widgets/Dashboard/components/ProtectedOutlet/ProtectedOutlet.spec.tsx +67 -42
- package/js/widgets/Dashboard/components/RouterButton/index.spec.tsx +12 -14
- package/js/widgets/Dashboard/components/TeacherDashboardOrganizationSidebar/index.spec.tsx +14 -39
- package/js/widgets/Dashboard/hooks/useDashboardRouter/index.spec.tsx +2 -4
- package/js/widgets/Dashboard/hooks/useEnroll/index.spec.tsx +7 -28
- package/js/widgets/Dashboard/hooks/useRouteInfo/index.spec.tsx +25 -33
- package/js/widgets/Dashboard/index.spec.tsx +49 -43
- package/js/widgets/LanguageSelector/index.spec.tsx +7 -7
- package/js/widgets/LtiConsumer/index.spec.tsx +46 -48
- package/js/widgets/RootSearchSuggestField/index.spec.tsx +8 -6
- package/js/widgets/Search/components/PaginateCourseSearch/index.spec.tsx +10 -3
- package/js/widgets/Search/components/SearchFilterGroup/index.spec.tsx +5 -3
- package/js/widgets/Search/components/SearchFilterGroupModal/index.spec.tsx +8 -4
- package/js/widgets/Search/components/SearchFilterValueLeaf/index.spec.tsx +7 -3
- package/js/widgets/Search/components/SearchFilterValueParent/index.spec.tsx +12 -7
- package/js/widgets/Search/components/SearchFiltersPane/index.spec.tsx +5 -1
- package/js/widgets/Search/hooks/useCourseSearch/index.spec.tsx +4 -12
- package/js/widgets/Search/hooks/useFilterValue/index.spec.tsx +0 -2
- package/js/widgets/Search/index.spec.tsx +14 -6
- package/js/widgets/SearchSuggestField/index.spec.tsx +14 -1
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCertificateItem/index.spec.tsx +16 -31
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseProductCourseRuns/index.spec.tsx +46 -72
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/components/CourseRunItem/index.spec.tsx +5 -2
- package/js/widgets/SyllabusCourseRunsList/components/CourseProductItem/index.spec.tsx +147 -162
- package/js/widgets/SyllabusCourseRunsList/components/CourseRunEnrollment/CourseRunUnenrollmentButton/index.spec.tsx +6 -4
- package/js/widgets/SyllabusCourseRunsList/components/CourseRunEnrollment/index.joanie.spec.tsx +22 -99
- package/js/widgets/SyllabusCourseRunsList/components/CourseRunEnrollment/index.openedx.spec.tsx +27 -83
- package/js/widgets/SyllabusCourseRunsList/components/CourseRunItem/index.spec.tsx +4 -1
- package/js/widgets/SyllabusCourseRunsList/components/CourseRunItemWithEnrollment/index.spec.tsx +28 -35
- package/js/widgets/SyllabusCourseRunsList/components/CourseWishButton/hooks/useCourseWish/index.spec.tsx +9 -28
- package/js/widgets/SyllabusCourseRunsList/components/CourseWishButton/index.login.spec.tsx +23 -48
- package/js/widgets/SyllabusCourseRunsList/components/CourseWishButton/index.logout.spec.tsx +20 -29
- package/js/widgets/SyllabusCourseRunsList/components/SyllabusSimpleCourseRunsList/index.spec.tsx +9 -4
- package/js/widgets/SyllabusCourseRunsList/hooks/useCourseEnrollment/index.spec.tsx +8 -10
- package/js/widgets/SyllabusCourseRunsList/index.spec.tsx +28 -39
- package/js/widgets/UserLogin/components/UserMenu/index.spec.tsx +9 -6
- package/js/widgets/UserLogin/index.not.isJoanieEnabled.spec.tsx +21 -32
- package/js/widgets/UserLogin/index.spec.tsx +15 -37
- package/js/widgets/index.spec.tsx +12 -17
- package/package.json +1 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
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
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
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
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
});
|
package/js/widgets/Dashboard/components/DashboardSidebar/components/ContractNavLink/index.spec.tsx
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
-
//
|
|
40
|
-
fetchMock.get('https://joanie.endpoint/api/v1.0/
|
|
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
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
<
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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(
|
package/js/widgets/Dashboard/components/DashboardSidebar/components/MenuNavLink/index.spec.tsx
CHANGED
|
@@ -1,22 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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 {
|
|
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
|
-
|
|
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
|
-
<
|
|
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.
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
|
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
|
-
<
|
|
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(
|
|
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(
|
|
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();
|