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,5 +1,5 @@
1
1
  import { QueryClientProvider } from '@tanstack/react-query';
2
- import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
2
+ import { act, fireEvent, screen, waitFor } from '@testing-library/react';
3
3
  import fetchMock from 'fetch-mock';
4
4
  import queryString from 'query-string';
5
5
  import { IntlProvider } from 'react-intl';
@@ -10,6 +10,7 @@ import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/fac
10
10
  import context from 'utils/context';
11
11
  import { createTestQueryClient } from 'utils/test/createTestQueryClient';
12
12
  import { HttpStatusCode } from 'utils/errors/HttpError';
13
+ import { render } from 'utils/test/render';
13
14
  import Search from '.';
14
15
 
15
16
  let mockMatches = false;
@@ -29,6 +30,10 @@ jest.mock('utils/context', () => ({
29
30
  default: mockRichieContextFactory().one(),
30
31
  }));
31
32
 
33
+ jest.mock('utils/errors/handle', () => ({
34
+ handle: jest.fn(),
35
+ }));
36
+
32
37
  describe('<Search />', () => {
33
38
  const historyPushState = jest.fn();
34
39
  const historyReplaceState = jest.fn();
@@ -42,11 +47,6 @@ describe('<Search />', () => {
42
47
  historyReplaceState,
43
48
  ];
44
49
 
45
- afterEach(() => {
46
- fetchMock.restore();
47
- jest.resetAllMocks();
48
- });
49
-
50
50
  it('shows a spinner while the results are loading', async () => {
51
51
  fetchMock.get('/api/v1.0/courses/?limit=20&offset=0', {
52
52
  meta: {
@@ -63,6 +63,7 @@ describe('<Search />', () => {
63
63
  </HistoryContext.Provider>
64
64
  </IntlProvider>
65
65
  </QueryClientProvider>,
66
+ { wrapper: null },
66
67
  );
67
68
 
68
69
  expect(screen.getByText('Loading search results...').parentElement).toHaveAttribute(
@@ -118,6 +119,7 @@ describe('<Search />', () => {
118
119
  </HistoryContext.Provider>
119
120
  </IntlProvider>
120
121
  </QueryClientProvider>,
122
+ { wrapper: null },
121
123
  );
122
124
 
123
125
  // Wait for search results to be loaded
@@ -142,6 +144,7 @@ describe('<Search />', () => {
142
144
  </HistoryContext.Provider>
143
145
  </IntlProvider>
144
146
  </QueryClientProvider>,
147
+ { wrapper: null },
145
148
  );
146
149
 
147
150
  expect(screen.getByText('Loading search results...').parentElement).toHaveAttribute(
@@ -172,6 +175,7 @@ describe('<Search />', () => {
172
175
  </HistoryContext.Provider>
173
176
  </IntlProvider>
174
177
  </QueryClientProvider>,
178
+ { wrapper: null },
175
179
  );
176
180
 
177
181
  await waitFor(() => {
@@ -198,6 +202,7 @@ describe('<Search />', () => {
198
202
  </HistoryContext.Provider>
199
203
  </IntlProvider>
200
204
  </QueryClientProvider>,
205
+ { wrapper: null },
201
206
  );
202
207
 
203
208
  // there is a button to toggle the filters pane, placed right before the filters pane in the DOM
@@ -265,6 +270,7 @@ describe('<Search />', () => {
265
270
  </HistoryContext.Provider>
266
271
  </IntlProvider>
267
272
  </QueryClientProvider>,
273
+ { wrapper: null },
268
274
  );
269
275
 
270
276
  // both filters and results zones are regions that are correctly labelled
@@ -301,6 +307,7 @@ describe('<Search />', () => {
301
307
  </HistoryContext.Provider>
302
308
  </IntlProvider>
303
309
  </QueryClientProvider>,
310
+ { wrapper: null },
304
311
  );
305
312
  });
306
313
 
@@ -333,6 +340,7 @@ describe('<Search />', () => {
333
340
  </HistoryContext.Provider>
334
341
  </IntlProvider>
335
342
  </QueryClientProvider>,
343
+ { wrapper: null },
336
344
  );
337
345
  });
338
346
 
@@ -1,4 +1,4 @@
1
- import { act, fireEvent, render, waitFor } from '@testing-library/react';
1
+ import { act, fireEvent, waitFor } from '@testing-library/react';
2
2
  import fetchMock from 'fetch-mock';
3
3
  import { IntlProvider } from 'react-intl';
4
4
  import { CourseSearchParamsAction, useCourseSearchParams } from 'hooks/useCourseSearchParams';
@@ -7,6 +7,7 @@ import { history, location } from 'utils/indirection/window';
7
7
  import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
8
8
  import { FilterDefinition } from 'types/filters';
9
9
  import context from 'utils/context';
10
+ import { render } from 'utils/test/render';
10
11
  import SearchSuggestField from '.';
11
12
 
12
13
  jest.mock('settings', () => ({
@@ -78,6 +79,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
78
79
  <SearchSuggestField context={context} />
79
80
  </HistoryProvider>
80
81
  </IntlProvider>,
82
+ { wrapper: null },
81
83
  );
82
84
 
83
85
  // The placeholder text is shown in the input
@@ -94,6 +96,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
94
96
  <SearchSuggestField context={context} />
95
97
  </HistoryProvider>
96
98
  </IntlProvider>,
99
+ { wrapper: null },
97
100
  );
98
101
 
99
102
  // The existing query is shown in the input
@@ -116,6 +119,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
116
119
  <OtherComponent />
117
120
  </HistoryProvider>
118
121
  </IntlProvider>,
122
+ { wrapper: null },
119
123
  );
120
124
 
121
125
  // The existing query is shown in the input
@@ -134,6 +138,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
134
138
  <OtherComponent />
135
139
  </HistoryProvider>
136
140
  </IntlProvider>,
141
+ { wrapper: null },
137
142
  );
138
143
 
139
144
  // The input does not show a value anymore
@@ -170,6 +175,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
170
175
  <SearchSuggestField context={context} />
171
176
  </HistoryProvider>
172
177
  </IntlProvider>,
178
+ { wrapper: null },
173
179
  );
174
180
 
175
181
  const field = getByPlaceholderText('Search for courses, organizations, categories');
@@ -212,6 +218,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
212
218
  <SearchSuggestField context={context} />
213
219
  </HistoryProvider>
214
220
  </IntlProvider>,
221
+ { wrapper: null },
215
222
  );
216
223
 
217
224
  const field = getByPlaceholderText('Search for courses, organizations, categories');
@@ -257,6 +264,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
257
264
  <SearchSuggestField context={context} />
258
265
  </HistoryProvider>
259
266
  </IntlProvider>,
267
+ { wrapper: null },
260
268
  );
261
269
 
262
270
  const field = getByPlaceholderText('Search for courses, organizations, categories');
@@ -349,6 +357,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
349
357
  <SearchSuggestField context={context} />
350
358
  </HistoryProvider>
351
359
  </IntlProvider>,
360
+ { wrapper: null },
352
361
  );
353
362
 
354
363
  const field = getByPlaceholderText('Search for courses, organizations, categories');
@@ -433,6 +442,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
433
442
  <SearchSuggestField context={context} />
434
443
  </HistoryProvider>
435
444
  </IntlProvider>,
445
+ { wrapper: null },
436
446
  );
437
447
 
438
448
  const field = getByPlaceholderText('Search for courses, organizations, categories');
@@ -477,6 +487,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
477
487
  <SearchSuggestField context={context} />
478
488
  </HistoryProvider>
479
489
  </IntlProvider>,
490
+ { wrapper: null },
480
491
  );
481
492
 
482
493
  const field = getByPlaceholderText('Search for courses, organizations, categories');
@@ -566,6 +577,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
566
577
  <SearchSuggestField context={context} />
567
578
  </HistoryProvider>
568
579
  </IntlProvider>,
580
+ { wrapper: null },
569
581
  );
570
582
 
571
583
  const field = getByPlaceholderText('Search for courses, organizations, categories');
@@ -627,6 +639,7 @@ describe('widgets/Search/components/SearchSuggestField', () => {
627
639
  <SearchSuggestField context={context} />
628
640
  </HistoryProvider>
629
641
  </IntlProvider>,
642
+ { wrapper: null },
630
643
  );
631
644
 
632
645
  const field = getByPlaceholderText('Search for courses, organizations, categories');
@@ -1,13 +1,13 @@
1
- import { fireEvent, render, screen, waitFor } from '@testing-library/react';
1
+ import { fireEvent, screen, waitFor } from '@testing-library/react';
2
2
  import { faker } from '@faker-js/faker';
3
3
  import fetchMock from 'fetch-mock';
4
- import { PropsWithChildren } from 'react';
5
- import { IntlProvider } from 'react-intl';
6
4
  import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
7
5
  import { CertificationDefinitionFactory, OrderLiteFactory } from 'utils/test/factories/joanie';
8
- import JoanieApiProvider from 'contexts/JoanieApiContext';
9
6
  import { CertificateDefinition, OrderLite } from 'types/Joanie';
10
7
  import { HttpStatusCode } from 'utils/errors/HttpError';
8
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
9
+ import { render } from 'utils/test/render';
10
+ import { BaseJoanieAppWrapper } from 'utils/test/wrappers/BaseJoanieAppWrapper';
11
11
  import CertificateItem from '.';
12
12
 
13
13
  jest.mock('utils/errors/handle');
@@ -15,16 +15,12 @@ jest.mock('utils/context', () => ({
15
15
  __esModule: true,
16
16
  default: mockRichieContextFactory({
17
17
  authentication: { backend: 'fonzie', endpoint: 'https://auth.test' },
18
- joanie_backend: { endpoint: 'https://joanie.test' },
18
+ joanie_backend: { endpoint: 'https://joanie.endpoint' },
19
19
  }).one(),
20
20
  }));
21
21
 
22
22
  describe('CourseProductCertificateItem', () => {
23
- const Wrapper = ({ children }: PropsWithChildren<{}>) => (
24
- <IntlProvider locale="en">
25
- <JoanieApiProvider>{children}</JoanieApiProvider>
26
- </IntlProvider>
27
- );
23
+ setupJoanieSession();
28
24
 
29
25
  beforeAll(() => {
30
26
  // eslint-disable-next-line compat/compat
@@ -34,19 +30,12 @@ describe('CourseProductCertificateItem', () => {
34
30
  HTMLAnchorElement.prototype.click = jest.fn();
35
31
  });
36
32
 
37
- afterEach(() => {
38
- fetchMock.restore();
39
- jest.resetAllMocks();
40
- });
41
-
42
33
  it('displays certificate information', () => {
43
34
  const certificateDefinition: CertificateDefinition = CertificationDefinitionFactory().one();
44
35
 
45
- render(
46
- <Wrapper>
47
- <CertificateItem certificateDefinition={certificateDefinition} />
48
- </Wrapper>,
49
- );
36
+ render(<CertificateItem certificateDefinition={certificateDefinition} />, {
37
+ wrapper: BaseJoanieAppWrapper,
38
+ });
50
39
 
51
40
  // the title is not a heading to prevent screen reader users "heading spam",
52
41
  // but we want it to visually look like a heading for sighted users
@@ -60,11 +49,9 @@ describe('CourseProductCertificateItem', () => {
60
49
  description: '',
61
50
  }).one();
62
51
 
63
- render(
64
- <Wrapper>
65
- <CertificateItem certificateDefinition={certificateDefinition} />
66
- </Wrapper>,
67
- );
52
+ render(<CertificateItem certificateDefinition={certificateDefinition} />, {
53
+ wrapper: BaseJoanieAppWrapper,
54
+ });
68
55
 
69
56
  screen.getByText(
70
57
  'You will be able to download your certificate once you will pass all course runs.',
@@ -75,11 +62,9 @@ describe('CourseProductCertificateItem', () => {
75
62
  const certificateDefinition: CertificateDefinition = CertificationDefinitionFactory().one();
76
63
  const order: OrderLite = OrderLiteFactory({ certificate_id: faker.string.uuid() }).one();
77
64
 
78
- render(
79
- <Wrapper>
80
- <CertificateItem certificateDefinition={certificateDefinition} order={order} />
81
- </Wrapper>,
82
- );
65
+ render(<CertificateItem certificateDefinition={certificateDefinition} order={order} />, {
66
+ wrapper: BaseJoanieAppWrapper,
67
+ });
83
68
 
84
69
  // - The certificate description should not be displayed ...
85
70
  expect(screen.queryByText(certificateDefinition.description)).toBeNull();
@@ -90,7 +75,7 @@ describe('CourseProductCertificateItem', () => {
90
75
 
91
76
  // When user clicks on "Download" button, the certificate should be downloaded
92
77
  fetchMock.get(
93
- `https://joanie.test/api/v1.0/certificates/${order.certificate_id}/download/`,
78
+ `https://joanie.endpoint/api/v1.0/certificates/${order.certificate_id}/download/`,
94
79
  () => ({
95
80
  status: HttpStatusCode.OK,
96
81
  body: new Blob(['test']),
@@ -1,9 +1,8 @@
1
1
  import { faker } from '@faker-js/faker';
2
- import { act, fireEvent, render, screen } from '@testing-library/react';
2
+ import { act, fireEvent, screen } from '@testing-library/react';
3
3
  import fetchMock from 'fetch-mock';
4
4
  import type { PropsWithChildren } from 'react';
5
5
  import { IntlProvider, createIntl } from 'react-intl';
6
- import { QueryClientProvider } from '@tanstack/react-query';
7
6
  import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
8
7
  import {
9
8
  CourseLightFactory,
@@ -12,20 +11,21 @@ import {
12
11
  CredentialOrderFactory,
13
12
  ProductFactory,
14
13
  } from 'utils/test/factories/joanie';
15
- import JoanieApiProvider from 'contexts/JoanieApiContext';
16
14
  import type { CourseLight, CourseRun, Enrollment } from 'types/Joanie';
17
15
  import { Deferred } from 'utils/test/deferred';
18
16
  import { CourseStateTextEnum, Priority } from 'types';
19
- import { createTestQueryClient } from 'utils/test/createTestQueryClient';
20
17
  import { IntlHelper } from 'utils/IntlHelper';
21
18
  import { HttpStatusCode } from 'utils/errors/HttpError';
19
+ import { render } from 'utils/test/render';
20
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
21
+ import { BaseJoanieAppWrapper } from 'utils/test/wrappers/BaseJoanieAppWrapper';
22
22
  import { CourseRunList, EnrollableCourseRunList, EnrolledCourseRun } from '.';
23
23
 
24
24
  jest.mock('utils/context', () => ({
25
25
  __esModule: true,
26
26
  default: mockRichieContextFactory({
27
27
  authentication: { backend: 'fonzie', endpoint: 'https://auth.test' },
28
- joanie_backend: { endpoint: 'https://joanie.test' },
28
+ joanie_backend: { endpoint: 'https://joanie.endpoint' },
29
29
  }).one(),
30
30
  }));
31
31
 
@@ -46,11 +46,7 @@ describe('CourseProductCourseRuns', () => {
46
46
  );
47
47
 
48
48
  it('renders a warning message when no course runs are provided', () => {
49
- render(
50
- <Wrapper>
51
- <CourseRunList courseRuns={[]} />
52
- </Wrapper>,
53
- );
49
+ render(<CourseRunList courseRuns={[]} />, { wrapper: Wrapper });
54
50
 
55
51
  expect(screen.getByText('No session available for this course.'));
56
52
  });
@@ -58,11 +54,7 @@ describe('CourseProductCourseRuns', () => {
58
54
  it('renders a list of course runs', () => {
59
55
  const courseRuns: CourseRun[] = CourseRunFactory().many(2);
60
56
 
61
- const { container } = render(
62
- <Wrapper>
63
- <CourseRunList courseRuns={courseRuns} />
64
- </Wrapper>,
65
- );
57
+ const { container } = render(<CourseRunList courseRuns={courseRuns} />, { wrapper: Wrapper });
66
58
 
67
59
  // It should render all course runs provided
68
60
  expect(screen.getAllByRole('listitem')).toHaveLength(2);
@@ -118,23 +110,16 @@ describe('CourseProductCourseRuns', () => {
118
110
  });
119
111
 
120
112
  describe('EnrollableCourseRunList', () => {
121
- const Wrapper = ({ children }: PropsWithChildren) => (
122
- <IntlProvider locale="en">
123
- <QueryClientProvider client={createTestQueryClient()}>
124
- <JoanieApiProvider>{children}</JoanieApiProvider>
125
- </QueryClientProvider>
126
- </IntlProvider>
127
- );
113
+ setupJoanieSession();
128
114
 
129
115
  it('renders a warning message when no course runs are provided', () => {
130
116
  const order = CredentialOrderFactory().one();
131
117
  const product = ProductFactory().one();
132
118
 
133
- render(
134
- <Wrapper>
135
- <EnrollableCourseRunList courseRuns={[]} order={order} product={product} />
136
- </Wrapper>,
137
- );
119
+ fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
120
+ render(<EnrollableCourseRunList courseRuns={[]} order={order} product={product} />, {
121
+ wrapper: BaseJoanieAppWrapper,
122
+ });
138
123
 
139
124
  expect(screen.getByText('No session available for this course.'));
140
125
  });
@@ -146,11 +131,10 @@ describe('CourseProductCourseRuns', () => {
146
131
  contract_definition: undefined,
147
132
  }).one();
148
133
 
149
- render(
150
- <Wrapper>
151
- <EnrollableCourseRunList courseRuns={courseRuns} order={order} product={product} />
152
- </Wrapper>,
153
- );
134
+ fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
135
+ render(<EnrollableCourseRunList courseRuns={courseRuns} order={order} product={product} />, {
136
+ wrapper: BaseJoanieAppWrapper,
137
+ });
154
138
 
155
139
  // the list should contain only the course run items, without the call to action button
156
140
  expect(screen.getAllByRole('listitem')).toHaveLength(2);
@@ -228,7 +212,7 @@ describe('CourseProductCourseRuns', () => {
228
212
  // - User clicks to enroll
229
213
  fetchMock.resetHistory();
230
214
  const enrollmentDeferred = new Deferred();
231
- fetchMock.post('https://joanie.test/api/v1.0/enrollments/', enrollmentDeferred.promise);
215
+ fetchMock.post('https://joanie.endpoint/api/v1.0/enrollments/', enrollmentDeferred.promise);
232
216
 
233
217
  await act(async () => {
234
218
  fireEvent.click($button);
@@ -241,10 +225,12 @@ describe('CourseProductCourseRuns', () => {
241
225
  enrollmentDeferred.resolve(HttpStatusCode.OK);
242
226
  });
243
227
 
244
- const calls = fetchMock.calls();
245
- expect(calls).toHaveLength(1);
228
+ const calledUrls = fetchMock.calls().map((call) => call[0]);
229
+ let nbApiCalls = 1; // post enrollments
230
+ nbApiCalls += 1; // refetch enrollments
231
+ expect(calledUrls).toHaveLength(nbApiCalls);
246
232
  // A request to create the enrollment should have been executed
247
- expect(calls[0][0]).toBe('https://joanie.test/api/v1.0/enrollments/');
233
+ expect(calledUrls[0]).toBe('https://joanie.endpoint/api/v1.0/enrollments/');
248
234
  expect(JSON.parse(fetchMock.calls()[0][1]!.body as string)).toEqual({
249
235
  is_active: true,
250
236
  course_run_id: courseRuns[0].id,
@@ -258,13 +244,12 @@ describe('CourseProductCourseRuns', () => {
258
244
  const order = CredentialOrderFactory().one();
259
245
  const product = ProductFactory().one();
260
246
  product.contract_definition = undefined;
261
- fetchMock.get(`https://joanie.test/api/v1.0/courses/${course.code}/`, HttpStatusCode.OK);
247
+ fetchMock.get(`https://joanie.endpoint/api/v1.0/courses/${course.code}/`, HttpStatusCode.OK);
248
+ fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
262
249
 
263
- render(
264
- <Wrapper>
265
- <EnrollableCourseRunList courseRuns={courseRuns} order={order} product={product} />
266
- </Wrapper>,
267
- );
250
+ render(<EnrollableCourseRunList courseRuns={courseRuns} order={order} product={product} />, {
251
+ wrapper: BaseJoanieAppWrapper,
252
+ });
268
253
 
269
254
  // the list should contain only the course run items, without the call to action button
270
255
  expect(screen.getAllByRole('listitem')).toHaveLength(2);
@@ -333,7 +318,7 @@ describe('CourseProductCourseRuns', () => {
333
318
  // - User clicks to enroll
334
319
  fetchMock.resetHistory();
335
320
  const enrollmentDeferred = new Deferred();
336
- fetchMock.post('https://joanie.test/api/v1.0/enrollments/', enrollmentDeferred.promise);
321
+ fetchMock.post('https://joanie.endpoint/api/v1.0/enrollments/', enrollmentDeferred.promise);
337
322
 
338
323
  await act(async () => {
339
324
  fireEvent.click($button);
@@ -374,11 +359,10 @@ describe('CourseProductCourseRuns', () => {
374
359
  product.contract_definition = undefined;
375
360
  const order = CredentialOrderFactory().one();
376
361
 
377
- render(
378
- <Wrapper>
379
- <EnrollableCourseRunList courseRuns={[courseRun]} order={order} product={product} />
380
- </Wrapper>,
381
- );
362
+ fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
363
+ render(<EnrollableCourseRunList courseRuns={[courseRun]} order={order} product={product} />, {
364
+ wrapper: BaseJoanieAppWrapper,
365
+ });
382
366
 
383
367
  // the list should contain only the course run items, without the call to action button
384
368
  expect(screen.getAllByRole('listitem')).toHaveLength(1);
@@ -413,7 +397,7 @@ describe('CourseProductCourseRuns', () => {
413
397
  // it should be enabled already to allow early user feedback
414
398
  expect($button.disabled).toBe(false);
415
399
 
416
- fetchMock.post('https://joanie.test/api/v1.0/enrollments/', []);
400
+ fetchMock.post('https://joanie.endpoint/api/v1.0/enrollments/', []);
417
401
  await act(async () => {
418
402
  // - Select the first course run
419
403
  const $radio = screen.getByRole('radio', {
@@ -457,11 +441,10 @@ describe('CourseProductCourseRuns', () => {
457
441
  const product = ProductFactory().one();
458
442
  const order = CredentialOrderFactory().one();
459
443
 
460
- render(
461
- <Wrapper>
462
- <EnrollableCourseRunList courseRuns={[courseRun]} order={order} product={product} />
463
- </Wrapper>,
464
- );
444
+ fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
445
+ render(<EnrollableCourseRunList courseRuns={[courseRun]} order={order} product={product} />, {
446
+ wrapper: BaseJoanieAppWrapper,
447
+ });
465
448
 
466
449
  // the list should contain only the course run items, without the call to action button
467
450
  expect(screen.getAllByRole('listitem')).toHaveLength(1);
@@ -502,22 +485,14 @@ describe('CourseProductCourseRuns', () => {
502
485
  });
503
486
 
504
487
  describe('EnrolledCourseRun', () => {
505
- const Wrapper = ({ children }: PropsWithChildren<{}>) => (
506
- <IntlProvider locale="en">
507
- <QueryClientProvider client={createTestQueryClient()}>
508
- <JoanieApiProvider>{children}</JoanieApiProvider>
509
- </QueryClientProvider>
510
- </IntlProvider>
511
- );
512
-
488
+ setupJoanieSession();
513
489
  it('renders enrollment information', () => {
514
490
  const enrollment: Enrollment = EnrollmentFactory().one();
515
491
 
516
- render(
517
- <Wrapper>
518
- <EnrolledCourseRun enrollment={enrollment} />
519
- </Wrapper>,
520
- );
492
+ fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
493
+ render(<EnrolledCourseRun enrollment={enrollment} />, {
494
+ wrapper: BaseJoanieAppWrapper,
495
+ });
521
496
 
522
497
  // - It should render course dates,
523
498
  const $startDate = screen.getByTestId(`enrollment-${enrollment.id}-start-date`);
@@ -560,11 +535,10 @@ describe('CourseProductCourseRuns', () => {
560
535
  },
561
536
  };
562
537
 
563
- render(
564
- <Wrapper>
565
- <EnrolledCourseRun enrollment={newEnrollment} />
566
- </Wrapper>,
567
- );
538
+ fetchMock.get('https://joanie.endpoint/api/v1.0/enrollments/', []);
539
+ render(<EnrolledCourseRun enrollment={newEnrollment} />, {
540
+ wrapper: BaseJoanieAppWrapper,
541
+ });
568
542
 
569
543
  await screen.getByText('You are enrolled');
570
544
  await screen.getByText('The course starts in 2 months');
@@ -1,8 +1,9 @@
1
1
  import { faker } from '@faker-js/faker';
2
- import { screen, getByText, render } from '@testing-library/react';
2
+ import { screen, getByText } from '@testing-library/react';
3
3
  import { CredentialOrderFactory, ProductFactory } from 'utils/test/factories/joanie';
4
4
  import type { CourseRun, CredentialOrder } from 'types/Joanie';
5
5
  import { OrderState } from 'types/Joanie';
6
+ import { render } from 'utils/test/render';
6
7
  import CourseRunItem from '.';
7
8
 
8
9
  jest.mock('../CourseProductCourseRuns', () => ({
@@ -21,7 +22,9 @@ describe('CourseRunItem', () => {
21
22
 
22
23
  const targetCourse = order.target_courses[0];
23
24
 
24
- render(<CourseRunItem targetCourse={targetCourse} order={order} product={product} />);
25
+ render(<CourseRunItem targetCourse={targetCourse} order={order} product={product} />, {
26
+ wrapper: null,
27
+ });
25
28
 
26
29
  // - It should render CourseRunList component
27
30
  const $item = screen.getByTestId(`course-item-${targetCourse.code}`);