Skip to content

Commit 3729431

Browse files
committed
test: Adding test for ImportDetailsPage
1 parent 655d775 commit 3729431

4 files changed

Lines changed: 219 additions & 9 deletions

File tree

src/data/api.mocks.ts

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ export async function mockGetMigrationStatus(migrationId: string): Promise<api.M
1010
return mockGetMigrationStatus.migrationStatusFailedMultipleData;
1111
case mockGetMigrationStatus.migrationIdOneLibrary:
1212
return mockGetMigrationStatus.migrationStatusFailedOneLibraryData;
13+
case mockGetMigrationStatus.migrationIdLoading:
14+
return new Promise(() => {});
15+
case mockGetMigrationStatus.migrationIdInProgress:
16+
return mockGetMigrationStatus.migrationStatusInProgressData;
17+
case mockGetMigrationStatus.migrationIdPartial:
18+
return mockGetMigrationStatus.migrationStatusPartialData;
1319
default:
1420
/* istanbul ignore next */
1521
throw new Error(`mockGetMigrationStatus: unknown migration ID "${migrationId}"`);
@@ -38,13 +44,16 @@ mockGetMigrationStatus.migrationStatusData = {
3844
targetCollectionSlug: 'coll-1',
3945
forwardSourceToTarget: true,
4046
isFailed: false,
41-
targetCollection: null,
47+
targetCollection: {
48+
key: 'coll',
49+
title: 'Test Collection',
50+
},
4251
migrationSummary: {
43-
totalBlocks: 0,
44-
sections: 0,
45-
subsections: 0,
46-
units: 0,
47-
components: 0,
52+
totalBlocks: 6,
53+
sections: 1,
54+
subsections: 1,
55+
units: 1,
56+
components: 3,
4857
unsupported: 0,
4958
},
5059
unsupportedReasons: [],
@@ -198,4 +207,82 @@ mockGetMigrationStatus.migrationStatusFailedOneLibraryData = {
198207
},
199208
],
200209
} as api.MigrateTaskStatusData;
210+
mockGetMigrationStatus.migrationIdLoading = '5';
211+
mockGetMigrationStatus.migrationIdInProgress = '6';
212+
mockGetMigrationStatus.migrationStatusInProgressData = {
213+
uuid: mockGetMigrationStatus.migrationIdInProgress,
214+
state: 'In Progress',
215+
stateText: 'In Progress',
216+
completedSteps: 3,
217+
totalSteps: 9,
218+
attempts: 1,
219+
created: '',
220+
modified: '',
221+
artifacts: [],
222+
parameters: [
223+
{
224+
id: 1,
225+
source: 'legacy-lib-1',
226+
target: 'lib',
227+
compositionLevel: 'component',
228+
repeatHandlingStrategy: 'update',
229+
preserveUrlSlugs: false,
230+
targetCollectionSlug: 'coll-1',
231+
forwardSourceToTarget: true,
232+
isFailed: false,
233+
targetCollection: null,
234+
migrationSummary: {
235+
totalBlocks: 0,
236+
sections: 0,
237+
subsections: 0,
238+
units: 0,
239+
components: 0,
240+
unsupported: 0,
241+
},
242+
unsupportedReasons: [],
243+
},
244+
],
245+
} as api.MigrateTaskStatusData;
246+
mockGetMigrationStatus.migrationIdPartial = '7';
247+
mockGetMigrationStatus.migrationStatusPartialData = {
248+
uuid: mockGetMigrationStatus.migrationIdPartial,
249+
state: 'Succeeded',
250+
stateText: 'Succeeded',
251+
completedSteps: 9,
252+
totalSteps: 9,
253+
attempts: 1,
254+
created: '',
255+
modified: '',
256+
artifacts: [],
257+
parameters: [
258+
{
259+
id: 1,
260+
source: 'legacy-lib-1',
261+
target: 'lib',
262+
compositionLevel: 'component',
263+
repeatHandlingStrategy: 'update',
264+
preserveUrlSlugs: false,
265+
targetCollectionSlug: 'coll-1',
266+
forwardSourceToTarget: true,
267+
isFailed: false,
268+
targetCollection: {
269+
key: 'coll',
270+
title: 'Test Collection',
271+
},
272+
migrationSummary: {
273+
totalBlocks: 7,
274+
sections: 1,
275+
subsections: 1,
276+
units: 1,
277+
components: 3,
278+
unsupported: 1,
279+
},
280+
unsupportedReasons: [{
281+
blockName: 'Legacy library content',
282+
blockType: 'library_content',
283+
reason: 'The block has children, so it is not supported in content libraries',
284+
}],
285+
},
286+
],
287+
} as api.MigrateTaskStatusData;
201288
mockGetMigrationStatus.applyMock = () => jest.spyOn(api, 'getModulestoreMigrationStatus').mockImplementation(mockGetMigrationStatus);

src/data/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ export interface MigrateParameters {
106106
unsupported: number;
107107
}
108108
unsupportedReasons: {
109-
block_name: string;
110-
block_type: string;
109+
blockName: string;
110+
blockType: string;
111111
reason: string;
112112
}[];
113113
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import userEvent from '@testing-library/user-event';
2+
import {
3+
initializeMocks,
4+
render as testRender,
5+
screen,
6+
waitFor,
7+
} from '@src/testUtils';
8+
import { mockGetMigrationStatus } from '@src/data/api.mocks';
9+
import { bulkModulestoreMigrateUrl } from '@src/data/api';
10+
import { ImportDetailsPage } from './ImportDetailsPage';
11+
import { LibraryProvider } from '../common/context/LibraryContext';
12+
import { mockContentLibrary } from '../data/api.mocks';
13+
14+
mockContentLibrary.applyMock();
15+
mockGetMigrationStatus.applyMock();
16+
const { libraryId } = mockContentLibrary;
17+
const mockNavigate = jest.fn();
18+
let axiosMock;
19+
20+
// Mock the useCourseDetails hook
21+
jest.mock('@src/course-outline/data/apiHooks', () => ({
22+
useCourseDetails: jest.fn().mockReturnValue({ isPending: false, data: { title: 'Test Course' } }),
23+
}));
24+
25+
jest.mock('react-router-dom', () => ({
26+
...jest.requireActual('react-router-dom'),
27+
useNavigate: () => mockNavigate,
28+
}));
29+
30+
const render = (migrationTaskId: string) => (
31+
testRender(
32+
<ImportDetailsPage />,
33+
{
34+
extraWrapper: ({ children }: { children: React.ReactNode }) => (
35+
<LibraryProvider libraryId={libraryId}>
36+
{children}
37+
</LibraryProvider>
38+
),
39+
path: '/libraries/:libraryId/import/:courseId/:migrationTaskId',
40+
params: {
41+
libraryId,
42+
migrationTaskId,
43+
courseId: '1',
44+
},
45+
},
46+
)
47+
);
48+
49+
describe('', () => {
50+
beforeEach(() => {
51+
const newMocks = initializeMocks();
52+
axiosMock = newMocks.axiosMock;
53+
});
54+
55+
it('should render loading state', () => {
56+
render(mockGetMigrationStatus.migrationIdLoading);
57+
expect(screen.getByText(/loading\.\.\./i)).toBeInTheDocument();
58+
expect(screen.getByText(/help & support/i)).toBeInTheDocument();
59+
});
60+
61+
it('should render In Progress state', async () => {
62+
render(mockGetMigrationStatus.migrationIdInProgress);
63+
expect(await screen.findByText(/test course is being imported/i));
64+
expect(screen.getByRole('button', {
65+
name: /view imported content/i,
66+
})).toBeDisabled();
67+
});
68+
69+
it('should render Failed state', async () => {
70+
const user = userEvent.setup();
71+
const url = bulkModulestoreMigrateUrl();
72+
axiosMock.onPost(url).reply(200);
73+
render(mockGetMigrationStatus.migrationIdFailed);
74+
expect(await screen.findByText(/test course was not imported into your Library/i));
75+
expect(screen.getByText(/import failed for the following reasons:/i));
76+
const retryImport = screen.getByRole('button', {
77+
name: /re-try import/i,
78+
});
79+
80+
await user.click(retryImport);
81+
await waitFor(() => expect(axiosMock.history.post.length).toBe(1));
82+
});
83+
84+
it('should render Succeeded state', async () => {
85+
render(mockGetMigrationStatus.migrationId);
86+
expect(await screen.findByText(
87+
/test course has been imported to your library in a collection called test collection/i,
88+
));
89+
90+
const viewImportedContentBtn = screen.getByRole('button', {
91+
name: /view imported content/i,
92+
});
93+
94+
await viewImportedContentBtn.click();
95+
await waitFor(() => expect(mockNavigate).toHaveBeenCalledWith('/library/lib:Axim:TEST/collection/coll'));
96+
});
97+
98+
it('should render Partial Succeeded state', async () => {
99+
render(mockGetMigrationStatus.migrationIdPartial);
100+
expect(await screen.findByText(/partial import successful/i)).toBeInTheDocument();
101+
102+
expect(screen.getByText(
103+
/85% of course test course has been imported successfully/i,
104+
)).toBeInTheDocument();
105+
106+
expect(screen.getByRole('cell', {
107+
name: /legacy library content/i,
108+
})).toBeInTheDocument();
109+
expect(screen.getByRole('cell', {
110+
name: /library_content/i,
111+
})).toBeInTheDocument();
112+
expect(screen.getByRole('cell', {
113+
name: /the block has children, so it is not supported in content libraries/i,
114+
}));
115+
116+
const viewImportedContentBtn = screen.getByRole('button', {
117+
name: /view imported content/i,
118+
});
119+
120+
await viewImportedContentBtn.click();
121+
await waitFor(() => expect(mockNavigate).toHaveBeenCalledWith('/library/lib:Axim:TEST/collection/coll'));
122+
});
123+
});

src/library-authoring/import-course/ImportDetailsPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useContext, useState } from 'react';
22
import { Helmet } from 'react-helmet';
3-
import { useNavigate, useParams } from 'react-router';
3+
import { useNavigate, useParams } from 'react-router-dom';
44
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
55
import {
66
Stack, Container, Alert, Layout, Button,

0 commit comments

Comments
 (0)