test: fix test code improperly using/missing 'await' (#2560)
This commit is contained in:
@@ -125,10 +125,13 @@ describe('ORASettings', () => {
|
||||
});
|
||||
|
||||
it('Displays title, helper text and badge when flexible peer grading button is enabled', async () => {
|
||||
renderComponent();
|
||||
await mockStore({ apiStatus: 200, enabled: true });
|
||||
renderComponent();
|
||||
|
||||
waitFor(() => {
|
||||
const checkbox = await screen.getByRole('checkbox', { name: /Flex Peer Grading/ });
|
||||
expect(checkbox).toBeChecked();
|
||||
|
||||
await waitFor(() => {
|
||||
const label = screen.getByText(messages.enableFlexPeerGradeLabel.defaultMessage);
|
||||
const enableBadge = screen.getByTestId('enable-badge');
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { fireEvent, render, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
@@ -22,7 +21,6 @@ jest.mock('react-textarea-autosize', () => jest.fn((props) => (
|
||||
<textarea
|
||||
{...props}
|
||||
onFocus={() => {}}
|
||||
onBlur={() => {}}
|
||||
/>
|
||||
)));
|
||||
|
||||
@@ -86,10 +84,10 @@ describe('<SettingCard />', () => {
|
||||
await waitFor(() => {
|
||||
expect(inputBox).toHaveValue('3, 2, 1');
|
||||
});
|
||||
await (async () => {
|
||||
await user.tab(); // blur off of the input.
|
||||
await waitFor(() => {
|
||||
expect(setEdited).toHaveBeenCalled();
|
||||
expect(handleBlur).toHaveBeenCalled();
|
||||
});
|
||||
fireEvent.focusOut(inputBox);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@ const SettingCard = ({
|
||||
const { deprecated, help, displayName } = settingData;
|
||||
const initialValue = JSON.stringify(settingData.value, null, 4);
|
||||
const [isOpen, open, close] = useToggle(false);
|
||||
const [target, setTarget] = useState(null);
|
||||
const [target, setTarget] = useState<HTMLButtonElement | null>(null);
|
||||
const [newValue, setNewValue] = useState(initialValue);
|
||||
|
||||
const handleSettingChange = (e) => {
|
||||
@@ -118,7 +118,7 @@ SettingCard.propTypes = {
|
||||
deprecated: PropTypes.bool,
|
||||
help: PropTypes.string,
|
||||
displayName: PropTypes.string,
|
||||
value: PropTypes.PropTypes.oneOfType([
|
||||
value: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.bool,
|
||||
PropTypes.number,
|
||||
@@ -65,7 +65,7 @@ describe('CertificateDetails', () => {
|
||||
|
||||
await user.type(input, newInputValue);
|
||||
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
expect(input.value).toBe(newInputValue);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -96,7 +96,7 @@ describe('CertificateSignatories', () => {
|
||||
expect(useCreateSignatory().handleAddSignatory).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls remove for the correct signatory when delete icon is clicked', async () => {
|
||||
it.skip('calls remove for the correct signatory when delete icon is clicked', async () => {
|
||||
const user = userEvent.setup();
|
||||
const { getAllByRole } = renderComponent(defaultProps);
|
||||
|
||||
@@ -105,7 +105,9 @@ describe('CertificateSignatories', () => {
|
||||
|
||||
await user.click(deleteIcons[0]);
|
||||
|
||||
waitFor(() => {
|
||||
// FIXME: this isn't called because the whole 'useEditSignatory' hook
|
||||
// which calls it is mocked out.
|
||||
await waitFor(() => {
|
||||
expect(mockArrayHelpers.remove).toHaveBeenCalledWith(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { Provider } from 'react-redux';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
@@ -30,6 +30,7 @@ const initialState = {
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
index: 0,
|
||||
...signatoriesMock[0],
|
||||
showDeleteButton: true,
|
||||
isEdit: true,
|
||||
@@ -62,15 +63,20 @@ describe('Signatory Component', () => {
|
||||
it('handles input change', async () => {
|
||||
const user = userEvent.setup();
|
||||
const handleChange = jest.fn();
|
||||
const { getByPlaceholderText } = renderSignatory({ ...defaultProps, handleChange });
|
||||
const input = getByPlaceholderText(messages.namePlaceholder.defaultMessage);
|
||||
renderSignatory({ ...defaultProps, handleChange });
|
||||
const input = screen.getByPlaceholderText(messages.namePlaceholder.defaultMessage);
|
||||
const newInputValue = 'Jane Doe';
|
||||
|
||||
await user.type(input, newInputValue, { name: 'signatories[0].name' });
|
||||
expect(handleChange).not.toHaveBeenCalled();
|
||||
expect(input.value).not.toBe(newInputValue);
|
||||
await user.type(input, newInputValue);
|
||||
|
||||
waitFor(() => {
|
||||
expect(handleChange).toHaveBeenCalledWith(expect.anything());
|
||||
expect(input.value).toBe(newInputValue);
|
||||
await waitFor(() => {
|
||||
// This is not a great test; handleChange() gets called for each key press:
|
||||
expect(handleChange).toHaveBeenCalledTimes(newInputValue.length);
|
||||
// And the input value never actually changes because it's a controlled component
|
||||
// and we pass the name in as a prop, which hasn't changed.
|
||||
// expect(input.value).toBe(newInputValue);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('HeaderButtons Component', () => {
|
||||
const dropdownButton = getByRole('button', { name: certificatesDataMock.courseModes[0] });
|
||||
await user.click(dropdownButton);
|
||||
|
||||
const verifiedMode = await getByRole('button', { name: certificatesDataMock.courseModes[1] });
|
||||
const verifiedMode = getByRole('button', { name: certificatesDataMock.courseModes[1] });
|
||||
await user.click(verifiedMode);
|
||||
|
||||
await waitFor(() => {
|
||||
|
||||
@@ -114,7 +114,7 @@ describe('<CourseLibraries />', () => {
|
||||
const dismissBtn = await screen.findByRole('button', { name: 'Dismiss' });
|
||||
await user.click(dismissBtn);
|
||||
expect(allTab).toHaveAttribute('aria-selected', 'true');
|
||||
waitFor(() => expect(alert).not.toBeInTheDocument());
|
||||
await waitFor(() => expect(alert).not.toBeInTheDocument());
|
||||
// review updates button
|
||||
const reviewActionBtn = await screen.findByRole('button', { name: 'Review Updates' });
|
||||
await user.click(reviewActionBtn);
|
||||
|
||||
@@ -33,10 +33,10 @@ jest.mock('react-redux', () => ({
|
||||
expect(newBtn).toBeInTheDocument();
|
||||
const useBtn = await screen.findByRole('button', { name: `Use ${containerType} from library` });
|
||||
expect(useBtn).toBeInTheDocument();
|
||||
userEvent.click(newBtn);
|
||||
waitFor(() => expect(newClickHandler).toHaveBeenCalled());
|
||||
userEvent.click(useBtn);
|
||||
waitFor(() => expect(useFromLibClickHandler).toHaveBeenCalled());
|
||||
await userEvent.click(newBtn);
|
||||
await waitFor(() => expect(newClickHandler).toHaveBeenCalled());
|
||||
await userEvent.click(useBtn);
|
||||
await waitFor(() => expect(useFromLibClickHandler).toHaveBeenCalled());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2218,7 +2218,7 @@ describe('<CourseUnit />', () => {
|
||||
const currentSubSectionName = courseSectionVerticalMock.xblock_info.ancestor_info.ancestors[1].display_name;
|
||||
const helpLinkUrl = 'https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/latest/developing_course/course_components.html#components-that-contain-other-components';
|
||||
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
const unitHeaderTitle = screen.getByTestId('unit-header-title');
|
||||
expect(screen.getByText(unitDisplayName)).toBeInTheDocument();
|
||||
expect(within(unitHeaderTitle).getByRole('button', { name: headerTitleMessages.altButtonEdit.defaultMessage })).toBeInTheDocument();
|
||||
@@ -2291,19 +2291,17 @@ describe('<CourseUnit />', () => {
|
||||
});
|
||||
|
||||
it('renders and navigates to the new HTML XBlock editor after xblock duplicating', async () => {
|
||||
render(<RootWrapper />);
|
||||
const updatedCourseVerticalChildrenMock = JSON.parse(JSON.stringify(courseVerticalChildrenMock));
|
||||
const targetBlockId = updatedCourseVerticalChildrenMock.children[1].block_id;
|
||||
|
||||
updatedCourseVerticalChildrenMock.children = updatedCourseVerticalChildrenMock.children
|
||||
.map((child) => (child.block_id === targetBlockId
|
||||
? { ...child, block_type: 'html' }
|
||||
: child));
|
||||
// Convert the second child from drag and drop to HTML:
|
||||
const targetChild = updatedCourseVerticalChildrenMock.children[1];
|
||||
targetChild.block_type = 'html';
|
||||
targetChild.name = 'Test HTML Block';
|
||||
targetChild.block_id = 'block-v1:OpenedX+L153+3T2023+type@html+block@test123original';
|
||||
|
||||
axiosMock
|
||||
.onPost(postXBlockBaseApiUrl({
|
||||
parent_locator: blockId,
|
||||
duplicate_source_locator: courseVerticalChildrenMock.children[0].block_id,
|
||||
duplicate_source_locator: targetChild.block_id,
|
||||
}))
|
||||
.replyOnce(200, { locator: '1234567890' });
|
||||
|
||||
@@ -2311,21 +2309,20 @@ describe('<CourseUnit />', () => {
|
||||
.onGet(getCourseVerticalChildrenApiUrl(blockId))
|
||||
.reply(200, updatedCourseVerticalChildrenMock);
|
||||
|
||||
render(<RootWrapper />);
|
||||
await executeThunk(fetchCourseVerticalChildrenData(blockId), store.dispatch);
|
||||
|
||||
await waitFor(() => {
|
||||
const iframe = screen.getByTitle(xblockContainerIframeMessages.xblockIframeTitle.defaultMessage);
|
||||
expect(iframe).toBeInTheDocument();
|
||||
simulatePostMessageEvent(messageTypes.currentXBlockId, {
|
||||
id: targetBlockId,
|
||||
});
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
simulatePostMessageEvent(messageTypes.duplicateXBlock, {});
|
||||
simulatePostMessageEvent(messageTypes.newXBlockEditor, {});
|
||||
expect(mockedUsedNavigate)
|
||||
.toHaveBeenCalledWith(`/course/${courseId}/editor/html/${targetBlockId}`, { replace: true });
|
||||
// After duplicating, the editor modal will open:
|
||||
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
||||
simulatePostMessageEvent(messageTypes.duplicateXBlock, { usageId: targetChild.block_id });
|
||||
simulatePostMessageEvent(messageTypes.newXBlockEditor, { blockType: 'html', usageId: targetChild.block_id });
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole('dialog')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ describe('CustomPages', () => {
|
||||
it('should update page order on drag', async () => {
|
||||
renderComponent();
|
||||
await mockStore(RequestStatus.SUCCESSFUL);
|
||||
const buttons = await screen.queryAllByRole('button');
|
||||
const buttons = screen.queryAllByRole('button');
|
||||
const draggableButton = buttons[9];
|
||||
expect(draggableButton).toBeVisible();
|
||||
await act(async () => {
|
||||
|
||||
@@ -48,15 +48,15 @@ describe('cms api', () => {
|
||||
});
|
||||
describe('apiMethods', () => {
|
||||
describe('fetchBlockId', () => {
|
||||
it('should call get with url.blocks', () => {
|
||||
apiMethods.fetchBlockById({ blockId, studioEndpointUrl });
|
||||
it('should call get with url.blocks', async () => {
|
||||
await apiMethods.fetchBlockById({ blockId, studioEndpointUrl });
|
||||
expect(get).toHaveBeenCalledWith(urls.block({ blockId, studioEndpointUrl }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchByUnitId', () => {
|
||||
it('should call get with url.blockAncestor', () => {
|
||||
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
|
||||
it('should call get with url.blockAncestor', async () => {
|
||||
await apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
|
||||
expect(get).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), {});
|
||||
});
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('cms api', () => {
|
||||
// eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
|
||||
const utils = await import('./utils');
|
||||
const getSpy = jest.spyOn(utils, 'get');
|
||||
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
|
||||
await apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
|
||||
expect(getSpy).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), {});
|
||||
});
|
||||
|
||||
@@ -94,22 +94,22 @@ describe('cms api', () => {
|
||||
// eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
|
||||
const utils = await import('./utils');
|
||||
const getSpy = jest.spyOn(utils, 'get');
|
||||
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
|
||||
await apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
|
||||
expect(getSpy).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), {});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchStudioView', () => {
|
||||
it('should call get with url.blockStudioView', () => {
|
||||
apiMethods.fetchStudioView({ blockId, studioEndpointUrl });
|
||||
it('should call get with url.blockStudioView', async () => {
|
||||
await apiMethods.fetchStudioView({ blockId, studioEndpointUrl });
|
||||
expect(get).toHaveBeenCalledWith(urls.blockStudioView({ studioEndpointUrl, blockId }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchCourseImages', () => {
|
||||
it('should call get with url.courseAssets', () => {
|
||||
apiMethods.fetchCourseImages({
|
||||
it('should call get with url.courseAssets', async () => {
|
||||
await apiMethods.fetchCourseImages({
|
||||
learningContextId, studioEndpointUrl, pageNumber: 0,
|
||||
});
|
||||
const params = {
|
||||
@@ -123,8 +123,8 @@ describe('cms api', () => {
|
||||
});
|
||||
});
|
||||
describe('fetchLibraryImages', () => {
|
||||
it('should call get with urls.libraryAssets for library V2', () => {
|
||||
apiMethods.fetchLibraryImages({
|
||||
it('should call get with urls.libraryAssets for library V2', async () => {
|
||||
await apiMethods.fetchLibraryImages({
|
||||
blockId,
|
||||
});
|
||||
expect(get).toHaveBeenCalledWith(
|
||||
@@ -134,30 +134,30 @@ describe('cms api', () => {
|
||||
});
|
||||
|
||||
describe('fetchCourseDetails', () => {
|
||||
it('should call get with url.courseDetailsUrl', () => {
|
||||
apiMethods.fetchCourseDetails({ learningContextId, studioEndpointUrl });
|
||||
it('should call get with url.courseDetailsUrl', async () => {
|
||||
await apiMethods.fetchCourseDetails({ learningContextId, studioEndpointUrl });
|
||||
expect(get).toHaveBeenCalledWith(urls.courseDetailsUrl({ studioEndpointUrl, learningContextId }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchVideos', () => {
|
||||
it('should call get with url.courseVideos', () => {
|
||||
apiMethods.fetchVideos({ learningContextId, studioEndpointUrl });
|
||||
it('should call get with url.courseVideos', async () => {
|
||||
await apiMethods.fetchVideos({ learningContextId, studioEndpointUrl });
|
||||
expect(get).toHaveBeenCalledWith(urls.courseVideos({ studioEndpointUrl, learningContextId }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchAdvancedSettings', () => {
|
||||
it('should call get with url.courseAdvanceSettings', () => {
|
||||
apiMethods.fetchAdvancedSettings({ learningContextId, studioEndpointUrl });
|
||||
it('should call get with url.courseAdvanceSettings', async () => {
|
||||
await apiMethods.fetchAdvancedSettings({ learningContextId, studioEndpointUrl });
|
||||
expect(get).toHaveBeenCalledWith(urls.courseAdvanceSettings({ studioEndpointUrl, learningContextId }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getHandlerUrl', () => {
|
||||
it('should call get with url.handlerUrl', () => {
|
||||
it('should call get with url.handlerUrl', async () => {
|
||||
const handlerName = 'transcript';
|
||||
apiMethods.getHandlerUrl({ studioEndpointUrl, blockId, handlerName });
|
||||
await apiMethods.getHandlerUrl({ studioEndpointUrl, blockId, handlerName });
|
||||
expect(get).toHaveBeenCalledWith(urls.handlerUrl({ studioEndpointUrl, blockId, handlerName }));
|
||||
});
|
||||
});
|
||||
@@ -250,8 +250,8 @@ describe('cms api', () => {
|
||||
|
||||
describe('saveBlock', () => {
|
||||
const content = 'Im baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever. Beard man braid migas single-origin coffee forage ramps.';
|
||||
it('should call post with urls.block and normalizeContent', () => {
|
||||
apiMethods.saveBlock({
|
||||
it('should call post with urls.block and normalizeContent', async () => {
|
||||
await apiMethods.saveBlock({
|
||||
blockId,
|
||||
blockType: 'html',
|
||||
content,
|
||||
@@ -278,8 +278,8 @@ describe('cms api', () => {
|
||||
const asset = new File([img], filename, { type: 'image/jpeg' });
|
||||
const mockFormdata = new FormData();
|
||||
mockFormdata.append('file', asset);
|
||||
it('should call post with urls.courseAssets and imgdata', () => {
|
||||
apiMethods.uploadAsset({
|
||||
it('should call post with urls.courseAssets and imgdata', async () => {
|
||||
await apiMethods.uploadAsset({
|
||||
blockId,
|
||||
learningContextId,
|
||||
studioEndpointUrl,
|
||||
@@ -290,10 +290,10 @@ describe('cms api', () => {
|
||||
mockFormdata,
|
||||
);
|
||||
});
|
||||
it('should call post with urls.libraryAssets and imgdata', () => {
|
||||
it('should call post with urls.libraryAssets and imgdata', async () => {
|
||||
learningContextId = 'lib:demo2uX';
|
||||
mockFormdata.append('content', asset);
|
||||
apiMethods.uploadAsset({
|
||||
await apiMethods.uploadAsset({
|
||||
blockId,
|
||||
learningContextId,
|
||||
studioEndpointUrl,
|
||||
@@ -307,10 +307,10 @@ describe('cms api', () => {
|
||||
});
|
||||
|
||||
describe('uploadVideo', () => {
|
||||
it('should call post with urls.courseVideos and data', () => {
|
||||
it('should call post with urls.courseVideos and data', async () => {
|
||||
const data = { files: [{ file_name: 'video.mp4', content_type: 'mp4' }] };
|
||||
|
||||
apiMethods.uploadVideo({ data, studioEndpointUrl, learningContextId });
|
||||
await apiMethods.uploadVideo({ data, studioEndpointUrl, learningContextId });
|
||||
|
||||
expect(urls.courseVideos).toHaveBeenCalledWith({ studioEndpointUrl, learningContextId });
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
@@ -354,10 +354,10 @@ describe('cms api', () => {
|
||||
describe('uploadThumbnail', () => {
|
||||
const thumbnail = 'dAta';
|
||||
const videoId = 'sOmeVIDeoiD';
|
||||
it('should call post with urls.thumbnailUpload and thumbnail data', () => {
|
||||
it('should call post with urls.thumbnailUpload and thumbnail data', async () => {
|
||||
const mockFormdata = new FormData();
|
||||
mockFormdata.append('file', thumbnail);
|
||||
apiMethods.uploadThumbnail({
|
||||
await apiMethods.uploadThumbnail({
|
||||
studioEndpointUrl,
|
||||
learningContextId,
|
||||
videoId,
|
||||
@@ -376,8 +376,8 @@ describe('cms api', () => {
|
||||
const youTubeId = 'SOMeyoutUBeid';
|
||||
describe('checkTranscriptsForImport', () => {
|
||||
const getJSON = `{"locator":"${blockId}","videos":[{"mode":"youtube","video":"${youTubeId}","type":"youtube"},{"mode":"edx_video_id","type":"edx_video_id","video":"${videoId}"}]}`;
|
||||
it('should call get with url.checkTranscriptsForImport', () => {
|
||||
apiMethods.checkTranscriptsForImport({
|
||||
it('should call get with url.checkTranscriptsForImport', async () => {
|
||||
await apiMethods.checkTranscriptsForImport({
|
||||
studioEndpointUrl,
|
||||
blockId,
|
||||
videoId,
|
||||
@@ -391,8 +391,8 @@ describe('cms api', () => {
|
||||
});
|
||||
describe('importTranscript', () => {
|
||||
const getJSON = `{"locator":"${blockId}","videos":[{"mode":"youtube","video":"${youTubeId}","type":"youtube"}]}`;
|
||||
it('should call get with url.replaceTranscript', () => {
|
||||
apiMethods.importTranscript({ studioEndpointUrl, blockId, youTubeId });
|
||||
it('should call get with url.replaceTranscript', async () => {
|
||||
await apiMethods.importTranscript({ studioEndpointUrl, blockId, youTubeId });
|
||||
expect(get).toHaveBeenCalledWith(urls.replaceTranscript({
|
||||
studioEndpointUrl,
|
||||
parameters: encodeURIComponent(getJSON),
|
||||
@@ -401,13 +401,13 @@ describe('cms api', () => {
|
||||
});
|
||||
describe('uploadTranscript', () => {
|
||||
const transcript = new Blob(['dAta']);
|
||||
it('should call post with urls.videoTranscripts and transcript data', () => {
|
||||
it('should call post with urls.videoTranscripts and transcript data', async () => {
|
||||
const mockFormdata = new FormData();
|
||||
mockFormdata.append('file', transcript);
|
||||
mockFormdata.append('edx_video_id', videoId);
|
||||
mockFormdata.append('language_code', language);
|
||||
mockFormdata.append('new_language_code', language);
|
||||
apiMethods.uploadTranscript({
|
||||
await apiMethods.uploadTranscript({
|
||||
blockId,
|
||||
studioEndpointUrl,
|
||||
transcript,
|
||||
@@ -422,14 +422,14 @@ describe('cms api', () => {
|
||||
});
|
||||
describe('uploadTranscriptV2', () => {
|
||||
const transcript = new Blob(['dAta']);
|
||||
it('should call post with urls.uploadTranscriptV2 and transcript data', () => {
|
||||
it('should call post with urls.uploadTranscriptV2 and transcript data', async () => {
|
||||
const mockFormdata = new FormData();
|
||||
const transcriptHandlerUrl = 'handlerUrl';
|
||||
mockFormdata.append('file', transcript);
|
||||
mockFormdata.append('edx_video_id', videoId);
|
||||
mockFormdata.append('language_code', language);
|
||||
mockFormdata.append('new_language_code', language);
|
||||
apiMethods.uploadTranscriptV2({
|
||||
await apiMethods.uploadTranscriptV2({
|
||||
handlerUrl: transcriptHandlerUrl,
|
||||
transcript,
|
||||
videoId,
|
||||
@@ -442,9 +442,9 @@ describe('cms api', () => {
|
||||
});
|
||||
});
|
||||
describe('transcript delete', () => {
|
||||
it('should call deleteObject with urls.videoTranscripts and transcript data', () => {
|
||||
it('should call deleteObject with urls.videoTranscripts and transcript data', async () => {
|
||||
const mockDeleteJSON = { data: { lang: language, edx_video_id: videoId } };
|
||||
apiMethods.deleteTranscript({
|
||||
await apiMethods.deleteTranscript({
|
||||
blockId,
|
||||
studioEndpointUrl,
|
||||
videoId,
|
||||
@@ -455,10 +455,10 @@ describe('cms api', () => {
|
||||
mockDeleteJSON,
|
||||
);
|
||||
});
|
||||
it('should call deleteObject with urls.transcriptXblockV2 and transcript data', () => {
|
||||
it('should call deleteObject with urls.transcriptXblockV2 and transcript data', async () => {
|
||||
const mockDeleteJSON = { data: { lang: language, edx_video_id: videoId } };
|
||||
const transcriptHandlerUrl = 'handlerUrl';
|
||||
apiMethods.deleteTranscriptV2({
|
||||
await apiMethods.deleteTranscriptV2({
|
||||
handlerUrl: transcriptHandlerUrl,
|
||||
videoId,
|
||||
language,
|
||||
@@ -470,9 +470,9 @@ describe('cms api', () => {
|
||||
});
|
||||
});
|
||||
describe('transcript get', () => {
|
||||
it('should call get with urls.videoTranscripts and transcript data', () => {
|
||||
it('should call get with urls.videoTranscripts and transcript data', async () => {
|
||||
const mockJSON = { data: { lang: language, edx_video_id: videoId } };
|
||||
apiMethods.getTranscript({
|
||||
await apiMethods.getTranscript({
|
||||
blockId,
|
||||
studioEndpointUrl,
|
||||
videoId,
|
||||
@@ -483,10 +483,10 @@ describe('cms api', () => {
|
||||
mockJSON,
|
||||
);
|
||||
});
|
||||
it('should call get with urls.transcriptXblockV2 and transcript data', () => {
|
||||
it('should call get with urls.transcriptXblockV2 and transcript data', async () => {
|
||||
const mockJSON = { data: { lang: language, edx_video_id: videoId } };
|
||||
const transcriptHandlerUrl = 'handlerUrl';
|
||||
apiMethods.getTranscriptV2({
|
||||
await apiMethods.getTranscriptV2({
|
||||
handlerUrl: transcriptHandlerUrl,
|
||||
videoId,
|
||||
language,
|
||||
@@ -672,9 +672,9 @@ describe('cms api', () => {
|
||||
});
|
||||
});
|
||||
describe('fetchVideoFeatures', () => {
|
||||
it('should call get with url.videoFeatures', () => {
|
||||
it('should call get with url.videoFeatures', async () => {
|
||||
const args = { studioEndpointUrl };
|
||||
apiMethods.fetchVideoFeatures({ ...args });
|
||||
await apiMethods.fetchVideoFeatures({ ...args });
|
||||
expect(get).toHaveBeenCalledWith(urls.videoFeatures({ ...args }));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('<SelectableBox />', () => {
|
||||
const onClickSpy = jest.fn();
|
||||
render(<SelectableCheckbox onClick={onClickSpy} />);
|
||||
const selectableBox = screen.getByRole('button');
|
||||
await await user.click(selectableBox);
|
||||
await user.click(selectableBox);
|
||||
expect(onClickSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it('renders with on key press event when onClick is passed', async () => {
|
||||
@@ -86,7 +86,7 @@ describe('<SelectableBox />', () => {
|
||||
render(<SelectableCheckbox onClick={onClickSpy} />);
|
||||
const selectableBox = screen.getByRole('button');
|
||||
selectableBox.focus();
|
||||
await await user.keyboard('{enter}');
|
||||
await user.keyboard('{enter}');
|
||||
expect(onClickSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it('renders with hidden input when inputHidden is passed', () => {
|
||||
|
||||
@@ -68,7 +68,7 @@ describe('<SelectableBox.Set />', () => {
|
||||
const onChangeSpy = jest.fn();
|
||||
render(<SelectableCheckboxSet onChange={onChangeSpy} />);
|
||||
const checkbox = screen.getByRole('button', { name: checkboxText(1) });
|
||||
await await user.click(checkbox);
|
||||
await user.click(checkbox);
|
||||
expect(onChangeSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it('renders with checkbox type', () => {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
import {
|
||||
act, fireEvent, render, screen,
|
||||
fireEvent, render, screen,
|
||||
} from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
@@ -48,43 +46,36 @@ describe('SearchSort component', () => {
|
||||
);
|
||||
}
|
||||
|
||||
test('adds a sort option for each sortKey', async () => {
|
||||
test('adds a sort option for each sortKey', () => {
|
||||
const { getByRole } = getComponent();
|
||||
await act(() => {
|
||||
fireEvent.click(screen.getByRole('button', {
|
||||
name: /By oldest/i,
|
||||
}));
|
||||
});
|
||||
fireEvent.click(screen.getByRole('button', {
|
||||
name: /By oldest/i,
|
||||
}));
|
||||
Object.values(sortMessages)
|
||||
.forEach(({ defaultMessage }) => {
|
||||
expect(getByRole('link', { name: `By ${defaultMessage}` }))
|
||||
.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
test('adds a sort option for each sortKey', async () => {
|
||||
test('adds a sort option for each sortKey', () => {
|
||||
const { getByRole } = getComponent();
|
||||
await act(() => {
|
||||
fireEvent.click(screen.getByRole('button', { name: /oldest/i }));
|
||||
});
|
||||
fireEvent.click(screen.getByRole('button', { name: /oldest/i }));
|
||||
Object.values(sortMessages)
|
||||
.forEach(({ defaultMessage }) => {
|
||||
expect(getByRole('link', { name: `By ${defaultMessage}` }))
|
||||
.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
test('adds a filter option for each filter key', async () => {
|
||||
test('adds a filter option for each filter key', () => {
|
||||
const { getByTestId } = getComponent();
|
||||
act(() => {
|
||||
fireEvent.click(getByTestId('dropdown-filter'));
|
||||
});
|
||||
|
||||
fireEvent.click(getByTestId('dropdown-filter'));
|
||||
Object.keys(filterMessages)
|
||||
.forEach((key) => {
|
||||
expect(getByTestId(`dropdown-filter-${key}`))
|
||||
.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
test('searchbox should show clear message button when not empty', async () => {
|
||||
test('searchbox should show clear message button when not empty', () => {
|
||||
const { queryByRole } = getComponent({ searchString: 'some string' });
|
||||
expect(queryByRole('button', { name: messages.clearSearch.defaultMessage }))
|
||||
.toBeInTheDocument();
|
||||
|
||||
@@ -280,7 +280,7 @@ describe('FilesAndUploads', () => {
|
||||
it('should have disabled action buttons', async () => {
|
||||
await mockStore(RequestStatus.SUCCESSFUL);
|
||||
|
||||
const actionsButton = await screen.getByText(messages.actionsButtonLabel.defaultMessage);
|
||||
const actionsButton = screen.getByText(messages.actionsButtonLabel.defaultMessage);
|
||||
fireEvent.click(actionsButton);
|
||||
expect(screen.getByText(messages.downloadTitle.defaultMessage).closest('a')).toHaveClass('disabled');
|
||||
|
||||
@@ -401,7 +401,7 @@ describe('FilesAndUploads', () => {
|
||||
it('should open asset info', async () => {
|
||||
await mockStore(RequestStatus.SUCCESSFUL);
|
||||
|
||||
const [assetMenuButton] = await screen.getAllByTestId('file-menu-dropdown-mOckID1');
|
||||
const [assetMenuButton] = screen.getAllByTestId('file-menu-dropdown-mOckID1');
|
||||
|
||||
axiosMock.onGet(`${getAssetsUrl(courseId)}mOckID1/usage`)
|
||||
.reply(201, {
|
||||
@@ -465,7 +465,7 @@ describe('FilesAndUploads', () => {
|
||||
|
||||
axiosMock.onPut(`${getAssetsUrl(courseId)}mOckID1`).reply(201, { locked: false });
|
||||
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
|
||||
fireEvent.click(await screen.getByText('Unlock'));
|
||||
fireEvent.click(screen.getByText('Unlock'));
|
||||
await executeThunk(updateAssetLock({
|
||||
courseId,
|
||||
assetId: 'mOckID1',
|
||||
@@ -484,7 +484,7 @@ describe('FilesAndUploads', () => {
|
||||
|
||||
axiosMock.onPut(`${getAssetsUrl(courseId)}mOckID3`).reply(201, { locked: true });
|
||||
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
|
||||
fireEvent.click(await screen.getByText('Lock'));
|
||||
fireEvent.click(screen.getByText('Lock'));
|
||||
await executeThunk(updateAssetLock({
|
||||
courseId,
|
||||
assetId: 'mOckID3',
|
||||
@@ -513,7 +513,7 @@ describe('FilesAndUploads', () => {
|
||||
|
||||
axiosMock.onDelete(`${getAssetsUrl(courseId)}mOckID1`).reply(204);
|
||||
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
|
||||
const confirmDelete = await screen.getByTestId('open-delete-confirmation-button');
|
||||
const confirmDelete = screen.getByTestId('open-delete-confirmation-button');
|
||||
fireEvent.click(confirmDelete);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Delete mOckID1')).toBeVisible();
|
||||
@@ -600,7 +600,7 @@ describe('FilesAndUploads', () => {
|
||||
|
||||
axiosMock.onDelete(`${getAssetsUrl(courseId)}mOckID3`).reply(404);
|
||||
fireEvent.click(within(assetMenuButton).getByLabelText('file-menu-toggle'));
|
||||
const confirmDelete = await screen.getByTestId('open-delete-confirmation-button');
|
||||
const confirmDelete = screen.getByTestId('open-delete-confirmation-button');
|
||||
fireEvent.click(confirmDelete);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Delete mOckID3')).toBeVisible();
|
||||
|
||||
@@ -546,7 +546,7 @@ describe('Videos page', () => {
|
||||
fireEvent.click(within(videoMenuButton).getByLabelText('file-menu-toggle'));
|
||||
fireEvent.click(screen.getByText('Info'));
|
||||
|
||||
const transcriptTab = await screen.getAllByRole('tab')[1];
|
||||
const transcriptTab = screen.getAllByRole('tab')[1];
|
||||
fireEvent.click(transcriptTab);
|
||||
|
||||
expect(screen.getByText('Transcript (1)')).toBeVisible();
|
||||
@@ -721,7 +721,7 @@ describe('Videos page', () => {
|
||||
expect(actionsButton).toBeVisible();
|
||||
|
||||
fireEvent.click(actionsButton);
|
||||
const downloadButton = await screen.getByText(messages.downloadTitle.defaultMessage).closest('a');
|
||||
const downloadButton = screen.getByText(messages.downloadTitle.defaultMessage).closest('a');
|
||||
expect(downloadButton).not.toHaveClass('disabled');
|
||||
|
||||
axiosMock.onPut(`${getVideosUrl(courseId)}/download`).reply(404);
|
||||
|
||||
@@ -196,7 +196,7 @@ describe('TranscriptTab', () => {
|
||||
axiosMock.onDelete(`${getApiBaseUrl()}/transcript_delete/${courseId}/mOckID0/ar`).reply(204);
|
||||
await act(async () => {
|
||||
fireEvent.click(confirmButton);
|
||||
executeThunk(deleteVideoTranscript({
|
||||
await executeThunk(deleteVideoTranscript({
|
||||
language: 'ar',
|
||||
videoId: updatedProps.id,
|
||||
transcripts: updatedProps.transcripts,
|
||||
@@ -215,7 +215,7 @@ describe('TranscriptTab', () => {
|
||||
axiosMock.onDelete(`${getApiBaseUrl()}/transcript_delete/${courseId}/mOckID0/ar`).reply(404);
|
||||
await act(async () => {
|
||||
fireEvent.click(confirmButton);
|
||||
executeThunk(deleteVideoTranscript({
|
||||
await executeThunk(deleteVideoTranscript({
|
||||
language: 'ar',
|
||||
videoId: updatedProps.id,
|
||||
transcripts: updatedProps.transcripts,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { fireEvent, render, act } from '@testing-library/react';
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
@@ -57,9 +57,7 @@ describe('<CourseUploadImage />', () => {
|
||||
it('should call onChange if input value changed', async () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const input = getByPlaceholderText(props.customInputPlaceholder);
|
||||
await act(() => {
|
||||
fireEvent.change(input, { target: { value: '/assets' } });
|
||||
});
|
||||
fireEvent.change(input, { target: { value: '/assets' } });
|
||||
expect(onChangeMock).toHaveBeenCalledWith(
|
||||
'/assets',
|
||||
props.assetImageField,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
fireEvent,
|
||||
screen,
|
||||
@@ -211,8 +210,8 @@ describe('<CreateOrRerunCourseForm />', () => {
|
||||
|
||||
fireEvent.change(numberInput, { target: { value: 'long-name-which-is-longer-than-65-characters-to-check-for-errors' } });
|
||||
|
||||
waitFor(() => {
|
||||
expect(screen.getByText(messages.totalLengthError)).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(messages.totalLengthError.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -278,9 +277,10 @@ describe('<CreateOrRerunCourseForm />', () => {
|
||||
const numberInput = await screen.findByPlaceholderText(messages.courseNumberPlaceholder.defaultMessage);
|
||||
|
||||
fireEvent.change(numberInput, { target: { value: 'number with invalid (+) symbol' } });
|
||||
fireEvent.blur(numberInput);
|
||||
|
||||
waitFor(() => {
|
||||
expect(screen.getByText(messages.noSpaceError)).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(messages.disallowedCharsError.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ const renderforContainer = () => defaultRender(
|
||||
close={closeMock}
|
||||
category="chapter"
|
||||
displayName="Introduction to Testing"
|
||||
onDeleteSubmit={onUnlinkSubmitMock}
|
||||
onUnlinkSubmit={onUnlinkSubmitMock}
|
||||
/>
|
||||
</IntlProvider>,
|
||||
);
|
||||
@@ -30,7 +30,7 @@ const renderforComponent = () => defaultRender(
|
||||
isOpen
|
||||
close={closeMock}
|
||||
category="component"
|
||||
onDeleteSubmit={onUnlinkSubmitMock}
|
||||
onUnlinkSubmit={onUnlinkSubmitMock}
|
||||
/>
|
||||
</IntlProvider>,
|
||||
);
|
||||
@@ -65,7 +65,7 @@ describe('<UnlinkModal />', () => {
|
||||
|
||||
const okButton = screen.getByRole('button', { name: messages.unlinkButton.defaultMessage });
|
||||
fireEvent.click(okButton);
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
expect(onUnlinkSubmitMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -46,7 +46,7 @@ describe('<CreditSection />', () => {
|
||||
const inputElement = await findByTestId('minimum-grade-credit-input');
|
||||
expect(inputElement.value).toBe('10');
|
||||
|
||||
await fireEvent.change(inputElement, { target: { value: '.01' } });
|
||||
fireEvent.change(inputElement, { target: { value: '.01' } });
|
||||
await findByText('Not able to set passing grade to less than: 0.1.');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -208,7 +208,7 @@ describe('<AddContent />', () => {
|
||||
expect(getClipboardSpy).toHaveBeenCalled(); // Hmm, this is getting called four times! Refactor to use react-query.
|
||||
|
||||
const pasteButton = await screen.findByRole('button', { name: /paste from clipboard/i });
|
||||
userEvent.click(pasteButton);
|
||||
await userEvent.click(pasteButton);
|
||||
|
||||
await waitFor(() => expect(axiosMock.history.post[0].url).toEqual(pasteUrl));
|
||||
});
|
||||
@@ -223,7 +223,7 @@ describe('<AddContent />', () => {
|
||||
|
||||
render();
|
||||
const pasteButton = await screen.findByRole('button', { name: /paste from clipboard/i });
|
||||
userEvent.click(pasteButton);
|
||||
await userEvent.click(pasteButton);
|
||||
|
||||
await waitFor(() => expect(axiosMock.history.post[0].url).toEqual(pasteUrl));
|
||||
expect(mockShowToast).toHaveBeenCalledWith(
|
||||
@@ -250,7 +250,7 @@ describe('<AddContent />', () => {
|
||||
expect(getClipboardSpy).toHaveBeenCalled(); // Hmm, this is getting called four times! Refactor to use react-query.
|
||||
|
||||
const pasteButton = await screen.findByRole('button', { name: /paste from clipboard/i });
|
||||
userEvent.click(pasteButton);
|
||||
await userEvent.click(pasteButton);
|
||||
|
||||
await waitFor(() => expect(axiosMock.history.post.length).toEqual(1));
|
||||
expect(axiosMock.history.post[0].url).toEqual(pasteUrl);
|
||||
@@ -277,7 +277,7 @@ describe('<AddContent />', () => {
|
||||
expect(getClipboardSpy).toHaveBeenCalled(); // Hmm, this is getting called four times! Refactor to use react-query.
|
||||
|
||||
const pasteButton = await screen.findByRole('button', { name: /paste from clipboard/i });
|
||||
userEvent.click(pasteButton);
|
||||
await userEvent.click(pasteButton);
|
||||
|
||||
await waitFor(() => expect(axiosMock.history.post[0].url).toEqual(pasteUrl));
|
||||
await waitFor(() => expect(axiosMock.history.patch.length).toEqual(1));
|
||||
@@ -295,7 +295,7 @@ describe('<AddContent />', () => {
|
||||
render();
|
||||
|
||||
const pasteButton = await screen.findByRole('button', { name: /paste from clipboard/i });
|
||||
userEvent.click(pasteButton);
|
||||
await userEvent.click(pasteButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(axiosMock.history.post.length).toEqual(0);
|
||||
@@ -329,7 +329,7 @@ describe('<AddContent />', () => {
|
||||
|
||||
render();
|
||||
const button = await screen.findByRole('button', { name: buttonName });
|
||||
userEvent.click(button);
|
||||
await userEvent.click(button);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(axiosMock.history.post.length).toEqual(1);
|
||||
|
||||
@@ -99,13 +99,13 @@ describe('<LibraryBackupPage />', () => {
|
||||
expect(exportingButton).toBeDisabled();
|
||||
});
|
||||
|
||||
it('shows succeeded state uses ready text and triggers download', () => {
|
||||
it('shows succeeded state uses ready text and triggers download', async () => {
|
||||
mockStatusData = { state: 'Succeeded', url: '/fake/path.tar.gz' };
|
||||
const downloadSpy = jest.spyOn(document, 'createElement');
|
||||
render();
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveTextContent(messages.downloadReadyButton.defaultMessage);
|
||||
userEvent.click(button);
|
||||
await userEvent.click(button);
|
||||
expect(downloadSpy).toHaveBeenCalledWith('a');
|
||||
downloadSpy.mockRestore();
|
||||
});
|
||||
@@ -118,19 +118,19 @@ describe('<LibraryBackupPage />', () => {
|
||||
expect(button).toBeEnabled();
|
||||
});
|
||||
|
||||
it('covers timeout cleanup on unmount', () => {
|
||||
it('covers timeout cleanup on unmount', async () => {
|
||||
mockMutate.mockImplementation((_arg: any, { onSuccess }: any) => {
|
||||
onSuccess({ task_id: 'task-123' });
|
||||
mockStatusData = { state: LibraryBackupStatus.Pending };
|
||||
});
|
||||
const { unmount } = render();
|
||||
const button = screen.getByRole('button');
|
||||
userEvent.click(button);
|
||||
await userEvent.click(button);
|
||||
unmount();
|
||||
// No assertion needed, just coverage for cleanup
|
||||
});
|
||||
|
||||
it('covers fallback download logic', () => {
|
||||
it('covers fallback download logic', async () => {
|
||||
mockStatusData = { state: LibraryBackupStatus.Succeeded, url: '/fake/path.tar.gz' };
|
||||
// Spy on createElement to force click failure for anchor
|
||||
const originalCreate = document.createElement.bind(document);
|
||||
@@ -153,7 +153,7 @@ describe('<LibraryBackupPage />', () => {
|
||||
window.location = { href: '' };
|
||||
render();
|
||||
const button = screen.getByRole('button');
|
||||
userEvent.click(button);
|
||||
await userEvent.click(button);
|
||||
expect(window.location.href).toContain('/fake/path.tar.gz');
|
||||
// restore
|
||||
createSpy.mockRestore();
|
||||
|
||||
@@ -129,7 +129,7 @@ describe('<CollectionDetails />', () => {
|
||||
});
|
||||
|
||||
it('should render Collection stats', async () => {
|
||||
mockGetBlockTypes('someBlocks');
|
||||
await mockGetBlockTypes('someBlocks');
|
||||
render();
|
||||
expect(await screen.findByText('Description / Card Preview Text')).toBeInTheDocument();
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('<CollectionDetails />', () => {
|
||||
});
|
||||
|
||||
it('should render Collection stats for empty collection', async () => {
|
||||
mockGetBlockTypes('noBlocks');
|
||||
await mockGetBlockTypes('noBlocks');
|
||||
render();
|
||||
expect(await screen.findByText('Description / Card Preview Text')).toBeInTheDocument();
|
||||
|
||||
@@ -157,7 +157,7 @@ describe('<CollectionDetails />', () => {
|
||||
});
|
||||
|
||||
it('should render Collection stats for big collection', async () => {
|
||||
mockGetBlockTypes('moreBlocks');
|
||||
await mockGetBlockTypes('moreBlocks');
|
||||
render();
|
||||
expect(await screen.findByText('Description / Card Preview Text')).toBeInTheDocument();
|
||||
|
||||
|
||||
@@ -409,7 +409,7 @@ describe('<LibraryCollectionPage />', () => {
|
||||
await renderLibraryCollectionPage();
|
||||
|
||||
// Wait for the unit cards to load
|
||||
waitFor(() => expect(screen.getAllByTestId('container-card-menu-toggle').length).toBeGreaterThan(0));
|
||||
await waitFor(() => expect(screen.getAllByTestId('container-card-menu-toggle').length).toBeGreaterThan(0));
|
||||
|
||||
// open sidebar
|
||||
fireEvent.click(await screen.findByText(displayName));
|
||||
|
||||
@@ -486,7 +486,7 @@ describe('<ContainerCard />', () => {
|
||||
// Click on Copy Item
|
||||
const copyMenuItem = screen.getByRole('button', { name: 'Copy to clipboard' });
|
||||
expect(copyMenuItem).toBeInTheDocument();
|
||||
user.click(copyMenuItem);
|
||||
await user.click(copyMenuItem);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(axiosMock.history.post.length).toBe(1);
|
||||
|
||||
@@ -211,7 +211,7 @@ let mockShowToast: { (message: string, action?: ToastActionData | undefined): vo
|
||||
// Click on Copy Item
|
||||
const copyMenuItem = await screen.findByRole('button', { name: 'Copy to clipboard' });
|
||||
expect(copyMenuItem).toBeInTheDocument();
|
||||
user.click(copyMenuItem);
|
||||
await user.click(copyMenuItem);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(axiosMock.history.post.length).toBe(1);
|
||||
|
||||
@@ -323,10 +323,10 @@ describe('OpenedXConfigForm', () => {
|
||||
});
|
||||
|
||||
test('check duplicate error is removed on deleting duplicate topic', async () => {
|
||||
await await user.click(
|
||||
await user.click(
|
||||
await findByLabelText(duplicateTopicCard, messages.deleteAltText.defaultMessage, { selector: 'button' }),
|
||||
);
|
||||
await await user.click(
|
||||
await user.click(
|
||||
await findByRole(container, 'button', { name: messages.deleteButton.defaultMessage }),
|
||||
);
|
||||
await waitForElementToBeRemoved(queryByText(topicCard, messages.discussionTopicNameAlreadyExist.defaultMessage));
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('AppCard', () => {
|
||||
},
|
||||
});
|
||||
|
||||
store = await initializeStore();
|
||||
store = initializeStore();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
});
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ describe('AppList', () => {
|
||||
},
|
||||
});
|
||||
|
||||
store = await initializeStore();
|
||||
store = initializeStore();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
await mockStore(piazzaApiResponse);
|
||||
});
|
||||
@@ -163,7 +163,7 @@ describe('AppList', () => {
|
||||
},
|
||||
});
|
||||
|
||||
store = await initializeStore();
|
||||
store = initializeStore();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
await mockStore(legacyApiResponse, 'legacy');
|
||||
});
|
||||
|
||||
@@ -326,9 +326,10 @@ describe('Data layer integration tests', () => {
|
||||
test('successfully saves an LTI configuration', async () => {
|
||||
axiosMock.onGet(getDiscussionsProvidersUrl(courseId)).reply(200, generateProvidersApiResponse());
|
||||
axiosMock.onGet(getDiscussionsSettingsUrl(courseId)).reply(200, piazzaApiResponse);
|
||||
// Note: if this test is failing, it's likely because the POSTed data has changed and no longer exactly matches
|
||||
// the expected data in the mock below.
|
||||
axiosMock.onPost(getDiscussionsSettingsUrl(courseId), {
|
||||
context_key: courseId,
|
||||
enabled: true,
|
||||
lti_configuration: {
|
||||
lti_1p1_client_key: 'new_consumer_key',
|
||||
lti_1p1_client_secret: 'new_consumer_secret',
|
||||
@@ -363,7 +364,7 @@ describe('Data layer integration tests', () => {
|
||||
mockedNavigator,
|
||||
), store.dispatch);
|
||||
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
expect(mockedNavigator).toHaveBeenCalledWith(pagesAndResourcesPath);
|
||||
expect(store.getState().discussions).toEqual(
|
||||
expect.objectContaining({
|
||||
@@ -388,9 +389,10 @@ describe('Data layer integration tests', () => {
|
||||
test('successfully saves a Legacy configuration', async () => {
|
||||
axiosMock.onGet(getDiscussionsProvidersUrl(courseId)).reply(200, generateProvidersApiResponse(false, 'legacy'));
|
||||
axiosMock.onGet(getDiscussionsSettingsUrl(courseId)).reply(200, legacyApiResponse);
|
||||
// Note: if this test is failing, it's likely because the POSTed data has changed and no longer exactly matches
|
||||
// the expected data in the mock below.
|
||||
axiosMock.onPost(getDiscussionsSettingsUrl(courseId), {
|
||||
context_key: courseId,
|
||||
enabled: true,
|
||||
lti_configuration: {},
|
||||
plugin_configuration: {
|
||||
allow_anonymous: true,
|
||||
@@ -458,7 +460,7 @@ describe('Data layer integration tests', () => {
|
||||
pagesAndResourcesPath,
|
||||
mockedNavigator,
|
||||
), store.dispatch);
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
expect(mockedNavigator).toHaveBeenCalledWith(pagesAndResourcesPath);
|
||||
expect(store.getState().discussions).toEqual(
|
||||
expect.objectContaining({
|
||||
|
||||
@@ -11,7 +11,6 @@ import { getApiWaffleFlagsUrl } from '../../data/api';
|
||||
|
||||
import PagesAndResourcesProvider from '../PagesAndResourcesProvider';
|
||||
|
||||
let container;
|
||||
let axiosMock;
|
||||
const courseId = '123';
|
||||
const mockPageConfig = [
|
||||
@@ -36,12 +35,11 @@ const mockPageConfig = [
|
||||
];
|
||||
|
||||
const renderComponent = () => {
|
||||
const wrapper = render(
|
||||
render(
|
||||
<PagesAndResourcesProvider courseId={courseId}>
|
||||
<PageGrid pages={mockPageConfig} />
|
||||
</PagesAndResourcesProvider>,
|
||||
);
|
||||
container = wrapper.container;
|
||||
};
|
||||
|
||||
describe('LiveSettings', () => {
|
||||
@@ -60,16 +58,16 @@ describe('LiveSettings', () => {
|
||||
|
||||
it('should render three cards', async () => {
|
||||
renderComponent();
|
||||
waitFor(() => {
|
||||
expect(screen.queryAllByRole(container, 'button')).toHaveLength(3);
|
||||
await waitFor(() => {
|
||||
expect(screen.queryAllByRole('button')).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to legacyLink', async () => {
|
||||
renderComponent();
|
||||
const textbookPagePath = mockPageConfig[0][1];
|
||||
waitFor(() => {
|
||||
const textbookSettingsButton = screen.queryAllByRole(container, 'link')[1];
|
||||
await waitFor(() => {
|
||||
const textbookSettingsButton = screen.queryAllByRole('link')[1];
|
||||
expect(textbookSettingsButton).toHaveAttribute('href', textbookPagePath);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,9 +125,7 @@ describe('<ScheduleAndDetails />', () => {
|
||||
|
||||
it('should display a success message when course details saves', async () => {
|
||||
const { getByText } = render(<ScheduleAndDetails courseId={courseId} />);
|
||||
await waitFor(() => {
|
||||
executeThunk(updateCourseDetailsQuery(courseId, 'DaTa'), store.dispatch);
|
||||
});
|
||||
await executeThunk(updateCourseDetailsQuery(courseId, 'DaTa'), store.dispatch);
|
||||
expect(getByText(messages.alertSuccess.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ describe('<DetailsSection />', () => {
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onChange if dropdown value changed', () => {
|
||||
it('should call onChange if dropdown value changed', async () => {
|
||||
const { getByRole } = render(<RootWrapper {...props} />);
|
||||
const option = getByRole('button', {
|
||||
name: courseSettingsMock.languageOptions[1][1],
|
||||
@@ -42,7 +42,7 @@ describe('<DetailsSection />', () => {
|
||||
name: courseSettingsMock.languageOptions[0][1],
|
||||
});
|
||||
|
||||
waitFor(() => expect(anotherOption));
|
||||
await waitFor(() => expect(anotherOption));
|
||||
fireEvent.click(anotherOption);
|
||||
expect(onChangeMock).toHaveBeenCalledWith(
|
||||
courseSettingsMock.languageOptions[0][0],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
act, fireEvent, render, waitFor,
|
||||
fireEvent, render, screen, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
@@ -46,45 +45,56 @@ const props = {
|
||||
|
||||
describe('<InstructorsSection />', () => {
|
||||
it('renders section successfully', () => {
|
||||
const { getByText, getByRole } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.instructorsTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.instructorsDescription.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: messages.instructorAdd.defaultMessage })).toBeInTheDocument();
|
||||
render(<RootWrapper {...props} />);
|
||||
expect(screen.getByText(messages.instructorsTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(screen.getByText(messages.instructorsDescription.defaultMessage)).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: messages.instructorAdd.defaultMessage })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should create another instructor form on click Add new instructor', () => {
|
||||
const { getAllByRole, getByRole } = render(<RootWrapper {...props} />);
|
||||
const addButton = getByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
act(() => {
|
||||
fireEvent.click(addButton);
|
||||
});
|
||||
it('should create another instructor form on click Add new instructor', async () => {
|
||||
const { rerender } = render(<RootWrapper {...props} />);
|
||||
const addButton = screen.getByRole('button', { name: messages.instructorAdd.defaultMessage });
|
||||
fireEvent.click(addButton);
|
||||
|
||||
waitFor(() => {
|
||||
const deleteButtons = getAllByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
const newInstructors = [
|
||||
props.instructors[0],
|
||||
{
|
||||
bio: '',
|
||||
image: '',
|
||||
name: '',
|
||||
organization: '',
|
||||
title: '',
|
||||
},
|
||||
];
|
||||
expect(onChangeMock).toHaveBeenCalledWith({ instructors: newInstructors }, 'instructorInfo');
|
||||
|
||||
rerender(<RootWrapper {...props} instructors={newInstructors} />);
|
||||
await waitFor(() => {
|
||||
const deleteButtons = screen.getAllByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
expect(deleteButtons.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete instructor form on click Delete', () => {
|
||||
const { getAllByRole, getByRole } = render(<RootWrapper {...props} />);
|
||||
const deleteButton = getByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
act(() => {
|
||||
fireEvent.click(deleteButton);
|
||||
});
|
||||
it('should delete instructor form on click Delete', async () => {
|
||||
const { rerender } = render(<RootWrapper {...props} />);
|
||||
const deleteButton = screen.getByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
fireEvent.click(deleteButton);
|
||||
|
||||
expect(onChangeMock).toHaveBeenCalledWith({ instructors: [] }, 'instructorInfo');
|
||||
waitFor(() => {
|
||||
const deleteButtons = getAllByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
rerender(<RootWrapper {...props} instructors={[]} />);
|
||||
await waitFor(() => {
|
||||
const deleteButtons = screen.queryAllByRole(
|
||||
'button',
|
||||
{ name: instructorMessages.instructorDelete.defaultMessage },
|
||||
);
|
||||
expect(deleteButtons.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onChange if input value changed', () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const inputName = getByPlaceholderText(instructorMessages.instructorNameInputPlaceholder.defaultMessage);
|
||||
act(() => {
|
||||
fireEvent.change(inputName, { target: { value: 'abc' } });
|
||||
});
|
||||
render(<RootWrapper {...props} />);
|
||||
const inputName = screen.getByPlaceholderText(instructorMessages.instructorNameInputPlaceholder.defaultMessage);
|
||||
fireEvent.change(inputName, { target: { value: 'abc' } });
|
||||
|
||||
expect(onChangeMock).toHaveBeenCalledWith({
|
||||
instructors: [{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { fireEvent, render, act } from '@testing-library/react';
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
@@ -112,18 +112,14 @@ describe('<InstructorContainer />', () => {
|
||||
it('should call onChange if input value changed', async () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const nameInput = getByPlaceholderText(messages.instructorNameInputPlaceholder.defaultMessage);
|
||||
await act(() => {
|
||||
fireEvent.change(nameInput, { target: { value: 'abc' } });
|
||||
});
|
||||
fireEvent.change(nameInput, { target: { value: 'abc' } });
|
||||
expect(onChangeMock).toHaveBeenCalledWith('abc', props.idx, 'name');
|
||||
});
|
||||
|
||||
it('should call onDelete if button delete clicked', async () => {
|
||||
const { getByRole } = render(<RootWrapper {...props} />);
|
||||
const deleteBtn = getByRole('button', { name: messages.instructorDelete.defaultMessage });
|
||||
await act(() => {
|
||||
fireEvent.click(deleteBtn);
|
||||
});
|
||||
fireEvent.click(deleteBtn);
|
||||
expect(onDeleteMock).toHaveBeenCalledWith(props.idx);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
act, fireEvent, render, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { courseDetailsMock } from '../__mocks__';
|
||||
@@ -28,39 +25,44 @@ describe('<LearningOutcomesSection />', () => {
|
||||
expect(getByRole('button', { name: messages.outcomesAdd.defaultMessage })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should create another learning outcome form on click Add learning outcome', () => {
|
||||
const { getAllByRole, getByRole } = render(<RootWrapper {...props} />);
|
||||
it('should create another learning outcome form on click Add learning outcome', async () => {
|
||||
const { getByRole } = render(<RootWrapper {...props} />);
|
||||
const addButton = getByRole('button', { name: messages.outcomesAdd.defaultMessage });
|
||||
act(() => {
|
||||
fireEvent.click(addButton);
|
||||
});
|
||||
expect(onChangeMock).not.toHaveBeenCalled();
|
||||
fireEvent.click(addButton);
|
||||
expect(onChangeMock).toHaveBeenCalledWith([
|
||||
props.learningInfo[0],
|
||||
'', // <-- new
|
||||
], 'learningInfo');
|
||||
|
||||
waitFor(() => {
|
||||
const deleteButtons = getAllByRole('button', { name: messages.outcomesDelete.defaultMessage });
|
||||
expect(deleteButtons.length).toBe(2);
|
||||
});
|
||||
// FIXME: the following doesn't happen, because this is a controlled component and only changes
|
||||
// when the props change (in response to 'onChange'). This needs to be tested at a higher level,
|
||||
// e.g. testing the whole page together, not just this component.
|
||||
// await waitFor(() => {
|
||||
// const deleteButtons = getAllByRole('button', { name: messages.outcomesDelete.defaultMessage });
|
||||
// expect(deleteButtons.length).toBe(2);
|
||||
// });
|
||||
});
|
||||
|
||||
it('should delete learning outcome form on click Delete', () => {
|
||||
const { getAllByRole, getByRole } = render(<RootWrapper {...props} />);
|
||||
it('should delete learning outcome form on click Delete', async () => {
|
||||
const { getByRole } = render(<RootWrapper {...props} />);
|
||||
const deleteButton = getByRole('button', { name: messages.outcomesDelete.defaultMessage });
|
||||
act(() => {
|
||||
fireEvent.click(deleteButton);
|
||||
});
|
||||
fireEvent.click(deleteButton);
|
||||
|
||||
expect(onChangeMock).toHaveBeenCalledWith([], 'learningInfo');
|
||||
waitFor(() => {
|
||||
const deleteButtons = getAllByRole('button', { name: messages.outcomesDelete.defaultMessage });
|
||||
expect(deleteButtons.length).toBe(0);
|
||||
});
|
||||
// FIXME: the following doesn't happen, because this is a controlled component and only changes
|
||||
// when the props change (in response to 'onChange'). This needs to be tested at a higher level,
|
||||
// e.g. testing the whole page together, not just this component.
|
||||
// await waitFor(() => {
|
||||
// const deleteButtons = getAllByRole('button', { name: messages.outcomesDelete.defaultMessage });
|
||||
// expect(deleteButtons.length).toBe(0);
|
||||
// });
|
||||
});
|
||||
|
||||
it('should call onChange if input value changed', () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const input = getByPlaceholderText(messages.outcomesInputPlaceholder.defaultMessage);
|
||||
act(() => {
|
||||
fireEvent.change(input, { target: { value: 'abc' } });
|
||||
});
|
||||
fireEvent.change(input, { target: { value: 'abc' } });
|
||||
|
||||
expect(onChangeMock).toHaveBeenCalledWith(['abc'], 'learningInfo');
|
||||
});
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
render, fireEvent, act, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { render, fireEvent } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { LICENSE_COMMONS_OPTIONS } from '../constants';
|
||||
@@ -44,15 +41,17 @@ describe('<LicenseCommonsOptions />', () => {
|
||||
expect(checkboxList[3].checked).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should call onToggleCheckbox event onClick', () => {
|
||||
it('should call onToggleCheckbox event onClick', async () => {
|
||||
const { getAllByRole } = render(<RootWrapper {...props} />);
|
||||
const checkboxList = getAllByRole('checkbox');
|
||||
act(() => {
|
||||
fireEvent.click(checkboxList[1]);
|
||||
});
|
||||
expect(props.onToggleCheckbox).not.toHaveBeenCalled();
|
||||
fireEvent.click(checkboxList[1]);
|
||||
expect(props.onToggleCheckbox).toHaveBeenCalledWith(LICENSE_COMMONS_OPTIONS.nonCommercial);
|
||||
waitFor(() => {
|
||||
expect(checkboxList[1].checked).toBeFalsy();
|
||||
});
|
||||
// Note: there is no point in asserting that the checkbox is now checked,
|
||||
// because it is a controlled component that never changes unless the props change.
|
||||
// This test should really be implemented in a higher level component/page.
|
||||
// await waitFor(() => {
|
||||
// expect(checkboxList[1].checked).toBeFalsy();
|
||||
// });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
act, fireEvent, render, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { LICENSE_TYPE } from '../constants';
|
||||
@@ -36,20 +33,21 @@ describe('<LicenseSelector />', () => {
|
||||
expect(anotherButton).toHaveClass('btn btn-outline-primary');
|
||||
});
|
||||
|
||||
it('should call onChangeLicenseType if button clicked', () => {
|
||||
it('should call onChangeLicenseType if button clicked', async () => {
|
||||
const { getByRole } = render(<RootWrapper {...props} />);
|
||||
const button = getByRole('button', { name: messages.licenseChoice2.defaultMessage });
|
||||
expect(button).toHaveClass('btn btn-outline-primary');
|
||||
act(() => {
|
||||
fireEvent.click(button);
|
||||
});
|
||||
waitFor(() => {
|
||||
expect(button).toHaveClass('btn btn-primary');
|
||||
});
|
||||
fireEvent.click(button);
|
||||
expect(props.onChangeLicenseType).toHaveBeenCalledWith(
|
||||
LICENSE_TYPE.creativeCommons,
|
||||
'license',
|
||||
);
|
||||
// FIXME: the following doesn't happen, because this is a controlled component and only changes
|
||||
// when the props change (in response to 'onChange'). This needs to be tested at a higher level,
|
||||
// e.g. testing the whole page together, not just this component.
|
||||
// await waitFor(() => {
|
||||
// expect(button).toHaveClass('btn btn-primary');
|
||||
// });
|
||||
});
|
||||
|
||||
it('should show disabled buttons if license is null', () => {
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
render, fireEvent, act, waitFor,
|
||||
render, screen, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { courseDetailsMock } from '../../__mocks__';
|
||||
import gradeRequirementsMessages from '../grade-requirements/messages';
|
||||
import messages from './messages';
|
||||
import EntranceExam from '.';
|
||||
|
||||
@@ -41,21 +40,21 @@ describe('<EntranceExam />', () => {
|
||||
expect(checkboxList[0].checked).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should toggle grade requirements after checkbox click', () => {
|
||||
const { getByText, queryAllByText, getAllByRole } = render(
|
||||
<RootWrapper {...props} />,
|
||||
);
|
||||
const checkbox = getAllByRole('checkbox')[0];
|
||||
expect(
|
||||
getByText(gradeRequirementsMessages.requirementsEntranceCollapseLabel.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
act(() => {
|
||||
fireEvent.click(checkbox);
|
||||
});
|
||||
waitFor(() => {
|
||||
expect(
|
||||
queryAllByText(gradeRequirementsMessages.requirementsEntranceCollapseLabel.defaultMessage).length,
|
||||
).toBe(0);
|
||||
it('should toggle grade requirements after checkbox click', async () => {
|
||||
onChangeMock.mockClear();
|
||||
const ui = render(<RootWrapper {...props} />);
|
||||
const user = userEvent.setup();
|
||||
const checkbox = screen.getByRole('checkbox', { name: 'Require students to pass an exam before beginning the course.' });
|
||||
|
||||
expect(checkbox).toBeChecked();
|
||||
expect(screen.queryByText('Grade requirements')).toBeInTheDocument();
|
||||
|
||||
await user.click(checkbox);
|
||||
expect(onChangeMock).toHaveBeenCalledWith('false', 'entranceExamEnabled');
|
||||
ui.rerender(<RootWrapper {...props} isCheckedString="false" />);
|
||||
await waitFor(() => {
|
||||
expect(checkbox).not.toBeChecked();
|
||||
expect(screen.queryByText('Grade requirements')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
render, fireEvent, act, waitFor,
|
||||
render, fireEvent, screen, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
@@ -34,20 +33,15 @@ describe('<GradeRequirements />', () => {
|
||||
it('should call onChange on input change', () => {
|
||||
const { getByDisplayValue } = render(<RootWrapper {...props} />);
|
||||
const input = getByDisplayValue(props.entranceExamMinimumScorePct);
|
||||
act(() => {
|
||||
fireEvent.change(input, { target: { valueAsNumber: '31' } });
|
||||
});
|
||||
fireEvent.change(input, { target: { valueAsNumber: '31' } });
|
||||
expect(props.onChange).toHaveBeenCalledWith('31', 'entranceExamMinimumScorePct');
|
||||
});
|
||||
|
||||
it('should show feedback error', () => {
|
||||
const { getByDisplayValue, getByText } = render(<RootWrapper {...props} />);
|
||||
const input = getByDisplayValue(props.entranceExamMinimumScorePct);
|
||||
act(() => {
|
||||
fireEvent.change(input, { target: { valueAsNumber: '123' } });
|
||||
});
|
||||
waitFor(() => {
|
||||
expect(getByText(scheduleMessage.errorMessage8.defaultMessage)).toBeInTheDocument();
|
||||
it('should show feedback error', async () => {
|
||||
const errorMessage = scheduleMessage.errorMessage8.defaultMessage;
|
||||
render(<RootWrapper {...props} entranceExamMinimumScorePct="123" errorEffort={errorMessage} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(errorMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import {
|
||||
render, fireEvent, waitFor, act,
|
||||
render, fireEvent, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
@@ -83,7 +83,7 @@ describe('<CollapsibleStateWithAction />', () => {
|
||||
expect(getByText(messages.deniedCollapsibleTitle.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders collapsible denied state successfully opened', () => {
|
||||
it('renders collapsible denied state successfully opened', async () => {
|
||||
useSelector.mockReturnValue(studioHomeMock);
|
||||
|
||||
const initialState = { ...props, state: COURSE_CREATOR_STATES.denied };
|
||||
@@ -91,11 +91,9 @@ describe('<CollapsibleStateWithAction />', () => {
|
||||
const container = getByText(messages.deniedCollapsibleTitle.defaultMessage);
|
||||
|
||||
fireEvent.click(container);
|
||||
act(async () => {
|
||||
await waitFor(() => {
|
||||
expect(getByText(messages.deniedCollapsibleState.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.deniedCollapsibleActionTitle.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(getByText(messages.deniedCollapsibleState.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.deniedCollapsibleActionTitle.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -251,9 +251,9 @@ describe('<ImportTagsWizard />', () => {
|
||||
} = render(<RootWrapper taxonomy={null} onClose={onClose} />);
|
||||
|
||||
// Check that there is no export step
|
||||
expect(await queryByTestId('export-step')).not.toBeInTheDocument();
|
||||
expect(queryByTestId('export-step')).not.toBeInTheDocument();
|
||||
// Check that there is no back button in the upload step
|
||||
expect(await queryByTestId('back-button')).not.toBeInTheDocument();
|
||||
expect(queryByTestId('back-button')).not.toBeInTheDocument();
|
||||
|
||||
// Check that we are on the upload step
|
||||
expect(getByTestId('upload-step')).toBeInTheDocument();
|
||||
|
||||
@@ -174,11 +174,11 @@ describe('<TextbookForm />', () => {
|
||||
const { findByTestId, findByRole } = renderComponent();
|
||||
|
||||
const button = await findByTestId('chapter-upload-button');
|
||||
await await user.click(button);
|
||||
await user.click(button);
|
||||
const modalBackdrop = await findByTestId('modal-backdrop');
|
||||
|
||||
const cancelButton = await within(await findByRole('dialog')).findByText('Cancel');
|
||||
await await user.click(cancelButton);
|
||||
await user.click(cancelButton);
|
||||
await waitFor(() => {
|
||||
expect(modalBackdrop).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user