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
@@ -2,18 +2,15 @@
2
2
  * Test suite for CourseAddToWishlist component
3
3
  * for logged visitors
4
4
  */
5
- import { act, render, screen, waitFor } from '@testing-library/react';
5
+ import { screen } from '@testing-library/react';
6
6
  import fetchMock from 'fetch-mock';
7
- import { IntlProvider } from 'react-intl';
8
- import { QueryClientProvider } from '@tanstack/react-query';
9
7
  import userEvent from '@testing-library/user-event';
10
8
  import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
11
- import { createTestQueryClient } from 'utils/test/createTestQueryClient';
12
- import JoanieApiProvider from 'contexts/JoanieApiContext';
13
- import { SessionProvider } from 'contexts/SessionContext';
14
9
  import { HttpStatusCode } from 'utils/errors/HttpError';
15
- import { CourseLight } from 'types/Joanie';
16
10
  import { CourseLightFactory } from 'utils/test/factories/joanie';
11
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
12
+ import { render } from 'utils/test/render';
13
+ import { expectNoSpinner } from 'utils/test/expectSpinner';
17
14
  import CourseWishButton from '.';
18
15
 
19
16
  jest.mock('utils/context', () => ({
@@ -24,63 +21,44 @@ jest.mock('utils/context', () => ({
24
21
  endpoint: 'https://authentication.test',
25
22
  },
26
23
  joanie_backend: {
27
- endpoint: 'https://joanie.test',
24
+ endpoint: 'https://joanie.endpoint',
28
25
  },
29
26
  }).one(),
30
27
  }));
31
28
 
32
- const renderButton = (course: CourseLight) =>
33
- render(
34
- <IntlProvider locale="en">
35
- <QueryClientProvider client={createTestQueryClient({ user: true })}>
36
- <JoanieApiProvider>
37
- <SessionProvider>
38
- <CourseWishButton course={course} />
39
- </SessionProvider>
40
- </JoanieApiProvider>
41
- </QueryClientProvider>
42
- </IntlProvider>,
43
- );
44
-
45
29
  describe('CourseWishButton', () => {
30
+ const joanieSessionData = setupJoanieSession();
31
+ let nbApiCalls: number;
46
32
  const course = CourseLightFactory().one();
47
33
 
48
34
  beforeEach(() => {
49
- // JoanieSessionProvider inital requests
50
- fetchMock.get('https://joanie.test/api/v1.0/orders/', []);
51
- fetchMock.get('https://joanie.test/api/v1.0/addresses/', []);
52
- fetchMock.get('https://joanie.test/api/v1.0/credit-cards/', []);
53
- });
54
-
55
- afterEach(() => {
56
- jest.clearAllMocks();
57
- fetchMock.restore();
35
+ nbApiCalls = joanieSessionData.nbSessionApiRequest;
58
36
  });
59
37
 
60
38
  it('renders a notify me button', async () => {
61
- fetchMock.get(`https://joanie.test/api/v1.0/courses/${course.code}/wish/`, {
39
+ fetchMock.get(`https://joanie.endpoint/api/v1.0/courses/${course.code}/wish/`, {
62
40
  status: HttpStatusCode.OK,
63
41
  body: {
64
42
  status: false,
65
43
  },
66
44
  });
67
- renderButton(course);
45
+ render(<CourseWishButton course={course} />);
68
46
 
69
- // wait for JoanieSession initialization
70
- await waitFor(() => expect(screen.queryByText('loading...')).not.toBeInTheDocument());
71
47
  // wait for CourseAddToWishlist initialization
72
- await waitFor(() => expect(screen.queryByTestId('spinner')).not.toBeInTheDocument());
48
+ await expectNoSpinner();
73
49
 
74
50
  const $notifyButton = screen.getByRole('button', { name: 'Notify me' });
75
51
  expect($notifyButton).toBeInTheDocument();
76
52
 
77
- let nbApiCalls = 3; // JoanieSessionProvider initial requests
78
53
  nbApiCalls += 1; // useUserWishlistCourses inital fetch
79
54
  expect(fetchMock.calls().length).toBe(nbApiCalls);
80
55
 
81
- fetchMock.post(`https://joanie.test/api/v1.0/courses/${course.code}/wish/`, HttpStatusCode.OK);
56
+ fetchMock.post(
57
+ `https://joanie.endpoint/api/v1.0/courses/${course.code}/wish/`,
58
+ HttpStatusCode.OK,
59
+ );
82
60
  fetchMock.get(
83
- `https://joanie.test/api/v1.0/courses/${course.code}/wish/`,
61
+ `https://joanie.endpoint/api/v1.0/courses/${course.code}/wish/`,
84
62
  {
85
63
  status: HttpStatusCode.OK,
86
64
  body: {
@@ -90,7 +68,7 @@ describe('CourseWishButton', () => {
90
68
  { overwriteRoutes: true },
91
69
  );
92
70
 
93
- await act(async () => userEvent.click($notifyButton));
71
+ await userEvent.click($notifyButton);
94
72
 
95
73
  await screen.findByRole('button', { name: 'Do not notify me anymore' });
96
74
  expect(screen.queryByRole('button', { name: 'Notify me' })).not.toBeInTheDocument();
@@ -101,25 +79,22 @@ describe('CourseWishButton', () => {
101
79
  });
102
80
 
103
81
  it('renders a "do not notify me" button', async () => {
104
- fetchMock.get(`https://joanie.test/api/v1.0/courses/${course.code}/wish/`, {
82
+ fetchMock.get(`https://joanie.endpoint/api/v1.0/courses/${course.code}/wish/`, {
105
83
  status: HttpStatusCode.OK,
106
84
  body: {
107
85
  status: true,
108
86
  },
109
87
  });
110
- renderButton(course);
88
+ render(<CourseWishButton course={course} />);
111
89
 
112
- // wait for JoanieSession initialization
113
- await waitFor(() => expect(screen.queryByText('loading...')).not.toBeInTheDocument());
114
90
  // wait for CourseAddToWishlist initialization
115
- await waitFor(() => expect(screen.queryByTestId('spinner')).not.toBeInTheDocument());
91
+ await expectNoSpinner();
116
92
 
117
93
  const $stopNotifyButton = await screen.findByRole('button', {
118
94
  name: 'Do not notify me anymore',
119
95
  });
120
96
  expect($stopNotifyButton).toBeInTheDocument();
121
97
 
122
- let nbApiCalls = 3; // JoanieSessionProvider initial requests
123
98
  nbApiCalls += 1; // useUserWishlistCourses inital fetch
124
99
  expect(fetchMock.calls().length).toBe(nbApiCalls);
125
100
 
@@ -127,11 +102,11 @@ describe('CourseWishButton', () => {
127
102
  // react-query will refetch data using the GET url.
128
103
 
129
104
  fetchMock.delete(
130
- `https://joanie.test/api/v1.0/courses/${course.code}/wish/`,
105
+ `https://joanie.endpoint/api/v1.0/courses/${course.code}/wish/`,
131
106
  HttpStatusCode.OK,
132
107
  );
133
108
  fetchMock.get(
134
- `https://joanie.test/api/v1.0/courses/${course.code}/wish/`,
109
+ `https://joanie.endpoint/api/v1.0/courses/${course.code}/wish/`,
135
110
  {
136
111
  status: HttpStatusCode.OK,
137
112
  body: {
@@ -141,7 +116,7 @@ describe('CourseWishButton', () => {
141
116
  { overwriteRoutes: true },
142
117
  );
143
118
 
144
- await act(async () => userEvent.click($stopNotifyButton));
119
+ await userEvent.click($stopNotifyButton);
145
120
 
146
121
  expect(await screen.findByRole('button', { name: 'Notify me' })).toBeInTheDocument();
147
122
  expect(
@@ -2,18 +2,17 @@
2
2
  * Test suite for CourseAddToWishlist component
3
3
  * for anonymous visitors
4
4
  */
5
- import { render, screen, waitFor } from '@testing-library/react';
6
- import fetchMock from 'fetch-mock';
7
- import { IntlProvider } from 'react-intl';
8
- import { QueryClientProvider } from '@tanstack/react-query';
5
+ import { screen } from '@testing-library/react';
9
6
  import userEvent from '@testing-library/user-event';
7
+ import fetchMock from 'fetch-mock';
10
8
  import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
11
- import { createTestQueryClient } from 'utils/test/createTestQueryClient';
12
- import JoanieApiProvider from 'contexts/JoanieApiContext';
13
- import { SessionProvider } from 'contexts/SessionContext';
14
9
  import { location } from 'utils/indirection/window';
15
10
  import { CourseLightFactory } from 'utils/test/factories/joanie';
16
- import { CourseLight } from 'types/Joanie';
11
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
12
+ import { render } from 'utils/test/render';
13
+ import { HttpStatusCode } from 'utils/errors/HttpError';
14
+ import { expectNoSpinner } from 'utils/test/expectSpinner';
15
+ import { createTestQueryClient } from 'utils/test/createTestQueryClient';
17
16
  import CourseWishButton from '.';
18
17
 
19
18
  jest.mock('utils/indirection/window', () => ({
@@ -31,36 +30,28 @@ jest.mock('utils/context', () => ({
31
30
  endpoint: 'https://authentication.test',
32
31
  },
33
32
  joanie_backend: {
34
- endpoint: 'https://joanie.test',
33
+ endpoint: 'https://joanie.endpoint',
35
34
  },
36
35
  }).one(),
37
36
  }));
38
37
 
39
- const renderButton = (course: CourseLight) =>
40
- render(
41
- <IntlProvider locale="en">
42
- <QueryClientProvider client={createTestQueryClient({ user: null })}>
43
- <JoanieApiProvider>
44
- <SessionProvider>
45
- <CourseWishButton course={course} />
46
- </SessionProvider>
47
- </JoanieApiProvider>
48
- </QueryClientProvider>
49
- </IntlProvider>,
50
- );
51
-
52
38
  describe('CourseWishButton', () => {
39
+ setupJoanieSession();
53
40
  const course = CourseLightFactory().one();
54
41
 
55
- afterEach(() => {
56
- jest.clearAllMocks();
57
- fetchMock.restore();
58
- });
59
-
60
42
  it('renders a log me link', async () => {
61
- renderButton(course);
43
+ fetchMock.get(`https://joanie.endpoint/api/v1.0/courses/${course.code}/wish/`, {
44
+ status: HttpStatusCode.OK,
45
+ body: {
46
+ status: false,
47
+ },
48
+ });
49
+
50
+ render(<CourseWishButton course={course} />, {
51
+ queryOptions: { client: createTestQueryClient({ user: null }) },
52
+ });
62
53
  // wait for JoanieSession initialization
63
- await waitFor(() => expect(screen.queryByText('loading...')).not.toBeInTheDocument());
54
+ await expectNoSpinner();
64
55
 
65
56
  const $logMeButton = await screen.findByRole('button', { name: 'Log in to be notified' });
66
57
  expect($logMeButton).toBeInTheDocument();
@@ -1,5 +1,6 @@
1
- import { render, screen } from '@testing-library/react';
1
+ import { screen } from '@testing-library/react';
2
2
  import { CourseRunFactory } from 'utils/test/factories/richie';
3
+ import { render } from 'utils/test/render';
3
4
  import { SyllabusSimpleCourseRunsList } from '.';
4
5
 
5
6
  jest.mock('widgets/SyllabusCourseRunsList/components/CourseRunItem', () => ({
@@ -16,7 +17,9 @@ describe('SyllabusSimpleCourseRunsList', () => {
16
17
  it('should render CourseRunItemWithEnrollment when checkEnrollment is true', () => {
17
18
  const courseRun = CourseRunFactory().one();
18
19
 
19
- render(<SyllabusSimpleCourseRunsList courseRuns={[courseRun]} checkEnrollment />);
20
+ render(<SyllabusSimpleCourseRunsList courseRuns={[courseRun]} checkEnrollment />, {
21
+ wrapper: null,
22
+ });
20
23
 
21
24
  screen.getByText('CourseRunItemWithEnrollment');
22
25
  });
@@ -24,7 +27,7 @@ describe('SyllabusSimpleCourseRunsList', () => {
24
27
  it('should not render CourseRunItemWithEnrollment when checkEnrollment is false', () => {
25
28
  const courseRun = CourseRunFactory().one();
26
29
 
27
- render(<SyllabusSimpleCourseRunsList courseRuns={[courseRun]} />);
30
+ render(<SyllabusSimpleCourseRunsList courseRuns={[courseRun]} />, { wrapper: null });
28
31
 
29
32
  screen.getByText('CourseRunItem');
30
33
  });
@@ -34,7 +37,9 @@ describe('SyllabusSimpleCourseRunsList', () => {
34
37
  snapshot: 'https://example.com/snaphosts/1/',
35
38
  }).one();
36
39
 
37
- render(<SyllabusSimpleCourseRunsList courseRuns={[courseRun]} checkEnrollment />);
40
+ render(<SyllabusSimpleCourseRunsList courseRuns={[courseRun]} checkEnrollment />, {
41
+ wrapper: null,
42
+ });
38
43
 
39
44
  screen.getByText('CourseRunItem');
40
45
  });
@@ -1,5 +1,5 @@
1
1
  import { act, renderHook, waitFor } from '@testing-library/react';
2
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2
+ import { QueryClient } from '@tanstack/react-query';
3
3
  import { faker } from '@faker-js/faker';
4
4
  import fetchMock from 'fetch-mock';
5
5
  import { PropsWithChildren } from 'react';
@@ -10,11 +10,11 @@ import {
10
10
  UserFactory,
11
11
  CourseRunFactory,
12
12
  } from 'utils/test/factories/richie';
13
- import BaseSessionProvider from 'contexts/SessionContext/BaseSessionProvider';
14
13
  import { createTestQueryClient } from 'utils/test/createTestQueryClient';
15
14
  import { User } from 'types/User';
16
15
  import useCourseEnrollment from 'widgets/SyllabusCourseRunsList/hooks/useCourseEnrollment/index';
17
16
  import { HttpStatusCode } from 'utils/errors/HttpError';
17
+ import { BaseAppWrapper } from 'utils/test/wrappers/BaseAppWrapper';
18
18
 
19
19
  jest.mock('utils/context', () => ({
20
20
  __esModule: true,
@@ -38,15 +38,9 @@ describe('useCourseEnrollment', () => {
38
38
  const wrapper =
39
39
  (client: QueryClient) =>
40
40
  ({ children }: PropsWithChildren) => (
41
- <QueryClientProvider client={client}>
42
- <BaseSessionProvider>{children}</BaseSessionProvider>
43
- </QueryClientProvider>
41
+ <BaseAppWrapper queryOptions={{ client }}>{children}</BaseAppWrapper>
44
42
  );
45
43
 
46
- beforeEach(() => {
47
- fetchMock.restore();
48
- });
49
-
50
44
  it('does not make request when user is not authenticated', async () => {
51
45
  const user: User = UserFactory().one();
52
46
  const courseRun: CourseRun = CourseRunFactory().one();
@@ -60,9 +54,13 @@ describe('useCourseEnrollment', () => {
60
54
  wrapper: wrapper(createTestQueryClient({ user: null })),
61
55
  });
62
56
 
57
+ await waitFor(() => {
58
+ expect(result.current).not.toBeNull();
59
+ });
60
+
63
61
  expect(fetchMock.called()).toBeFalsy();
64
62
  expect(result.current.enrollment).toBeUndefined();
65
- expect(result.current.enrollmentIsActive).toBeUndefined();
63
+ expect(result.current.enrollmentIsActive).toBe(false);
66
64
  });
67
65
 
68
66
  it('retrieves enrollment when user is authenticated', async () => {
@@ -4,14 +4,11 @@ import {
4
4
  getByRole,
5
5
  getByText,
6
6
  queryByRole,
7
- render,
8
7
  screen,
9
8
  within,
10
9
  } from '@testing-library/react';
11
10
  import ReactDOM from 'react-dom';
12
- import { createIntl, IntlProvider } from 'react-intl';
13
- import { QueryClientProvider } from '@tanstack/react-query';
14
- import { PropsWithChildren } from 'react';
11
+ import { createIntl } from 'react-intl';
15
12
  import fetchMock from 'fetch-mock';
16
13
  import userEvent from '@testing-library/user-event';
17
14
  import { faker } from '@faker-js/faker';
@@ -23,16 +20,14 @@ import {
23
20
  import SyllabusCourseRunsList from 'widgets/SyllabusCourseRunsList/index';
24
21
  import { createTestQueryClient } from 'utils/test/createTestQueryClient';
25
22
  import { CourseRun, Priority } from 'types';
26
- import JoanieApiProvider from 'contexts/JoanieApiContext';
27
23
  import { CourseProductRelation } from 'types/Joanie';
28
24
  import { CourseLightFactory, CourseProductRelationFactory } from 'utils/test/factories/joanie';
29
25
  import { DEFAULT_DATE_FORMAT } from 'hooks/useDateFormat';
30
26
  import { StringHelper } from 'utils/StringHelper';
31
27
  import { computeStates } from 'utils/CourseRuns';
32
- import { User } from 'types/User';
33
- import { Nullable } from 'types/utils';
34
- import BaseSessionProvider from 'contexts/SessionContext/BaseSessionProvider';
35
28
  import { IntlHelper } from 'utils/IntlHelper';
29
+ import { render } from 'utils/test/render';
30
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
36
31
 
37
32
  jest.mock('utils/context', () => {
38
33
  const mock = mockRichieContextFactory().one();
@@ -40,7 +35,7 @@ jest.mock('utils/context', () => {
40
35
  {
41
36
  backend: 'joanie',
42
37
  course_regexp: '^.*/api/v1.0((?:/(?:courses|course-runs|products)/[^/]+)+)/?$',
43
- endpoint: 'https://joanie.test',
38
+ endpoint: 'https://joanie.endpoint',
44
39
  },
45
40
  {
46
41
  backend: 'openedx-hawthorn',
@@ -49,7 +44,7 @@ jest.mock('utils/context', () => {
49
44
  },
50
45
  ];
51
46
  mock.authentication = { backend: 'fonzie', endpoint: 'https://auth.test' };
52
- mock.joanie_backend = { endpoint: 'https://joanie.test' };
47
+ mock.joanie_backend = { endpoint: 'https://joanie.endpoint' };
53
48
  return {
54
49
  __esModule: true,
55
50
  default: mock,
@@ -59,6 +54,9 @@ jest.mock('utils/context', () => {
59
54
  const MAX_ARCHIVED_COURSE_RUNS = 5;
60
55
 
61
56
  describe('<SyllabusCourseRunsList/>', () => {
57
+ let nbApiCalls: number;
58
+ const joanieSessionData = setupJoanieSession();
59
+
62
60
  beforeAll(() => {
63
61
  // @ts-ignore
64
62
  ReactDOM.createPortal = jest.fn((element) => {
@@ -66,24 +64,15 @@ describe('<SyllabusCourseRunsList/>', () => {
66
64
  });
67
65
  });
68
66
 
67
+ beforeEach(() => {
68
+ nbApiCalls = joanieSessionData.nbSessionApiRequest;
69
+ });
70
+
69
71
  afterEach(() => {
70
72
  // @ts-ignore
71
73
  ReactDOM.createPortal.mockClear();
72
- fetchMock.restore();
73
74
  });
74
75
 
75
- const Wrapper = ({ children, user = null }: PropsWithChildren<{ user?: Nullable<User> }>) => {
76
- return (
77
- <QueryClientProvider client={createTestQueryClient({ user })}>
78
- <IntlProvider locale="en">
79
- <JoanieApiProvider>
80
- <BaseSessionProvider>{children}</BaseSessionProvider>
81
- </JoanieApiProvider>
82
- </IntlProvider>
83
- </QueryClientProvider>
84
- );
85
- };
86
-
87
76
  const getHeaderContainer = (): HTMLElement => {
88
77
  return document.querySelector('.course-detail__row')!;
89
78
  };
@@ -176,7 +165,7 @@ describe('<SyllabusCourseRunsList/>', () => {
176
165
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
177
166
  />,
178
167
  {
179
- wrapper: Wrapper,
168
+ queryOptions: { client: createTestQueryClient({ user: null }) },
180
169
  },
181
170
  );
182
171
 
@@ -213,7 +202,7 @@ describe('<SyllabusCourseRunsList/>', () => {
213
202
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
214
203
  />,
215
204
  {
216
- wrapper: Wrapper,
205
+ queryOptions: { client: createTestQueryClient({ user: null }) },
217
206
  },
218
207
  );
219
208
 
@@ -250,7 +239,7 @@ describe('<SyllabusCourseRunsList/>', () => {
250
239
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
251
240
  />,
252
241
  {
253
- wrapper: Wrapper,
242
+ queryOptions: { client: createTestQueryClient({ user: null }) },
254
243
  },
255
244
  );
256
245
 
@@ -295,7 +284,7 @@ describe('<SyllabusCourseRunsList/>', () => {
295
284
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
296
285
  />,
297
286
  {
298
- wrapper: Wrapper,
287
+ queryOptions: { client: createTestQueryClient({ user: null }) },
299
288
  },
300
289
  );
301
290
 
@@ -315,7 +304,7 @@ describe('<SyllabusCourseRunsList/>', () => {
315
304
  it('has one opened product', async () => {
316
305
  const course = CourseLightFactory().one();
317
306
  const relation = CourseProductRelationFactory().one();
318
- const resourceLink = `https://joanie.test/api/v1.0/courses/${course.code}/products/${relation.product.id}/`;
307
+ const resourceLink = `https://joanie.endpoint/api/v1.0/courses/${course.code}/products/${relation.product.id}/`;
319
308
  fetchMock.get(resourceLink, relation);
320
309
 
321
310
  const courseRun = CourseRunFactoryFromPriority(Priority.ONGOING_OPEN)({
@@ -329,7 +318,7 @@ describe('<SyllabusCourseRunsList/>', () => {
329
318
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
330
319
  />,
331
320
  {
332
- wrapper: Wrapper,
321
+ queryOptions: { client: createTestQueryClient({ user: null }) },
333
322
  },
334
323
  );
335
324
 
@@ -353,7 +342,7 @@ describe('<SyllabusCourseRunsList/>', () => {
353
342
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
354
343
  />,
355
344
  {
356
- wrapper: Wrapper,
345
+ queryOptions: { client: createTestQueryClient({ user: null }) },
357
346
  },
358
347
  );
359
348
  getByRole(getPortalContainer(), 'heading', {
@@ -378,7 +367,7 @@ describe('<SyllabusCourseRunsList/>', () => {
378
367
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
379
368
  />,
380
369
  {
381
- wrapper: Wrapper,
370
+ queryOptions: { client: createTestQueryClient({ user: null }) },
382
371
  },
383
372
  );
384
373
  getByRole(getPortalContainer(), 'heading', {
@@ -415,7 +404,7 @@ describe('<SyllabusCourseRunsList/>', () => {
415
404
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
416
405
  />,
417
406
  {
418
- wrapper: Wrapper,
407
+ queryOptions: { client: createTestQueryClient({ user: null }) },
419
408
  },
420
409
  );
421
410
 
@@ -467,7 +456,7 @@ describe('<SyllabusCourseRunsList/>', () => {
467
456
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
468
457
  />,
469
458
  {
470
- wrapper: Wrapper,
459
+ queryOptions: { client: createTestQueryClient({ user: null }) },
471
460
  },
472
461
  );
473
462
 
@@ -494,7 +483,7 @@ describe('<SyllabusCourseRunsList/>', () => {
494
483
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
495
484
  />,
496
485
  {
497
- wrapper: Wrapper,
486
+ queryOptions: { client: createTestQueryClient({ user: null }) },
498
487
  },
499
488
  );
500
489
 
@@ -540,7 +529,7 @@ describe('<SyllabusCourseRunsList/>', () => {
540
529
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
541
530
  />,
542
531
  {
543
- wrapper: Wrapper,
532
+ queryOptions: { client: createTestQueryClient({ user: null }) },
544
533
  },
545
534
  );
546
535
 
@@ -600,7 +589,7 @@ describe('<SyllabusCourseRunsList/>', () => {
600
589
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
601
590
  />,
602
591
  {
603
- wrapper: Wrapper,
592
+ queryOptions: { client: createTestQueryClient({ user: null }) },
604
593
  },
605
594
  );
606
595
 
@@ -651,7 +640,7 @@ describe('<SyllabusCourseRunsList/>', () => {
651
640
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
652
641
  />,
653
642
  {
654
- wrapper: Wrapper,
643
+ queryOptions: { client: createTestQueryClient({ user: null }) },
655
644
  },
656
645
  );
657
646
 
@@ -711,7 +700,7 @@ describe('<SyllabusCourseRunsList/>', () => {
711
700
  maxArchivedCourseRuns={MAX_ARCHIVED_COURSE_RUNS}
712
701
  />,
713
702
  {
714
- wrapper: ({ children }) => <Wrapper user={user}>{children}</Wrapper>,
703
+ queryOptions: { client: createTestQueryClient({ user }) },
715
704
  },
716
705
  );
717
706
 
@@ -730,7 +719,7 @@ describe('<SyllabusCourseRunsList/>', () => {
730
719
  const links = screen.getAllByRole('link');
731
720
  expect(links.length).toBe(1);
732
721
  const calledUrls = fetchMock.calls().map((call) => call[0]);
733
- expect(calledUrls).toHaveLength(1);
722
+ expect(calledUrls).toHaveLength(nbApiCalls + 1);
734
723
 
735
724
  // Assert user's enrollment state has been checked for the ongoing course run.
736
725
  const link = within(portalContainer).getByRole('link');
@@ -1,6 +1,7 @@
1
- import { render, screen } from '@testing-library/react';
1
+ import { screen } from '@testing-library/react';
2
2
  import userEvent from '@testing-library/user-event';
3
- import { IntlProvider } from 'react-intl';
3
+ import { IntlWrapper } from 'utils/test/wrappers/IntlWrapper';
4
+ import { render } from 'utils/test/render';
4
5
  import { UserMenu } from '.';
5
6
 
6
7
  /* Enforce to use DesktopUserMenu by default */
@@ -44,9 +45,10 @@ describe('<UserMenu />', () => {
44
45
 
45
46
  it('renders a dropdown with links matching the data passed to the "link" prop', async () => {
46
47
  render(
47
- <IntlProvider locale="en">
48
+ <IntlWrapper>
48
49
  <UserMenu {...props} />
49
- </IntlProvider>,
50
+ </IntlWrapper>,
51
+ { wrapper: null },
50
52
  );
51
53
 
52
54
  const button = screen.getByLabelText('Access to your profile settings', {
@@ -69,9 +71,10 @@ describe('<UserMenu />', () => {
69
71
  mockMatches = false;
70
72
 
71
73
  render(
72
- <IntlProvider locale="en">
74
+ <IntlWrapper>
73
75
  <UserMenu {...props} />
74
- </IntlProvider>,
76
+ </IntlWrapper>,
77
+ { wrapper: null },
75
78
  );
76
79
 
77
80
  screen.getByRole('heading', { name: 'John Doe' });