- {olxUpdater.error && (
+ {olxUpdater.error ? (
-
- {/*
- TODO: fix the API so it returns 400 errors in a JSON object, not HTML 500 errors. Then display
- a useful error message here like "parsing the XML failed on line 3".
- (olxUpdater.error as Record)?.customAttributes?.httpErrorResponseData.errorMessage
- */}
+ <>
+
+ {/*
+ TODO: fix the API so it returns 400 errors in a JSON object, not HTML 500 errors. Then display
+ a useful error message here like "parsing the XML failed on line 3".
+ (olxUpdater.error as Record)?.customAttributes?.httpErrorResponseData.errorMessage
+ */}
+ >
- )}
+ ) : null}
{olx}
{
isEditingOLX ? (
diff --git a/src/library-authoring/create-collection/CreateCollectionModal.tsx b/src/library-authoring/create-collection/CreateCollectionModal.tsx
index de9e776cf..fccd59885 100644
--- a/src/library-authoring/create-collection/CreateCollectionModal.tsx
+++ b/src/library-authoring/create-collection/CreateCollectionModal.tsx
@@ -44,6 +44,7 @@ const CreateCollectionModal = () => {
size="xl"
hasCloseButton
isFullscreenOnMobile
+ isOverflowVisible
>
diff --git a/src/library-authoring/data/apiHooks.test.tsx b/src/library-authoring/data/apiHooks.test.tsx
index 4cf659fb5..746e0139d 100644
--- a/src/library-authoring/data/apiHooks.test.tsx
+++ b/src/library-authoring/data/apiHooks.test.tsx
@@ -2,8 +2,7 @@ import React from 'react';
import { initializeMockApp } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
-import { waitFor } from '@testing-library/react';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import MockAdapter from 'axios-mock-adapter';
import {
diff --git a/src/pages-and-resources/PagesAndResources.jsx b/src/pages-and-resources/PagesAndResources.jsx
index 51aaa254d..0733a76cd 100644
--- a/src/pages-and-resources/PagesAndResources.jsx
+++ b/src/pages-and-resources/PagesAndResources.jsx
@@ -1,4 +1,4 @@
-import React, { useContext, useEffect, Suspense } from 'react';
+import React, { useContext, useEffect } from 'react';
import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
@@ -86,7 +86,7 @@ const PagesAndResources = ({ courseId, intl }) => {
} />
} />
} />
- } />
+ } />
diff --git a/src/pages-and-resources/SettingsComponent.jsx b/src/pages-and-resources/SettingsComponent.jsx
index bf6d29530..4600d17ef 100644
--- a/src/pages-and-resources/SettingsComponent.jsx
+++ b/src/pages-and-resources/SettingsComponent.jsx
@@ -25,7 +25,11 @@ const SettingsComponent = ({ url }) => {
[appId],
);
- return navigate(url)} />;
+ return (
+
+ navigate(url)} />
+
+ );
};
SettingsComponent.propTypes = {
diff --git a/src/pages-and-resources/SettingsComponent.test.jsx b/src/pages-and-resources/SettingsComponent.test.jsx
index 21b3aa424..9a5fee4fb 100644
--- a/src/pages-and-resources/SettingsComponent.test.jsx
+++ b/src/pages-and-resources/SettingsComponent.test.jsx
@@ -1,5 +1,5 @@
-import React, { Suspense } from 'react';
-import { useParams } from 'react-router-dom';
+import React from 'react';
+import { useParams, useLocation } from 'react-router-dom';
import { render, screen, waitFor } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { AppProvider } from '@edx/frontend-platform/react';
@@ -8,6 +8,7 @@ import { initializeMockApp } from '@edx/frontend-platform/testing';
import PagesAndResourcesProvider from 'CourseAuthoring/pages-and-resources/PagesAndResourcesProvider';
import initializeStore from 'CourseAuthoring/store';
import { RequestStatus } from 'CourseAuthoring/data/constants';
+import userEvent from '@testing-library/user-event';
import SettingsComponent from './SettingsComponent';
jest.mock('react-router-dom', () => ({
@@ -51,19 +52,44 @@ describe('SettingsComponent', () => {
test('renders LazyLoadedComponent when provided with props', async () => {
useParams.mockImplementation(() => ({ appId: 'wiki' }));
- const rendered = render(
-
-
- ,
+ render(
+ ,
{ wrapper: RequiredProviders },
);
- await waitFor(() => expect(rendered.getByText('Configure wiki')).toBeInTheDocument());
+ await screen.findByText('Configure wiki');
const modalComponent = screen.getByRole('dialog');
expect(modalComponent.querySelector('#enable-wiki-toggleHelpText')).toContainHTML('The course wiki can be set up');
});
+ test('navigates to provided url when closing', async () => {
+ useParams.mockImplementation(() => ({ appId: 'wiki' }));
+
+ const LocationDisplay = () => {
+ const location = useLocation();
+
+ return {location.pathname}
;
+ };
+
+ render(
+ <>
+
+
+ >,
+ { wrapper: RequiredProviders },
+ );
+
+ await screen.findByText('Configure wiki');
+ const firstLocation = await screen.findByTestId('location-display');
+ expect(firstLocation).toHaveTextContent('/');
+
+ const cancelButton = await screen.findByText('Cancel');
+ await userEvent.click(cancelButton);
+ const secondLocation = await screen.findByTestId('location-display');
+ expect(secondLocation).toHaveTextContent('/some-url');
+ });
+
test('renders error message when plugin is unavilable when provided with props', async () => {
// Silence noisy error about the plugin failing to load, when we do that deliberately.
jest.spyOn(console, 'trace').mockImplementation(() => {});
@@ -71,9 +97,7 @@ describe('SettingsComponent', () => {
useParams.mockImplementation(() => ({ appId: 'invalid-plugin' }));
const rendered = render(
-
-
- ,
+ ,
{ wrapper: RequiredProviders },
);
diff --git a/src/pages-and-resources/discussions/DiscussionsSettings.test.jsx b/src/pages-and-resources/discussions/DiscussionsSettings.test.jsx
index 60a257ee1..0c4a62cf9 100644
--- a/src/pages-and-resources/discussions/DiscussionsSettings.test.jsx
+++ b/src/pages-and-resources/discussions/DiscussionsSettings.test.jsx
@@ -414,13 +414,19 @@ describe.each([
const showLTIConfig = isAdmin;
renderComponent(`/course/${courseId}/pages-and-resources/discussion`);
- // This is an important line that ensures the spinner has been removed - and thus our main
- // content has been loaded - prior to proceeding with our expectations.
- await waitForElementToBeRemoved(screen.queryByRole('status'));
- userEvent.click(screen.getByLabelText('Select Piazza'));
- userEvent.click(queryByText(container, messages.nextButton.defaultMessage));
- expect(screen.queryByRole('status')).not.toBeInTheDocument();
+ let spinner = await screen.findByRole('status');
+ await waitFor(() => {
+ expect(spinner).not.toBeInTheDocument();
+ });
+
+ await userEvent.click(screen.getByLabelText('Select Piazza'));
+ await userEvent.click(queryByText(container, messages.nextButton.defaultMessage));
+
+ spinner = await screen.findByRole('status');
+ await waitFor(() => {
+ expect(spinner).not.toBeInTheDocument();
+ });
await waitFor(() => {
if (showLTIConfig) {
@@ -468,14 +474,20 @@ describe.each([
test(`${piiSharingAllowed ? 'shows PII share username/email field when piiSharingAllowed is true'
: 'hides PII share username/email field when piiSharingAllowed is false'}`, async () => {
renderComponent(`/course/${courseId}/pages-and-resources/discussion`);
- // This is an important line that ensures the spinner has been removed - and thus our main
- // content has been loaded - prior to proceeding with our expectations.
- await waitForElementToBeRemoved(screen.queryByRole('status'));
- userEvent.click(screen.getByLabelText('Select Piazza'));
- userEvent.click(screen.getByText(messages.nextButton.defaultMessage));
+ let spinner = await screen.findByRole('status');
+ await waitFor(() => {
+ expect(spinner).not.toBeInTheDocument();
+ });
+
+ await userEvent.click(screen.getByLabelText('Select Piazza'));
+ await userEvent.click(screen.getByText(messages.nextButton.defaultMessage));
+
+ spinner = await screen.findByRole('status');
+ await waitFor(() => {
+ expect(spinner).not.toBeInTheDocument();
+ });
- expect(screen.queryByRole('status')).not.toBeInTheDocument();
if (enablePIISharing) {
expect(queryByTestId(container, 'piiSharingFields')).toBeInTheDocument();
} else {
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
index ddff4fee9..3b180206e 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/openedx/OpenedXConfigForm.test.jsx
@@ -4,8 +4,9 @@ import {
act,
fireEvent,
queryAllByText,
+ findByLabelText,
queryByLabelText,
- queryByRole,
+ findByRole,
queryByTestId,
queryByText,
render,
@@ -320,18 +321,12 @@ describe('OpenedXConfigForm', () => {
});
test('check duplicate error is removed on deleting duplicate topic', async () => {
- await act(async () => {
- userEvent.click(
- queryByLabelText(duplicateTopicCard, messages.deleteAltText.defaultMessage, { selector: 'button' }),
- );
- });
-
- await act(async () => {
- userEvent.click(
- queryByRole(container, 'button', { name: messages.deleteButton.defaultMessage }),
- );
- });
-
+ await userEvent.click(
+ await findByLabelText(duplicateTopicCard, messages.deleteAltText.defaultMessage, { selector: 'button' }),
+ );
+ await userEvent.click(
+ await findByRole(container, 'button', { name: messages.deleteButton.defaultMessage }),
+ );
await waitForElementToBeRemoved(queryByText(topicCard, messages.discussionTopicNameAlreadyExist.defaultMessage));
expect(duplicateTopicCard).not.toBeInTheDocument();
diff --git a/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/TopicItem.test.jsx b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/TopicItem.test.jsx
index 46e122205..b849f3bba 100644
--- a/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/TopicItem.test.jsx
+++ b/src/pages-and-resources/discussions/app-config-form/apps/shared/discussion-topics/TopicItem.test.jsx
@@ -4,7 +4,9 @@ import {
queryAllByTestId,
queryAllByText,
queryByRole,
+ findByTestId,
queryByTestId,
+ findByText,
queryByText,
queryByLabelText,
render,
@@ -158,10 +160,10 @@ describe('TopicItem', () => {
await mockStore(legacyApiResponse);
createComponent(additionalTopic);
- const topicCard = queryByTestId(container, '13f106c6-6735-4e84-b097-0456cff55960');
+ const topicCard = await findByTestId(container, '13f106c6-6735-4e84-b097-0456cff55960');
userEvent.click(queryByLabelText(topicCard, 'Expand'));
topicCard.querySelector('input').focus();
- expect(queryByText(topicCard, messages.addTopicHelpText.defaultMessage)).toBeInTheDocument();
+ await findByText(topicCard, messages.addTopicHelpText.defaultMessage);
});
});
diff --git a/src/search-manager/data/apiHooks.test.tsx b/src/search-manager/data/apiHooks.test.tsx
index e21c581bf..4a7d7c878 100644
--- a/src/search-manager/data/apiHooks.test.tsx
+++ b/src/search-manager/data/apiHooks.test.tsx
@@ -1,6 +1,5 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { waitFor } from '@testing-library/react';
-import { renderHook } from '@testing-library/react-hooks';
+import { renderHook, waitFor } from '@testing-library/react';
import fetchMock from 'fetch-mock-jest';
import mockResult from './__mocks__/block-types.json';
diff --git a/src/setupTest.js b/src/setupTest.js
index 923399a41..6c24a7523 100755
--- a/src/setupTest.js
+++ b/src/setupTest.js
@@ -1,5 +1,4 @@
import '@testing-library/jest-dom';
-import '@testing-library/jest-dom/extend-expect';
import { mergeConfig } from '@edx/frontend-platform';
diff --git a/src/studio-home/tabs-section/courses-tab/courses-filters/courses-filter-menu/__snapshots__/index.test.jsx.snap b/src/studio-home/tabs-section/courses-tab/courses-filters/courses-filter-menu/__snapshots__/index.test.jsx.snap
index 1e4a3c377..d74c78c4c 100644
--- a/src/studio-home/tabs-section/courses-tab/courses-filters/courses-filter-menu/__snapshots__/index.test.jsx.snap
+++ b/src/studio-home/tabs-section/courses-tab/courses-filters/courses-filter-menu/__snapshots__/index.test.jsx.snap
@@ -15,9 +15,7 @@ exports[`CoursesFilterMenu snapshot 1`] = `
data-testid="course-filter-menu-toggle"
id="course-filter-menu-toggle"
type="button"
- >
-
-
+ />
`;
diff --git a/src/taxonomy/TaxonomyLayout.test.tsx b/src/taxonomy/TaxonomyLayout.test.tsx
index 4333c0465..719835d91 100644
--- a/src/taxonomy/TaxonomyLayout.test.tsx
+++ b/src/taxonomy/TaxonomyLayout.test.tsx
@@ -1,5 +1,6 @@
import React, { useContext } from 'react';
+import userEvent from '@testing-library/user-event';
import { initializeMocks, render, screen } from '../testUtils';
import { TaxonomyContext } from './common/context';
import { TaxonomyLayout } from './TaxonomyLayout';
@@ -61,16 +62,16 @@ describe('