richie-education 2.25.0-b2.dev124 → 2.25.0-b2.dev127

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.
@@ -1,19 +1,13 @@
1
1
  import { renderHook, act, waitFor } from '@testing-library/react';
2
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
- import { IntlProvider } from 'react-intl';
4
2
  import fetchMock from 'fetch-mock';
5
- import { PropsWithChildren } from 'react';
3
+ import queryString from 'query-string';
6
4
  import { PaginatedResourceQuery } from 'types/Joanie';
7
- import { History, HistoryContext } from 'hooks/useHistory';
8
- import { createTestQueryClient } from 'utils/test/createTestQueryClient';
9
- import { SessionProvider } from 'contexts/SessionContext';
10
5
  import { Deferred } from 'utils/test/deferred';
11
-
12
6
  import { noop } from 'utils';
13
7
  import { mockPaginatedResponse } from 'utils/test/mockPaginatedResponse';
14
8
  import { PER_PAGE } from 'settings';
15
9
  import { HttpError, HttpStatusCode } from 'utils/errors/HttpError';
16
- import { FetchEntityData } from './utils/fetchEntities';
10
+ import { BaseAppWrapper } from 'utils/test/wrappers/BaseAppWrapper';
17
11
  import { QueryConfig, FetchDataFunction } from './utils/fetchEntity';
18
12
  import useUnionResource from '.';
19
13
 
@@ -37,49 +31,6 @@ interface TestDataB {
37
31
  created_on: string;
38
32
  }
39
33
 
40
- const renderUseUnionResource = <
41
- DataA extends FetchEntityData,
42
- DataB extends FetchEntityData,
43
- FiltersA extends PaginatedResourceQuery,
44
- FiltersB extends PaginatedResourceQuery,
45
- >(
46
- queryAConfig: QueryConfig<DataA, FiltersA>,
47
- queryBConfig: QueryConfig<DataB, FiltersB>,
48
- ) => {
49
- const Wrapper = ({ client, children }: PropsWithChildren<{ client?: QueryClient }>) => {
50
- const historyPushState = jest.fn();
51
- const historyReplaceState = jest.fn();
52
- const makeHistoryOf: (params: any) => History = () => [
53
- {
54
- state: { name: '', data: {} },
55
- title: '',
56
- url: `/`,
57
- },
58
- historyPushState,
59
- historyReplaceState,
60
- ];
61
-
62
- return (
63
- <QueryClientProvider client={client ?? createTestQueryClient({ user: true })}>
64
- <IntlProvider locale="en">
65
- <HistoryContext.Provider value={makeHistoryOf({})}>
66
- <SessionProvider>{children}</SessionProvider>
67
- </HistoryContext.Provider>
68
- </IntlProvider>
69
- </QueryClientProvider>
70
- );
71
- };
72
-
73
- return renderHook(
74
- () =>
75
- useUnionResource<DataA, DataB, FiltersA, FiltersB>({
76
- queryAConfig,
77
- queryBConfig,
78
- }),
79
- { wrapper: Wrapper },
80
- );
81
- };
82
-
83
34
  describe('useUnionResource', () => {
84
35
  const perPage = PER_PAGE.useUnionResources;
85
36
  let dataAList: TestDataA[];
@@ -111,14 +62,14 @@ describe('useUnionResource', () => {
111
62
 
112
63
  { name: 'TestDataB', id: '14', created_on: '2022-12-03' },
113
64
  ];
114
- const dummyFetchWrapper = async (url: string) => {
115
- const res = await fetch(url);
65
+ const dummyFetchWrapper = async (url: string, queryParams: { [key: string]: any }) => {
66
+ const res = await fetch(`${url}?${queryString.stringify(queryParams)}`);
116
67
  return res.json();
117
68
  };
118
- const fetchDataA = ({ page }: { page: number }) =>
119
- dummyFetchWrapper(`http://data.a/?page=${page}`);
69
+ const fetchDataA = ({ page, isFiltered }: { page: number; isFiltered?: boolean }) =>
70
+ dummyFetchWrapper('http://data.a/', { page, isFiltered });
120
71
  const fetchDataB = ({ page }: { page: number }) =>
121
- dummyFetchWrapper(`http://data.b/?page=${page}`);
72
+ dummyFetchWrapper('http://data.b/', { page });
122
73
 
123
74
  queryAConfig = {
124
75
  queryKey: ['resourceA'],
@@ -132,11 +83,6 @@ describe('useUnionResource', () => {
132
83
  };
133
84
  });
134
85
 
135
- afterEach(() => {
136
- jest.clearAllMocks();
137
- fetchMock.restore();
138
- });
139
-
140
86
  it('should handle loading state', async () => {
141
87
  const dataADeferred = new Deferred();
142
88
  const dataBDeferred = new Deferred();
@@ -144,12 +90,16 @@ describe('useUnionResource', () => {
144
90
  const pendingDataBPromise = () => dataBDeferred.promise;
145
91
  queryAConfig.fn = pendingDataAPromise as FetchDataFunction<TestDataA, TestDataAFilters>;
146
92
  queryBConfig.fn = pendingDataBPromise as FetchDataFunction<TestDataB, PaginatedResourceQuery>;
147
- const { result } = renderUseUnionResource<
148
- TestDataA,
149
- TestDataB,
150
- TestDataAFilters,
151
- PaginatedResourceQuery
152
- >(queryAConfig, queryBConfig);
93
+
94
+ const { result } = renderHook(
95
+ () =>
96
+ useUnionResource<TestDataA, TestDataB, TestDataAFilters, PaginatedResourceQuery>({
97
+ queryAConfig,
98
+ queryBConfig,
99
+ }),
100
+ { wrapper: BaseAppWrapper },
101
+ );
102
+
153
103
  expect(result.current.isLoading).toBe(true);
154
104
  expect(result.current.hasMore).toBe(false);
155
105
 
@@ -164,12 +114,15 @@ describe('useUnionResource', () => {
164
114
  it('should render less than 1 page of dataA', async () => {
165
115
  fetchMock.get('http://data.a/?page=1', mockPaginatedResponse([dataAList[0]], 1, false));
166
116
  fetchMock.get('http://data.b/?page=1', mockPaginatedResponse([], 0, false));
167
- const { result } = renderUseUnionResource<
168
- TestDataA,
169
- TestDataB,
170
- TestDataAFilters,
171
- PaginatedResourceQuery
172
- >(queryAConfig, queryBConfig);
117
+
118
+ const { result } = renderHook(
119
+ () =>
120
+ useUnionResource<TestDataA, TestDataB, TestDataAFilters, PaginatedResourceQuery>({
121
+ queryAConfig,
122
+ queryBConfig,
123
+ }),
124
+ { wrapper: BaseAppWrapper },
125
+ );
173
126
 
174
127
  await waitFor(() => expect(result.current.isLoading).toBe(false));
175
128
  expect(result.current.hasMore).toBe(false);
@@ -180,12 +133,15 @@ describe('useUnionResource', () => {
180
133
  it('should render less than 1 page of dataB', async () => {
181
134
  fetchMock.get('http://data.a/?page=1', mockPaginatedResponse([], 0, false));
182
135
  fetchMock.get('http://data.b/?page=1', mockPaginatedResponse([dataBList[0]], 1, false));
183
- const { result } = renderUseUnionResource<
184
- TestDataA,
185
- TestDataB,
186
- TestDataAFilters,
187
- PaginatedResourceQuery
188
- >(queryAConfig, queryBConfig);
136
+
137
+ const { result } = renderHook(
138
+ () =>
139
+ useUnionResource<TestDataA, TestDataB, TestDataAFilters, PaginatedResourceQuery>({
140
+ queryAConfig,
141
+ queryBConfig,
142
+ }),
143
+ { wrapper: BaseAppWrapper },
144
+ );
189
145
 
190
146
  await waitFor(() => expect(result.current.isLoading).toBe(false));
191
147
  expect(result.current.hasMore).toBe(false);
@@ -196,12 +152,15 @@ describe('useUnionResource', () => {
196
152
  it('should renders less than 1 page of both dataA and dataB', async () => {
197
153
  fetchMock.get('http://data.a/?page=1', mockPaginatedResponse([dataAList[0]], 1, false));
198
154
  fetchMock.get('http://data.b/?page=1', mockPaginatedResponse([dataBList[0]], 1, false));
199
- const { result } = renderUseUnionResource<
200
- TestDataA,
201
- TestDataB,
202
- TestDataAFilters,
203
- PaginatedResourceQuery
204
- >(queryAConfig, queryBConfig);
155
+
156
+ const { result } = renderHook(
157
+ () =>
158
+ useUnionResource<TestDataA, TestDataB, TestDataAFilters, PaginatedResourceQuery>({
159
+ queryAConfig,
160
+ queryBConfig,
161
+ }),
162
+ { wrapper: BaseAppWrapper },
163
+ );
205
164
 
206
165
  await waitFor(() => expect(result.current.isLoading).toBe(false));
207
166
  expect(result.current.hasMore).toBe(false);
@@ -237,12 +196,14 @@ describe('useUnionResource', () => {
237
196
  mockPaginatedResponse(dataBList.slice(perPage * 2, perPage * 3), dataAList.length, false),
238
197
  );
239
198
 
240
- const { result } = renderUseUnionResource<
241
- TestDataA,
242
- TestDataB,
243
- TestDataAFilters,
244
- PaginatedResourceQuery
245
- >(queryAConfig, queryBConfig);
199
+ const { result } = renderHook(
200
+ () =>
201
+ useUnionResource<TestDataA, TestDataB, TestDataAFilters, PaginatedResourceQuery>({
202
+ queryAConfig,
203
+ queryBConfig,
204
+ }),
205
+ { wrapper: BaseAppWrapper },
206
+ );
246
207
 
247
208
  await waitFor(() => expect(result.current.isLoading).toBe(false));
248
209
  expect(result.current.hasMore).toBe(true);
@@ -297,12 +258,16 @@ describe('useUnionResource', () => {
297
258
  const dataADeferred = new Deferred();
298
259
  const pendingDataAPromise = () => dataADeferred.promise;
299
260
  queryAConfig.fn = pendingDataAPromise as FetchDataFunction<TestDataA, TestDataAFilters>;
300
- const { result } = renderUseUnionResource<
301
- TestDataA,
302
- TestDataB,
303
- TestDataAFilters,
304
- PaginatedResourceQuery
305
- >(queryAConfig, queryBConfig);
261
+
262
+ const { result } = renderHook(
263
+ () =>
264
+ useUnionResource<TestDataA, TestDataB, TestDataAFilters, PaginatedResourceQuery>({
265
+ queryAConfig,
266
+ queryBConfig,
267
+ }),
268
+ { wrapper: BaseAppWrapper },
269
+ );
270
+
306
271
  expect(result.current.isLoading).toBe(true);
307
272
 
308
273
  await act(() => {
@@ -313,4 +278,40 @@ describe('useUnionResource', () => {
313
278
  expect(result.current.isLoading).toBe(false);
314
279
  expect(result.current.error).toBe('An error occurred while fetching data. Please retry later.');
315
280
  });
281
+
282
+ it('should refetch data when filters change', async () => {
283
+ fetchMock.get('http://data.a/?page=1', mockPaginatedResponse([dataAList[0]], 1, false));
284
+ fetchMock.get('http://data.b/?page=1', mockPaginatedResponse([], 0, false));
285
+
286
+ const { result, rerender } = renderHook(
287
+ (queries: {
288
+ queryA?: QueryConfig<TestDataA, TestDataAFilters>;
289
+ queryB?: QueryConfig<TestDataB, PaginatedResourceQuery>;
290
+ }) =>
291
+ useUnionResource<TestDataA, TestDataB, TestDataAFilters, PaginatedResourceQuery>({
292
+ queryAConfig: queries?.queryA || queryAConfig,
293
+ queryBConfig: queries?.queryB || queryBConfig,
294
+ }),
295
+ { wrapper: BaseAppWrapper },
296
+ );
297
+
298
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
299
+ let calledUrls = fetchMock.calls().map((call) => call[0]);
300
+ expect(calledUrls).toHaveLength(2);
301
+ expect(calledUrls).toContain('http://data.a/?page=1');
302
+ expect(calledUrls).toContain('http://data.b/?page=1');
303
+
304
+ queryAConfig.filters = { isFiltered: true };
305
+ fetchMock.get(
306
+ 'http://data.a/?isFiltered=true&page=1',
307
+ mockPaginatedResponse([dataAList[0]], 1, false),
308
+ );
309
+ rerender({ queryA: queryAConfig, queryB: queryBConfig });
310
+ expect(result.current.isLoading).toBe(true);
311
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
312
+
313
+ calledUrls = fetchMock.calls().map((call) => call[0]);
314
+ expect(calledUrls).toHaveLength(4);
315
+ expect(calledUrls).toContain('http://data.a/?isFiltered=true&page=1');
316
+ });
316
317
  });
@@ -90,6 +90,8 @@ const useUnionResource = <
90
90
  const eofRef = useRef<Record<string, number>>(queryClient.getQueryData(eofQueryKey) ?? {});
91
91
  log('eof', eofRef.current);
92
92
 
93
+ const [unionQueryKey, setUnionQueryKey] = useState<string>();
94
+
93
95
  const reset = () => {
94
96
  setStack([]);
95
97
  setPage(0);
@@ -104,6 +106,18 @@ const useUnionResource = <
104
106
  useQueryKeyInvalidateListener(queryBConfig.queryKey, reset);
105
107
  }
106
108
 
109
+ useEffect(() => {
110
+ // filters have changes, new results will be fetch.
111
+ // let's reset every previous fetches states
112
+ reset();
113
+
114
+ // We need to fetch new results.
115
+ // reset all states isn't enought. If we've a research without results
116
+ // then the next reset would do nothing.
117
+ // to force execution of useEffect::fetchNewPage(), we use a uniq key build with current queries filters.
118
+ setUnionQueryKey(JSON.stringify(queryAConfig.filters) + JSON.stringify(queryBConfig.filters));
119
+ }, [JSON.stringify(queryAConfig.filters), JSON.stringify(queryBConfig.filters)]);
120
+
107
121
  useEffect(() => {
108
122
  async function fetchNewPage() {
109
123
  const {
@@ -145,11 +159,18 @@ const useUnionResource = <
145
159
 
146
160
  // we request more entities than we can display in the right order
147
161
  // it's time for new fetching and sorting.
148
- if (cursor > integrityCount) {
162
+ if (!isSyncing && cursor > integrityCount) {
149
163
  setIsSyncing(true);
150
164
  fetchNewPage();
151
165
  }
152
- }, [cursor, stack.length]); // stack.length is added in the dependency array to force a new fetch on reset.
166
+ }, [
167
+ cursor,
168
+ // FIXME(rlecellier): when stack.length === 0, invalidate the query will not refetch.
169
+ // stack.length is added in the dependency array to force a new fetch on reset.
170
+ stack.length,
171
+ // unionQueryKey assure that we refetch data when query filters change.
172
+ unionQueryKey,
173
+ ]);
153
174
 
154
175
  const cursorToUse = Math.min(cursor, integrityCount);
155
176
  const next = () => {
@@ -1,13 +1,8 @@
1
- import { act, getByRole, render, screen, waitFor } from '@testing-library/react';
2
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
- import { IntlProvider } from 'react-intl';
1
+ import { act, getByRole, screen, waitFor } from '@testing-library/react';
2
+ import { QueryClient } from '@tanstack/react-query';
4
3
  import fetchMock from 'fetch-mock';
5
4
  import userEvent from '@testing-library/user-event';
6
- import {
7
- UserFactory,
8
- RichieContextFactory as mockRichieContextFactory,
9
- } from 'utils/test/factories/richie';
10
- import { History, HistoryContext } from 'hooks/useHistory';
5
+ import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
11
6
  import { DashboardTest } from 'widgets/Dashboard/components/DashboardTest';
12
7
  import {
13
8
  CourseProductRelationFactory,
@@ -15,7 +10,6 @@ import {
15
10
  CredentialOrderFactory,
16
11
  } from 'utils/test/factories/joanie';
17
12
  import { createTestQueryClient } from 'utils/test/createTestQueryClient';
18
- import { SessionProvider } from 'contexts/SessionContext';
19
13
  import { LearnerDashboardPaths } from 'widgets/Dashboard/utils/learnerRouteMessages';
20
14
  import { CourseLight, CourseProductRelation, Enrollment, CredentialOrder } from 'types/Joanie';
21
15
  import { expectNoSpinner, expectSpinner } from 'utils/test/expectSpinner';
@@ -25,6 +19,9 @@ import { isOrder } from 'pages/DashboardCourses/useOrdersEnrollments';
25
19
  import { noop } from 'utils';
26
20
  import { PER_PAGE } from 'settings';
27
21
  import { HttpStatusCode } from 'utils/errors/HttpError';
22
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
23
+ import { render } from 'utils/test/render';
24
+ import { BaseJoanieAppWrapper } from 'utils/test/wrappers/BaseJoanieAppWrapper';
28
25
 
29
26
  jest.mock('utils/context', () => ({
30
27
  __esModule: true,
@@ -52,44 +49,8 @@ jest.mock('hooks/useIntersectionObserver', () => ({
52
49
  }));
53
50
 
54
51
  describe('<DashboardCourses/>', () => {
52
+ setupJoanieSession();
55
53
  const perPage = PER_PAGE.useOrdersEnrollments;
56
- const historyPushState = jest.fn();
57
- const historyReplaceState = jest.fn();
58
- const makeHistoryOf: (params: any) => History = () => [
59
- {
60
- state: { name: '', data: {} },
61
- title: '',
62
- url: `/`,
63
- },
64
- historyPushState,
65
- historyReplaceState,
66
- ];
67
-
68
- beforeEach(() => {
69
- fetchMock.get('https://joanie.endpoint/api/v1.0/addresses/', []);
70
- fetchMock.get('https://joanie.endpoint/api/v1.0/credit-cards/', []);
71
- fetchMock.get('https://joanie.endpoint/api/v1.0/orders/', []);
72
- });
73
-
74
- afterEach(() => {
75
- jest.clearAllMocks();
76
- fetchMock.restore();
77
- });
78
-
79
- const Wrapper = ({ client }: { client?: QueryClient }) => {
80
- const user = UserFactory().one();
81
- return (
82
- <QueryClientProvider client={client ?? createTestQueryClient({ user })}>
83
- <IntlProvider locale="en">
84
- <HistoryContext.Provider value={makeHistoryOf({})}>
85
- <SessionProvider>
86
- <DashboardTest initialRoute={LearnerDashboardPaths.COURSES} />
87
- </SessionProvider>
88
- </HistoryContext.Provider>
89
- </IntlProvider>
90
- </QueryClientProvider>
91
- );
92
- };
93
54
 
94
55
  const mockOrders = (orders: CredentialOrder[], client?: QueryClient) => {
95
56
  const relations: Record<string, CourseProductRelation> = {};
@@ -150,7 +111,9 @@ describe('<DashboardCourses/>', () => {
150
111
  enrollmentsDeferred.promise,
151
112
  );
152
113
 
153
- render(<Wrapper />);
114
+ render(<DashboardTest initialRoute={LearnerDashboardPaths.COURSES} />, {
115
+ wrapper: BaseJoanieAppWrapper,
116
+ });
154
117
 
155
118
  await expectSpinner('Loading orders and enrollments...');
156
119
  expect(await screen.queryByRole('button', { name: 'Load more' })).not.toBeInTheDocument();
@@ -242,7 +205,9 @@ describe('<DashboardCourses/>', () => {
242
205
 
243
206
  const entities = merge(orders, enrollments);
244
207
 
245
- render(<Wrapper client={client} />);
208
+ render(<DashboardTest initialRoute={LearnerDashboardPaths.COURSES} />, {
209
+ wrapper: BaseJoanieAppWrapper,
210
+ });
246
211
 
247
212
  // Slice 1.
248
213
  await expectNoSpinner('Loading orders and enrollments...');
@@ -277,7 +242,10 @@ describe('<DashboardCourses/>', () => {
277
242
  { results: [], next: null, previous: null, count: 0 },
278
243
  );
279
244
 
280
- render(<Wrapper />);
245
+ render(<DashboardTest initialRoute={LearnerDashboardPaths.COURSES} />, {
246
+ wrapper: BaseJoanieAppWrapper,
247
+ });
248
+
281
249
  ordersDeferred.resolve({
282
250
  status: HttpStatusCode.INTERNAL_SERVER_ERROR,
283
251
  body: 'Internal Server Error',
@@ -0,0 +1,19 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import { SessionProvider } from 'contexts/SessionContext';
3
+ import { IntlWrapper } from './IntlWrapper';
4
+ import { ReactQueryWrapper } from './ReactQueryWrapper';
5
+ import { AppWrapperProps } from './types';
6
+
7
+ export const BaseAppWrapper = ({
8
+ children,
9
+ intlOptions,
10
+ queryOptions,
11
+ }: PropsWithChildren<AppWrapperProps>) => {
12
+ return (
13
+ <IntlWrapper {...(intlOptions || { locale: 'en' })}>
14
+ <ReactQueryWrapper {...(queryOptions || {})}>
15
+ <SessionProvider>{children}</SessionProvider>
16
+ </ReactQueryWrapper>
17
+ </IntlWrapper>
18
+ );
19
+ };
@@ -0,0 +1,20 @@
1
+ import { PropsWithChildren } from 'react';
2
+
3
+ import JoanieSessionProvider from 'contexts/SessionContext/JoanieSessionProvider';
4
+ import { IntlWrapper } from './IntlWrapper';
5
+ import { ReactQueryWrapper } from './ReactQueryWrapper';
6
+ import { AppWrapperProps } from './types';
7
+
8
+ export const BaseJoanieAppWrapper = ({
9
+ children,
10
+ intlOptions,
11
+ queryOptions,
12
+ }: PropsWithChildren<AppWrapperProps>) => {
13
+ return (
14
+ <IntlWrapper {...(intlOptions || { locale: 'en' })}>
15
+ <ReactQueryWrapper {...(queryOptions || {})}>
16
+ <JoanieSessionProvider>{children}</JoanieSessionProvider>
17
+ </ReactQueryWrapper>
18
+ </IntlWrapper>
19
+ );
20
+ };
@@ -1,12 +1,10 @@
1
1
  import { CunninghamProvider } from '@openfun/cunningham-react';
2
2
  import { PropsWithChildren } from 'react';
3
3
  import fetchMock from 'fetch-mock';
4
- import JoanieSessionProvider from 'contexts/SessionContext/JoanieSessionProvider';
5
4
  import { DashboardBreadcrumbsProvider } from 'widgets/Dashboard/contexts/DashboardBreadcrumbsContext';
6
- import { IntlWrapper } from './IntlWrapper';
7
- import { ReactQueryWrapper } from './ReactQueryWrapper';
8
5
  import { RouterWrapper } from './RouterWrapper';
9
6
  import { AppWrapperProps } from './types';
7
+ import { BaseJoanieAppWrapper } from './BaseJoanieAppWrapper';
10
8
 
11
9
  export const setupJoanieSession = () => {
12
10
  beforeEach(() => {
@@ -21,10 +19,6 @@ export const setupJoanieSession = () => {
21
19
  };
22
20
  };
23
21
 
24
- export const JoanieSessionWrapper = ({ children }: PropsWithChildren) => {
25
- return <JoanieSessionProvider>{children}</JoanieSessionProvider>;
26
- };
27
-
28
22
  export const JoanieAppWrapper = ({
29
23
  children,
30
24
  intlOptions,
@@ -32,16 +26,12 @@ export const JoanieAppWrapper = ({
32
26
  routerOptions,
33
27
  }: PropsWithChildren<AppWrapperProps>) => {
34
28
  return (
35
- <IntlWrapper {...(intlOptions || { locale: 'en' })}>
29
+ <BaseJoanieAppWrapper intlOptions={intlOptions} queryOptions={queryOptions}>
36
30
  <CunninghamProvider>
37
- <ReactQueryWrapper {...(queryOptions || {})}>
38
- <JoanieSessionWrapper>
39
- <DashboardBreadcrumbsProvider>
40
- <RouterWrapper {...routerOptions}>{children}</RouterWrapper>
41
- </DashboardBreadcrumbsProvider>
42
- </JoanieSessionWrapper>
43
- </ReactQueryWrapper>
31
+ <DashboardBreadcrumbsProvider>
32
+ <RouterWrapper {...routerOptions}>{children}</RouterWrapper>
33
+ </DashboardBreadcrumbsProvider>
44
34
  </CunninghamProvider>
45
- </IntlWrapper>
35
+ </BaseJoanieAppWrapper>
46
36
  );
47
37
  };
@@ -1,13 +1,9 @@
1
1
  // FIXME: this test is about useUnionResource behavior.
2
2
  // we need to rewrite it in useUnionResource tests suite as small and generic as possible.
3
- import { QueryClientProvider } from '@tanstack/react-query';
4
- import { IntlProvider } from 'react-intl';
5
3
  import fetchMock from 'fetch-mock';
6
- import { act, render, screen, waitFor, within } from '@testing-library/react';
4
+ import { act, screen, waitFor, within } from '@testing-library/react';
7
5
  import userEvent from '@testing-library/user-event';
8
6
  import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
9
- import { createTestQueryClient } from 'utils/test/createTestQueryClient';
10
- import { SessionProvider } from 'contexts/SessionContext';
11
7
  import { DashboardTest } from 'widgets/Dashboard/components/DashboardTest';
12
8
  import {
13
9
  ContractFactory,
@@ -19,6 +15,9 @@ import { LearnerDashboardPaths } from 'widgets/Dashboard/utils/learnerRouteMessa
19
15
  import { Deferred } from 'utils/test/deferred';
20
16
  import { expectNoSpinner, expectSpinner } from 'utils/test/expectSpinner';
21
17
  import { CONTRACT_SETTINGS } from 'settings';
18
+ import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
19
+ import { render } from 'utils/test/render';
20
+ import { BaseJoanieAppWrapper } from 'utils/test/wrappers/BaseJoanieAppWrapper';
22
21
 
23
22
  jest.mock('utils/context', () => ({
24
23
  __esModule: true,
@@ -35,31 +34,15 @@ jest.mock('hooks/useIntersectionObserver', () => ({
35
34
  }));
36
35
 
37
36
  describe('<DashboardItemOrder/> Contract', () => {
38
- const Wrapper = (route: string) => {
39
- return (
40
- <QueryClientProvider client={createTestQueryClient({ user: true })}>
41
- <IntlProvider locale="en">
42
- <SessionProvider>
43
- <DashboardTest initialRoute={route} />
44
- </SessionProvider>
45
- </IntlProvider>
46
- </QueryClientProvider>
47
- );
48
- };
37
+ setupJoanieSession();
49
38
 
50
39
  beforeEach(() => {
51
40
  jest.useFakeTimers();
52
41
  jest.clearAllTimers();
53
-
54
- fetchMock.get('https://joanie.endpoint/api/v1.0/addresses/', []);
55
- fetchMock.get('https://joanie.endpoint/api/v1.0/credit-cards/', []);
56
- fetchMock.get('https://joanie.endpoint/api/v1.0/orders/', []);
57
42
  });
58
43
 
59
44
  afterEach(() => {
60
45
  jest.restoreAllMocks();
61
- jest.clearAllMocks();
62
- fetchMock.restore();
63
46
  });
64
47
 
65
48
  describe('writable', () => {
@@ -103,9 +86,10 @@ describe('<DashboardItemOrder/> Contract', () => {
103
86
  // RTL too. See https://github.com/testing-library/user-event/issues/833.
104
87
  const user = userEvent.setup({ delay: null });
105
88
 
106
- render(Wrapper(LearnerDashboardPaths.COURSES));
89
+ render(<DashboardTest initialRoute={LearnerDashboardPaths.COURSES} />, {
90
+ wrapper: BaseJoanieAppWrapper,
91
+ });
107
92
 
108
- // console.log('apiCalls:2', fetchMock.calls().length);
109
93
  await expectNoSpinner('Loading orders and enrollments...');
110
94
 
111
95
  expect(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "richie-education",
3
- "version": "2.25.0-b2.dev124",
3
+ "version": "2.25.0-b2.dev127",
4
4
  "description": "A CMS to build learning portals for Open Education",
5
5
  "main": "sandbox/manage.py",
6
6
  "scripts": {