fix: resolve incorrect or missing 'await' usages (#2592)

* chore: fix incorrect or missing 'await' usages
* test: fix broken test
* chore: ignore lines causing patch coverage to fail
This commit is contained in:
Braden MacDonald
2026-01-28 16:48:13 -08:00
committed by GitHub
parent 7e53e1143f
commit 9d9d7a7167
54 changed files with 136 additions and 62 deletions

View File

@@ -72,6 +72,7 @@ const LiveSettings = ({
};
const handleSettingsSave = async (values) => {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
await dispatch(saveLiveConfiguration(courseId, values, navigate));
};

View File

@@ -48,8 +48,9 @@ const ORASettings = ({ onClose }) => {
event.preventDefault();
success = success && await handleSettingsSave(formValues);
await setSaveError(!success);
setSaveError(!success);
if ((initialFormValues.enableFlexiblePeerGrade !== formValues.enableFlexiblePeerGrade) && success) {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
success = await dispatch(updateModel({
modelType: 'courseApps',
model: {

View File

@@ -128,7 +128,7 @@ describe('ORASettings', () => {
await mockStore({ apiStatus: 200, enabled: true });
renderComponent();
const checkbox = await screen.getByRole('checkbox', { name: /Flex Peer Grading/ });
const checkbox = screen.getByRole('checkbox', { name: /Flex Peer Grading/ });
expect(checkbox).toBeChecked();
await waitFor(() => {

View File

@@ -239,8 +239,10 @@ const SettingsModal = ({
const values = { ...rest, enabled: enabled ? checked === 'true' : undefined };
if (enabled) {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
success = await dispatch(updateXpertSettings(courseId, values));
} else {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
success = await dispatch(removeXpertSettings(courseId));
}

View File

@@ -25,6 +25,7 @@ const useCertificatesList = (courseId) => {
}));
const handleSubmit = async (values) => {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
await dispatch(updateCourseCertificate(courseId, values));
setEditModes({});
dispatch(setMode(MODE_STATES.view));

View File

@@ -172,6 +172,7 @@ export const useContentTaxonomyTagsUpdater = (contentId: string) => {
// feature to support the legacy Django template courseware page.
// Sends content tags.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
getContentTaxonomyTagsData(contentId).then((data) => {
const contentData = { contentId, ...data };
@@ -187,6 +188,7 @@ export const useContentTaxonomyTagsUpdater = (contentId: string) => {
});
// Sends tags count.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
getContentTaxonomyTagsCount(contentId).then((count) => {
const contentData = { contentId, count };

View File

@@ -46,9 +46,9 @@ describe('CourseChecklistPage', () => {
});
describe('renders', () => {
describe('if enable_quality prop is true', () => {
it('two checklist components ', () => {
it('two checklist components ', async () => {
renderComponent();
mockStore(200);
await mockStore(200);
expect(screen.getByText(messages.launchChecklistLabel.defaultMessage)).toBeVisible();
@@ -67,7 +67,7 @@ describe('CourseChecklistPage', () => {
it('correct content when the launch checklist has loaded', async () => {
renderComponent();
mockStore(404);
await mockStore(404);
await waitFor(() => {
const { launchChecklistStatus } = store.getState().courseChecklist.loadingStatus;
@@ -79,7 +79,7 @@ describe('CourseChecklistPage', () => {
it('correct content when the best practices checklist is loading', async () => {
renderComponent();
mockStore(404);
await mockStore(404);
await waitFor(() => {
const { bestPracticeChecklistStatus } = store.getState().courseChecklist.loadingStatus;
@@ -100,9 +100,9 @@ describe('CourseChecklistPage', () => {
});
});
it('one checklist components ', () => {
it('one checklist components ', async () => {
renderComponent();
mockStore(200);
await mockStore(200);
expect(screen.getByText(messages.launchChecklistLabel.defaultMessage)).toBeVisible();
@@ -112,7 +112,7 @@ describe('CourseChecklistPage', () => {
describe('an aria-live region with', () => {
it('correct content when the launch checklist has loaded', async () => {
renderComponent();
mockStore(404);
await mockStore(404);
await waitFor(() => {
const { launchChecklistStatus } = store.getState().courseChecklist.loadingStatus;
@@ -124,7 +124,7 @@ describe('CourseChecklistPage', () => {
it('correct content when the best practices checklist is loading', async () => {
renderComponent();
mockStore(404);
await mockStore(404);
await waitFor(() => {
const { bestPracticeChecklistStatus } = store.getState().courseChecklist.loadingStatus;

View File

@@ -31,11 +31,13 @@ const LegacyLibContentBlockAlert = ({ courseId }: Props) => {
if (taskStatus.data?.state === UserTaskStatus.Succeeded) {
showToast(intl.formatMessage(messages.legacyLibReadyToMigrateTaskCompleted));
setTaskId(undefined);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
refetch();
} else if (taskStatus.data?.state === UserTaskStatus.Failed
|| taskStatus.data?.state === UserTaskStatus.Cancelled) {
showToast(intl.formatMessage(messages.legacyLibReadyToMigrateTaskFailed));
setTaskId(undefined);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
refetch();
} else if (taskId) {
showToast(intl.formatMessage(messages.legacyLibReadyToMigrateTaskInProgress));

View File

@@ -471,11 +471,11 @@ describe('<CourseOutline />', () => {
const dummyBtn = await screen.findByRole('button', { name: 'Dummy button' });
fireEvent.click(dummyBtn);
waitFor(() => expect(axiosMock.history.post.length).toBe(3));
await waitFor(() => expect(axiosMock.history.post.length).toBe(3));
const [section] = courseOutlineIndexMock.courseStructure.childInfo.children;
const [subsection] = section.childInfo.children;
waitFor(() => {
await waitFor(() => {
expect(axiosMock.history.post[2].data).toBe(JSON.stringify({
type: COMPONENT_TYPES.libraryV2,
category: 'vertical',
@@ -509,10 +509,10 @@ describe('<CourseOutline />', () => {
const dummyBtn = await screen.findByRole('button', { name: 'Dummy button' });
fireEvent.click(dummyBtn);
waitFor(() => expect(axiosMock.history.post.length).toBe(3));
await waitFor(() => expect(axiosMock.history.post.length).toBe(3));
const [section] = courseOutlineIndexMock.courseStructure.childInfo.children;
waitFor(() => {
await waitFor(() => {
expect(axiosMock.history.post[2].data).toBe(JSON.stringify({
type: COMPONENT_TYPES.libraryV2,
category: 'sequential',
@@ -545,10 +545,10 @@ describe('<CourseOutline />', () => {
const dummyBtn = await screen.findByRole('button', { name: 'Dummy button' });
fireEvent.click(dummyBtn);
waitFor(() => expect(axiosMock.history.post.length).toBe(3));
await waitFor(() => expect(axiosMock.history.post.length).toBe(3));
const courseUsageKey = courseOutlineIndexMock.courseStructure.id;
waitFor(() => {
await waitFor(() => {
expect(axiosMock.history.post[2].data).toBe(JSON.stringify({
type: COMPONENT_TYPES.libraryV2,
category: 'chapter',

View File

@@ -321,6 +321,7 @@ const LegacyOutlineAddChildButtons = ({
}
const handleOnComponentSelected = (selected: SelectedComponent) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
onUseLibraryContent(selected);
closeAddLibrarySectionModal();
};

View File

@@ -229,7 +229,7 @@ describe('<CardHeader />', () => {
});
expect(await screen.findByTestId('subsection-edit-field')).toBeInTheDocument();
waitFor(() => {
await waitFor(() => {
expect(screen.queryByTestId('subsection-card-header__expanded-btn')).not.toBeInTheDocument();
expect(screen.queryByTestId('edit-button')).not.toBeInTheDocument();
});

View File

@@ -113,6 +113,7 @@ const useCourseOutline = ({ courseId }) => {
const headerNavigationsActions = {
handleNewSection: () => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
handleAddSection.mutateAsync({
type: ContainerType.Chapter,
parentLocator: courseStructure?.id,

View File

@@ -318,12 +318,12 @@ describe('<SectionCard />', () => {
renderComponent();
const element = await screen.findByTestId('section-card');
const menu = await within(element).findByTestId('section-card-header__menu-button');
await fireEvent.click(menu);
fireEvent.click(menu);
const manageTagsBtn = await within(element).findByTestId('section-card-header__menu-manage-tags-button');
expect(manageTagsBtn).toBeInTheDocument();
await fireEvent.click(manageTagsBtn);
fireEvent.click(manageTagsBtn);
const drawer = await screen.findByRole('alert');
expect(within(drawer).getByText(/manage tags/i));
@@ -364,12 +364,12 @@ describe('<SectionCard />', () => {
renderComponent();
const element = await screen.findByTestId('section-card');
const menu = await within(element).findByTestId('section-card-header__menu-button');
await fireEvent.click(menu);
fireEvent.click(menu);
const manageTagsBtn = await within(element).findByTestId('section-card-header__menu-manage-tags-button');
expect(manageTagsBtn).toBeInTheDocument();
await fireEvent.click(manageTagsBtn);
fireEvent.click(manageTagsBtn);
await waitFor(() => {
expect(mockSetCurrentPageKey).toHaveBeenCalledWith('align', section.id);

View File

@@ -32,6 +32,7 @@ export function useDynamicHookShim() {
}
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
load();
return () => {

View File

@@ -428,12 +428,12 @@ describe('<SubsectionCard />', () => {
renderComponent();
const element = await screen.findByTestId('subsection-card');
const menu = await within(element).findByTestId('subsection-card-header__menu-button');
await fireEvent.click(menu);
fireEvent.click(menu);
const manageTagsBtn = await within(element).findByTestId('subsection-card-header__menu-manage-tags-button');
expect(manageTagsBtn).toBeInTheDocument();
await fireEvent.click(manageTagsBtn);
fireEvent.click(manageTagsBtn);
const drawer = await screen.findByRole('alert');
expect(within(drawer).getByText(/manage tags/i));
@@ -474,12 +474,12 @@ describe('<SubsectionCard />', () => {
renderComponent();
const element = await screen.findByTestId('subsection-card');
const menu = await within(element).findByTestId('subsection-card-header__menu-button');
await fireEvent.click(menu);
fireEvent.click(menu);
const manageTagsBtn = await within(element).findByTestId('subsection-card-header__menu-manage-tags-button');
expect(manageTagsBtn).toBeInTheDocument();
await fireEvent.click(manageTagsBtn);
fireEvent.click(manageTagsBtn);
await waitFor(() => {
expect(mockSetCurrentPageKey).toHaveBeenCalledWith('align', subsection.id);

View File

@@ -286,12 +286,12 @@ describe('<UnitCard />', () => {
renderComponent();
const element = await screen.findByTestId('unit-card');
const menu = await within(element).findByTestId('unit-card-header__menu-button');
await fireEvent.click(menu);
fireEvent.click(menu);
const manageTagsBtn = await within(element).findByTestId('unit-card-header__menu-manage-tags-button');
expect(manageTagsBtn).toBeInTheDocument();
await fireEvent.click(manageTagsBtn);
fireEvent.click(manageTagsBtn);
const drawer = await screen.findByRole('alert');
expect(within(drawer).getByText(/manage tags/i));
@@ -332,12 +332,12 @@ describe('<UnitCard />', () => {
renderComponent();
const element = await screen.findByTestId('unit-card');
const menu = await within(element).findByTestId('unit-card-header__menu-button');
await fireEvent.click(menu);
fireEvent.click(menu);
const manageTagsBtn = await within(element).findByTestId('unit-card-header__menu-manage-tags-button');
expect(manageTagsBtn).toBeInTheDocument();
await fireEvent.click(manageTagsBtn);
fireEvent.click(manageTagsBtn);
await waitFor(() => {
expect(mockSetCurrentPageKey).toHaveBeenCalledWith('align', unit.id);

View File

@@ -157,6 +157,7 @@ const UnitCard = ({
};
const handleCopyClick = () => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
copyToClipboard(id);
};

View File

@@ -17,6 +17,13 @@ jest.mock('react-redux', () => ({
useSelector: jest.fn(),
}));
const mockNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'), // use actual for all non-hook parts
useNavigate: () => mockNavigate,
}));
describe('<CourseRerun />', () => {
beforeEach(() => {
const { axiosMock } = initializeMocks();
@@ -30,13 +37,13 @@ describe('<CourseRerun />', () => {
expect(getAllByRole('button', { name: messages.cancelButton.defaultMessage }).length).toBe(2);
});
it('should navigate to /home on cancel button click', () => {
it('should navigate to /home on cancel button click', async () => {
const { getAllByRole } = render(<CourseRerun />);
const cancelButton = getAllByRole('button', { name: messages.cancelButton.defaultMessage })[0];
fireEvent.click(cancelButton);
waitFor(() => {
expect(window.location.pathname).toBe('/home');
await waitFor(() => {
expect(mockNavigate).toHaveBeenCalledWith('/home');
});
});

View File

@@ -7,7 +7,14 @@ import {
import { cloneDeep, set } from 'lodash';
import {
act, fireEvent, render, waitFor, within, screen, initializeMocks,
act,
cleanup,
fireEvent,
initializeMocks,
render,
waitFor,
within,
screen,
} from '@src/testUtils';
import { IFRAME_FEATURE_POLICY } from '@src/constants';
import { mockWaffleFlags } from '@src/data/apiHooks.mock';
@@ -790,9 +797,10 @@ describe('<CourseUnit />', () => {
.reply(200, {
...updatedCourseSectionVerticalData,
});
cleanup(); // clear the first render before we create the second.
render(<RootWrapper />);
// to wait for loading
screen.findByTestId('unit-header-title');
await screen.findByTestId('unit-header-title');
// The new unit button should not be visible when childAddable is false
expect(
screen.queryByRole('button', { name: courseSequenceMessages.newUnitBtnText.defaultMessage }),

View File

@@ -88,6 +88,7 @@ const UnitInfoSettings = () => {
groupAccess: Object | null,
isDiscussionEnabled: boolean,
) => {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
await dispatch(editCourseUnitVisibilityAndData(
id,
PUBLISH_TYPES.republish,

View File

@@ -83,8 +83,10 @@ const UpdateForm = ({
showPopperArrow={false}
onChange={(value) => {
if (!isValidDate(value)) {
/* istanbul ignore next */
return;
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('date', convertToStringFromDate(value));
}}
/>
@@ -103,8 +105,8 @@ const UpdateForm = ({
data-testid="course-updates-wisiwyg-editor"
name={contentFieldName}
minHeight={300}
onChange={(value) => {
setFieldValue(contentFieldName, value || DEFAULT_EMPTY_WYSIWYG_VALUE);
onChange={/* istanbul ignore next: we can't test WYSIWYG editors */async (value) => {
await setFieldValue(contentFieldName, value || DEFAULT_EMPTY_WYSIWYG_VALUE);
}}
/>
</Form.Group>

View File

@@ -70,7 +70,7 @@ export async function getDownload(selectedRows, courseId) {
definedAssets.forEach((assetBlob, index) => {
folder.file(assetNames[index], assetBlob.value, { blob: true });
});
zip.generateAsync({ type: 'blob' }).then(content => {
await zip.generateAsync({ type: 'blob' }).then(content => {
saveAs(content, `${courseId}-assets-${date}.zip`);
});
}

View File

@@ -58,6 +58,7 @@ const MoreInfoColumn = ({
as={Button}
variant="tertiary"
onClick={() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
navigator.clipboard.writeText(id);
close();
}}
@@ -70,6 +71,7 @@ const MoreInfoColumn = ({
as={Button}
variant="tertiary"
onClick={() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
navigator.clipboard.writeText(portableUrl);
close();
}}
@@ -80,6 +82,7 @@ const MoreInfoColumn = ({
as={Button}
variant="tertiary"
onClick={() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
navigator.clipboard.writeText(externalUrl);
close();
}}

View File

@@ -55,6 +55,7 @@ export function cancelAllUploads(courseId, uploadData) {
});
Object.entries(uploadData).forEach(([key, value]) => {
if (value.status === RequestStatus.IN_PROGRESS) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
updateVideoUploadStatus(
courseId,
key,
@@ -178,6 +179,7 @@ export function markVideoUploadsInProgressAsFailed({ uploadingIdsRef, courseId }
return (dispatch) => {
Object.keys(uploadingIdsRef.current.uploadData).forEach((edxVideoId) => {
try {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
updateVideoUploadStatus(
courseId,
edxVideoId || '',
@@ -246,7 +248,7 @@ const uploadToBucket = async ({
...currentVideoData,
status: RequestStatus.SUCCESSFUL,
};
updateVideoUploadStatus(
await updateVideoUploadStatus(
courseId,
edxVideoId,
'Upload completed',
@@ -270,7 +272,7 @@ const uploadToBucket = async ({
status: RequestStatus.FAILED,
};
}
updateVideoUploadStatus(
await updateVideoUploadStatus(
courseId,
edxVideoId || '',
'Upload failed',

View File

@@ -155,6 +155,7 @@ const CreateOrRerunCourseForm = ({
const handleCustomBlurForDropdown = (e) => {
// it needs to correct handleOnChange Form.Autosuggest
const { value, name } = e.target;
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue(name, value);
handleBlur(e);
};

View File

@@ -88,7 +88,7 @@ describe('generic api calls', () => {
it('should throw an error if no pattern is provided', async () => {
const pattern = undefined;
expect(getTagsCount(pattern)).rejects.toThrow('contentPattern is required');
await expect(getTagsCount(pattern)).rejects.toThrow('contentPattern is required');
expect(axiosMock.history.get.length).toEqual(0);
});
});

View File

@@ -58,6 +58,7 @@ export const InplaceTextEditor: React.FC<InplaceTextEditorProps> = ({
const handleOnKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
handleOnChangeText(event);
} else if (event.key === 'Escape') {
setIsActive(false);

View File

@@ -114,6 +114,7 @@ export const LegacyLibMigrationPage = () => {
break;
case 'confirmation-view':
setConfirmationButtonState('pending');
// eslint-disable-next-line @typescript-eslint/no-floating-promises
handleMigrate();
break;
default:

View File

@@ -431,7 +431,7 @@ describe('<LibraryAuthoringPage />', () => {
expect(mockResult0.display_name).toStrictEqual(displayName);
await renderLibraryPage();
waitFor(() => expect(screen.getAllByTestId('component-card-menu-toggle').length).toBeGreaterThan(0));
await waitFor(() => expect(screen.getAllByTestId('component-card-menu-toggle').length).toBeGreaterThan(0));
// Open menu
fireEvent.click((await screen.findAllByTestId('component-card-menu-toggle'))[0]);
@@ -455,7 +455,7 @@ describe('<LibraryAuthoringPage />', () => {
const displayName = 'Test Unit';
await renderLibraryPage();
waitFor(() => expect(screen.getAllByTestId('container-card-menu-toggle').length).toBeGreaterThan(0));
await waitFor(() => expect(screen.getAllByTestId('container-card-menu-toggle').length).toBeGreaterThan(0));
// Open menu
fireEvent.click((await screen.findAllByTestId('container-card-menu-toggle'))[0]);

View File

@@ -93,7 +93,7 @@ describe('<AddContent />', () => {
expect(screen.queryByRole('button', { name: /video/i })).toBeInTheDocument();
expect(screen.queryByRole('button', { name: /copy from clipboard/i })).not.toBeInTheDocument();
expect(await screen.findByRole('button', { name: /advanced \/ other/i })).toBeInTheDocument();
expect(await screen.queryByRole('button', { name: /existing library content/i })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /existing library content/i })).not.toBeInTheDocument();
});
it('should render advanced content buttons', async () => {

View File

@@ -59,6 +59,7 @@ export const ComponentAdvancedAssets: React.FC<Record<never, never>> = () => {
const deleter = useDeleteXBlockAsset(usageKey);
const [filePathToDelete, setConfirmDeleteAsset] = React.useState<string>('');
const deleteFile = React.useCallback(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
deleter.mutateAsync(filePathToDelete); // Don't wait for this before clearing the modal on the next line
setConfirmDeleteAsset('');
}, [filePathToDelete, usageKey]);

View File

@@ -143,7 +143,7 @@ describe('<ComponentInfo> Sidebar', () => {
// Should show the confirmation box
expect(await screen.findByText(/Confirm Publish/i)).toBeInTheDocument();
const secondPublishButton = await screen.getByRole('button', { name: /publish/i });
const secondPublishButton = screen.getByRole('button', { name: /publish/i });
secondPublishButton.click();
});
@@ -160,7 +160,7 @@ describe('<ComponentInfo> Sidebar', () => {
// Should show the confirmation box
expect(await screen.findByText(/Confirm Publish/i)).toBeInTheDocument();
const secondPublishButton = await screen.getByRole('button', { name: /publish/i });
const secondPublishButton = screen.getByRole('button', { name: /publish/i });
secondPublishButton.click();
});
@@ -177,7 +177,7 @@ describe('<ComponentInfo> Sidebar', () => {
// Should show the confirmation box
expect(await screen.findByText(/Confirm Publish/i)).toBeInTheDocument();
const secondPublishButton = await screen.getByRole('button', { name: /publish/i });
const secondPublishButton = screen.getByRole('button', { name: /publish/i });
secondPublishButton.click();
});
@@ -195,7 +195,7 @@ describe('<ComponentInfo> Sidebar', () => {
// Should show the confirmation box
expect(await screen.findByText(/Confirm Publish/i)).toBeInTheDocument();
const secondPublishButton = await screen.getByRole('button', { name: /publish/i });
const secondPublishButton = screen.getByRole('button', { name: /publish/i });
secondPublishButton.click();
await waitFor(() => {
@@ -217,7 +217,7 @@ describe('<ComponentInfo> Sidebar', () => {
// Should show the confirmation box
expect(await screen.findByText(/Confirm Publish/i)).toBeInTheDocument();
const secondPublishButton = await screen.getByRole('button', { name: /publish/i });
const secondPublishButton = screen.getByRole('button', { name: /publish/i });
secondPublishButton.click();
await waitFor(() => {

View File

@@ -62,6 +62,7 @@ const AddComponentWidget = () => {
variant="outline-primary"
className="m-1 text-nowrap flex-grow-1"
onClick={() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
onComponentSelected({ usageKey, blockType: getBlockType(usageKey) });
}}
>
@@ -78,8 +79,10 @@ const AddComponentWidget = () => {
blockType: getBlockType(usageKey),
};
if (!isChecked) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
addComponentToSelectedComponents(selectedComponent);
} else {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
removeComponentFromSelectedComponents(selectedComponent);
}
};

View File

@@ -50,8 +50,8 @@ describe('<ComponentUsageTab />', () => {
render(mockLibraryBlockMetadata.usageKeyPublished);
expect(await screen.findByText('text block 0')).toBeInTheDocument();
expect(await screen.getByText('4 Units')).toBeInTheDocument();
expect(await screen.getByText('3 Subsections')).toBeInTheDocument();
expect(await screen.getByText('2 Sections')).toBeInTheDocument();
expect(screen.getByText('4 Units')).toBeInTheDocument();
expect(screen.getByText('3 Subsections')).toBeInTheDocument();
expect(screen.getByText('2 Sections')).toBeInTheDocument();
});
});

View File

@@ -69,8 +69,10 @@ const AddComponentWidget = ({ usageKey, blockType }: AddComponentWidgetProps) =>
blockType,
};
if (!isChecked) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
addComponentToSelectedComponents(selectedComponent);
} else {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
removeComponentFromSelectedComponents(selectedComponent);
}
};

View File

@@ -54,6 +54,7 @@ export const ComponentMenu = ({ usageKey, index }: Props) => {
const { copyToClipboard } = useClipboard();
const updateClipboardClick = () => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
copyToClipboard(usageKey);
};

View File

@@ -95,6 +95,7 @@ export const ContainerMenu = ({ containerKey, displayName, index } : ContainerMe
}, [navigateTo, containerKey]);
const handleCopy = useCallback(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
copyToClipboard(containerKey);
}, [copyToClipboard, containerKey]);

View File

@@ -44,6 +44,7 @@ const ContainerMenu = ({ containerId }: ContainerPreviewProps) => {
const { copyToClipboard } = useClipboard();
const handleCopy = useCallback(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
copyToClipboard(containerId);
}, [copyToClipboard, containerId]);

View File

@@ -123,10 +123,10 @@ export const ItemHierarchyPublisher = ({
{intl.formatMessage(messages.publishCancel)}
</Button>
<LoadingButton
onClick={async (e) => {
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
await handlePublish();
handlePublish();
}}
variant="primary rounded-0"
label={intl.formatMessage(messages.publishConfirm)}

View File

@@ -104,7 +104,7 @@ describe('<ImportDetailsPage />', () => {
name: /view imported content/i,
});
await viewImportedContentBtn.click();
viewImportedContentBtn.click();
await waitFor(() => expect(mockNavigate).toHaveBeenCalledWith('/library/lib:Axim:TEST/collection/coll'));
});

View File

@@ -132,6 +132,7 @@ const ImportDetailsContent = () => {
migrationStatus = 'Failed';
} else if (migrationStatusData?.state === 'Succeeded') {
// refetch migrationBlockInfo data once the import is complete
// eslint-disable-next-line @typescript-eslint/no-floating-promises
refetchMigrationBlockInfo();
// Currently, bulk migrate is being used to migrate courses because
// it has the ability to create collections.

View File

@@ -460,6 +460,7 @@ const ScanResults: FC<Props> = ({
const handleUpdateCompletion = async () => {
if (rerunLinkUpdateInProgress === false && isUpdateAllInProgress) {
try {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
const updateStatusResponse = await dispatch(fetchRerunLinkUpdateStatus(courseId)) as any;
if (!updateStatusResponse) {
@@ -506,6 +507,7 @@ const ScanResults: FC<Props> = ({
}
};
// eslint-disable-next-line @typescript-eslint/no-floating-promises
handleUpdateCompletion();
}, [rerunLinkUpdateInProgress,
isUpdateAllInProgress,
@@ -590,6 +592,7 @@ const ScanResults: FC<Props> = ({
try {
setUpdatingLinkIds(prev => ({ ...prev, [uniqueId]: true }));
const contentType = getContentType(sectionId || '');
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
await dispatch(updateSinglePreviousRunLink(courseId, link, blockId, contentType));
const pollForSingleLinkResult = async (attempts = 0): Promise<boolean> => {
@@ -597,6 +600,7 @@ const ScanResults: FC<Props> = ({
throw new Error('Timeout waiting for link update result');
}
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
const updateStatusResponse = await dispatch(fetchRerunLinkUpdateStatus(courseId)) as any;
const pollStatus = updateStatusResponse?.status || updateStatusResponse?.updateStatus;
@@ -755,6 +759,7 @@ const ScanResults: FC<Props> = ({
try {
setProcessedResponseIds(new Set());
setIsUpdateAllInProgress(true);
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
await dispatch(updateAllPreviousRunLinks(courseId));
return true;

View File

@@ -72,13 +72,14 @@ const AppSettingsModal = ({
const handleFormSubmit = async (values) => {
let success = true;
if (appInfo.enabled !== values.enabled) {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
success = await dispatch(updateAppStatus(courseId, appInfo.id, values.enabled));
}
// Call the submit handler for the settings component to save its settings
if (onSettingsSave) {
success = success && await onSettingsSave(values);
}
await setSaveError(!success);
setSaveError(!success);
!success && alertRef?.current.scrollIntoView(); // eslint-disable-line @typescript-eslint/no-unused-expressions
};
@@ -86,7 +87,8 @@ const AppSettingsModal = ({
// If submitting the form with errors, show the alert and scroll to it.
await handleSubmit(event);
if (Object.keys(errors).length > 0) {
await setSaveError(true);
/* istanbul ignore next: temp to unblock lint cleanup. We probably should test this. */
setSaveError(true);
alertRef?.current.scrollIntoView?.(); // eslint-disable-line no-unused-expressions
}
};

View File

@@ -46,7 +46,9 @@ const AppConfigForm = ({
const [confirmationDialogVisible, setConfirmationDialogVisible] = useState(false);
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
// oxlint-disable-next-line @typescript-eslint/await-thenable - this dispatch() IS returning a promise.
await dispatch(fetchDiscussionSettings(courseId, selectedAppId));
setLoading(false);
})();

View File

@@ -24,12 +24,14 @@ const DiscussionRestriction = () => {
setSelectedRestrictionOption(value);
if (value !== discussionRestriction.ENABLED) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('postingRestrictions', value);
}
}, []);
const handleConfirmation = useCallback(() => {
setSelectedRestrictionOption(discussionRestriction.ENABLED);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('postingRestrictions', discussionRestriction.ENABLED);
}, []);

View File

@@ -36,10 +36,13 @@ const DivisionByGroupFields = () => {
useEffect(() => {
if (divideByCohorts) {
if (!divideCourseTopicsByCohorts && size(discussionTopics) !== size(divideDiscussionIds)) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('divideDiscussionIds', discussionTopics.map(topic => topic.id));
}
} else {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('divideDiscussionIds', []);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('divideCourseTopicsByCohorts', false);
}
}, [
@@ -59,6 +62,7 @@ const DivisionByGroupFields = () => {
const handleDivideCourseTopicsByCohortsToggle = (event) => {
const { checked } = event.target;
if (!checked) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('divideDiscussionIds', []);
}
handleChange(event);

View File

@@ -19,6 +19,7 @@ const InContextDiscussionFields = ({
const [showPopup, setShowPopup] = useState(false);
const handleConfirmation = () => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('enableGradedUnits', !values.enableGradedUnits);
setShowPopup(false);
};

View File

@@ -29,6 +29,7 @@ const RestrictionSchedules = () => {
...updatedRestrictedDates[index],
status: checkStatus(denormalizeRestrictedDate(updatedRestrictedDates[index])),
};
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('restrictedDates', updatedRestrictedDates);
}, [restrictedDates]);
@@ -43,7 +44,7 @@ const RestrictionSchedules = () => {
const onAddNewItem = useCallback(async (push) => {
await push(newRestrictedDateItem);
validateForm();
await validateForm();
}, []);
return (

View File

@@ -26,13 +26,14 @@ const DiscussionTopics = () => {
const handleTopicDelete = async (topicIndex, topicId, remove) => {
await remove(topicIndex);
validateForm();
await validateForm();
setValidDiscussionTopics(filterItemFromObject(validDiscussionTopics, 'id', topicId));
};
const handleOnFocus = useCallback((id, hasError) => {
if (hasError) {
setValidDiscussionTopics(currentValidTopics => filterItemFromObject(currentValidTopics, 'id', id));
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('divideDiscussionIds', filterItemFromObject(divideDiscussionIds, 'id', id));
} else {
setValidDiscussionTopics(currentValidTopics => {
@@ -40,6 +41,7 @@ const DiscussionTopics = () => {
const allValidTopics = removeElements(allDiscussionTopics, topic => topic.name !== '');
return uniqBy(allValidTopics, 'id');
});
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setFieldValue('divideDiscussionIds', uniq([...divideDiscussionIds, id]));
}
}, [divideDiscussionIds, discussionTopics]);

View File

@@ -107,7 +107,7 @@ mockFetchIndexDocuments.applyMock = () => {
/**
* Mock the useGetContentHits
*/
export async function mockGetContentHits(
export function mockGetContentHits(
mockResponse: 'noHits' | 'someHits',
) {
fetchMock.post(mockContentSearchConfig.searchEndpointUrl, () => {

View File

@@ -187,7 +187,12 @@ export const useContentSearchResults = ({
// Call this to load more pages. We include some "safety" features recommended by the docs: this should never be
// called while already fetching a page, and parameters (like 'event') should not be passed into fetchNextPage().
// See https://tanstack.com/query/v4/docs/framework/react/guides/infinite-queries
fetchNextPage: () => { if (!query.isFetching && !query.isFetchingNextPage) { query.fetchNextPage(); } },
fetchNextPage: /* istanbul ignore next */ () => {
if (!query.isFetching && !query.isFetchingNextPage) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
query.fetchNextPage();
}
},
hasNextPage: query.hasNextPage,
// The last page has the most accurate count of total hits
totalHits: pages?.[pages.length - 1]?.totalHits ?? 0,

View File

@@ -175,7 +175,7 @@ describe('<TaxonomyListPage />', () => {
} = render(<TaxonomyListPage />);
// Open the taxonomies org filter select menu
const taxonomiesFilterSelectMenu = await getByRole('button', { name: 'All taxonomies' });
const taxonomiesFilterSelectMenu = getByRole('button', { name: 'All taxonomies' });
fireEvent.click(taxonomiesFilterSelectMenu);
// Check that the 'Unassigned' option is correctly called

View File

@@ -41,6 +41,7 @@ const TaxonomyMenu = ({
const { setToastMessage } = useContext(TaxonomyContext);
const onDeleteTaxonomy = useCallback(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
deleteTaxonomy({ pk: taxonomy.id }, {
onSuccess: () => {
if (setToastMessage) {

View File

@@ -175,7 +175,7 @@ describe('<TextbookCard />', () => {
.onDelete(getEditTextbooksApiUrl(courseId, textbookId))
.reply(200);
executeThunk(deleteTextbookQuery(courseId, textbookId), store.dispatch);
await executeThunk(deleteTextbookQuery(courseId, textbookId), store.dispatch);
});
});
});