From b8e08d8a8f3f95bfc2df9a814ec0f5bcb18bec34 Mon Sep 17 00:00:00 2001 From: Maxwell Frank <92897870+MaxFrank13@users.noreply.github.com> Date: Wed, 3 Apr 2024 13:41:20 -0400 Subject: [PATCH] Refactor course list and empty state (#308) Co-authored-by: Maxwell Frank --- package-lock.json | 2 +- package.json | 2 +- .../__snapshots__/index.test.jsx.snap | 185 ------------------ src/containers/CourseList/index.jsx | 77 -------- .../__snapshots__/index.test.jsx.snap | 70 +++++++ .../CoursesPanel/CourseList/hooks.js | 8 + .../CoursesPanel/CourseList/index.jsx | 51 +++++ .../CourseList/index.test.jsx | 31 +-- .../__snapshots__/index.test.jsx.snap | 0 .../NoCoursesView/index.jsx | 0 .../NoCoursesView/index.scss | 0 .../NoCoursesView/index.test.jsx | 0 .../NoCoursesView/messages.js | 0 .../__snapshots__/index.test.jsx.snap | 51 +++++ .../{CourseList => CoursesPanel}/hooks.js | 10 +- .../hooks.test.js | 0 src/containers/CoursesPanel/index.jsx | 48 +++++ .../{CourseList => CoursesPanel}/index.scss | 0 src/containers/CoursesPanel/index.test.jsx | 55 ++++++ .../{CourseList => CoursesPanel}/messages.js | 0 .../__snapshots__/index.test.jsx.snap | 4 +- src/containers/Dashboard/index.jsx | 4 +- src/containers/Dashboard/index.test.jsx | 8 +- .../app/selectors/simpleSelectors.test.js | 1 + src/widgets/ProductRecommendations/index.jsx | 2 +- .../ProductRecommendations/index.test.jsx | 4 +- 26 files changed, 305 insertions(+), 308 deletions(-) delete mode 100644 src/containers/CourseList/__snapshots__/index.test.jsx.snap delete mode 100644 src/containers/CourseList/index.jsx create mode 100644 src/containers/CoursesPanel/CourseList/__snapshots__/index.test.jsx.snap create mode 100644 src/containers/CoursesPanel/CourseList/hooks.js create mode 100644 src/containers/CoursesPanel/CourseList/index.jsx rename src/containers/{ => CoursesPanel}/CourseList/index.test.jsx (68%) rename src/containers/{CourseList => CoursesPanel}/NoCoursesView/__snapshots__/index.test.jsx.snap (100%) rename src/containers/{CourseList => CoursesPanel}/NoCoursesView/index.jsx (100%) rename src/containers/{CourseList => CoursesPanel}/NoCoursesView/index.scss (100%) rename src/containers/{CourseList => CoursesPanel}/NoCoursesView/index.test.jsx (100%) rename src/containers/{CourseList => CoursesPanel}/NoCoursesView/messages.js (100%) create mode 100644 src/containers/CoursesPanel/__snapshots__/index.test.jsx.snap rename src/containers/{CourseList => CoursesPanel}/hooks.js (82%) rename src/containers/{CourseList => CoursesPanel}/hooks.test.js (100%) create mode 100644 src/containers/CoursesPanel/index.jsx rename src/containers/{CourseList => CoursesPanel}/index.scss (100%) create mode 100644 src/containers/CoursesPanel/index.test.jsx rename src/containers/{CourseList => CoursesPanel}/messages.js (100%) diff --git a/package-lock.json b/package-lock.json index 91de9b9..31a8501 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@fortawesome/free-brands-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.15", - "@openedx/frontend-plugin-framework": "1.0.2", + "@openedx/frontend-plugin-framework": "^1.0.2", "@openedx/paragon": "^21.11.3", "@optimizely/react-sdk": "^2.9.2", "@redux-beacon/segment": "^1.1.0", diff --git a/package.json b/package.json index 6705b2f..6b85510 100755 --- a/package.json +++ b/package.json @@ -33,11 +33,11 @@ "@edx/frontend-platform": "7.1.0", "@edx/openedx-atlas": "^0.6.0", "@edx/react-unit-test-utils": "2.0.0", - "@openedx/frontend-plugin-framework": "1.0.2", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-brands-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.15", + "@openedx/frontend-plugin-framework": "^1.0.2", "@openedx/paragon": "^21.11.3", "@optimizely/react-sdk": "^2.9.2", "@redux-beacon/segment": "^1.1.0", diff --git a/src/containers/CourseList/__snapshots__/index.test.jsx.snap b/src/containers/CourseList/__snapshots__/index.test.jsx.snap deleted file mode 100644 index fe6523e..0000000 --- a/src/containers/CourseList/__snapshots__/index.test.jsx.snap +++ /dev/null @@ -1,185 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CourseList collapsed with multiple courses and pages snapshot 1`] = ` -
-
-

- My Courses -

-
- -
-
- -
- -
-
- - - - -
-
-
-`; - -exports[`CourseList no courses snapshot 1`] = ` -
-
-

- My Courses -

-
- -
-
- -
- -
-`; - -exports[`CourseList no filters snapshot 1`] = ` -
-
-

- My Courses -

-
- -
-
- -
- -
-`; - -exports[`CourseList with filters snapshot 1`] = ` -
-
-

- My Courses -

-
- -
-
- -
- -
-
- -
-`; - -exports[`CourseList with multiple courses and pages snapshot 1`] = ` -
-
-

- My Courses -

-
- -
-
- -
- - - - -
-
-
-`; diff --git a/src/containers/CourseList/index.jsx b/src/containers/CourseList/index.jsx deleted file mode 100644 index 6ca9819..0000000 --- a/src/containers/CourseList/index.jsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from 'react'; - -import { useIntl } from '@edx/frontend-platform/i18n'; -import { Pagination } from '@openedx/paragon'; - -import { reduxHooks } from 'hooks'; -import { - ActiveCourseFilters, - CourseFilterControls, -} from 'containers/CourseFilterControls'; -import CourseCard from 'containers/CourseCard'; -import NoCoursesView from './NoCoursesView'; - -import { useCourseListData, useIsCollapsed } from './hooks'; - -import messages from './messages'; - -import './index.scss'; - -/** - * Renders the list of CourseCards, as well as the controls (CourseFilterControls) for modifying the list. - * Also houses the NoCoursesView to display if the user hasn't enrolled in any courses. - * @returns List of courses as CourseCards - */ -export const CourseList = () => { - const { formatMessage } = useIntl(); - const hasCourses = reduxHooks.useHasCourses(); - const { - filterOptions, - setPageNumber, - numPages, - showFilters, - visibleList, - } = useCourseListData(); - const isCollapsed = useIsCollapsed(); - - return ( -
-
-

{formatMessage(messages.myCourses)}

-
- -
-
- {hasCourses - ? ( - <> - {showFilters && ( -
- -
- )} -
- {visibleList.map(({ cardId }) => ( - - ))} - {numPages > 1 && ( - - )} -
- - ) : ( - - )} -
- ); -}; - -CourseList.propTypes = {}; - -export default CourseList; diff --git a/src/containers/CoursesPanel/CourseList/__snapshots__/index.test.jsx.snap b/src/containers/CoursesPanel/CourseList/__snapshots__/index.test.jsx.snap new file mode 100644 index 0000000..8988932 --- /dev/null +++ b/src/containers/CoursesPanel/CourseList/__snapshots__/index.test.jsx.snap @@ -0,0 +1,70 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CourseList collapsed with multiple courses and pages snapshot 1`] = ` + +
+ +
+
+ + + + +
+
+`; + +exports[`CourseList no courses or filters snapshot 1`] = ` + +
+ +`; + +exports[`CourseList with filters snapshot 1`] = `undefined`; + +exports[`CourseList with multiple courses and pages snapshot 1`] = ` + +
+ + + + +
+
+`; diff --git a/src/containers/CoursesPanel/CourseList/hooks.js b/src/containers/CoursesPanel/CourseList/hooks.js new file mode 100644 index 0000000..9cff96c --- /dev/null +++ b/src/containers/CoursesPanel/CourseList/hooks.js @@ -0,0 +1,8 @@ +import { useWindowSize, breakpoints } from '@openedx/paragon'; + +export const useIsCollapsed = () => { + const { width } = useWindowSize(); + return width < breakpoints.medium.maxWidth; +}; + +export default useIsCollapsed; diff --git a/src/containers/CoursesPanel/CourseList/index.jsx b/src/containers/CoursesPanel/CourseList/index.jsx new file mode 100644 index 0000000..2f6111a --- /dev/null +++ b/src/containers/CoursesPanel/CourseList/index.jsx @@ -0,0 +1,51 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { Pagination } from '@openedx/paragon'; +import { + ActiveCourseFilters, +} from 'containers/CourseFilterControls'; +import CourseCard from 'containers/CourseCard'; + +import { useIsCollapsed } from './hooks'; + +export const CourseList = ({ + filterOptions, setPageNumber, numPages, showFilters, visibleList, +}) => { + const isCollapsed = useIsCollapsed(); + return ( + <> + {showFilters && ( +
+ +
+ )} +
+ {visibleList.map(({ cardId }) => ( + + ))} + {numPages > 1 && ( + + )} +
+ + ); +}; + +CourseList.propTypes = { + showFilters: PropTypes.bool.isRequired, + // eslint-disable-next-line react/forbid-prop-types + visibleList: PropTypes.arrayOf(PropTypes.object).isRequired, + // eslint-disable-next-line react/forbid-prop-types + filterOptions: PropTypes.object.isRequired, + numPages: PropTypes.number.isRequired, + setPageNumber: PropTypes.func.isRequired, +}; + +export default CourseList; diff --git a/src/containers/CourseList/index.test.jsx b/src/containers/CoursesPanel/CourseList/index.test.jsx similarity index 68% rename from src/containers/CourseList/index.test.jsx rename to src/containers/CoursesPanel/CourseList/index.test.jsx index 8621722..a2e09b3 100644 --- a/src/containers/CourseList/index.test.jsx +++ b/src/containers/CoursesPanel/CourseList/index.test.jsx @@ -1,26 +1,17 @@ import { shallow } from '@edx/react-unit-test-utils'; -import { reduxHooks } from 'hooks'; -import { useCourseListData, useIsCollapsed } from './hooks'; +import { useIsCollapsed } from './hooks'; import CourseList from '.'; -jest.mock('hooks', () => ({ - reduxHooks: { useHasCourses: jest.fn() }, -})); - jest.mock('./hooks', () => ({ - useCourseListData: jest.fn(), useIsCollapsed: jest.fn(), })); jest.mock('containers/CourseCard', () => 'CourseCard'); jest.mock('containers/CourseFilterControls', () => ({ ActiveCourseFilters: 'ActiveCourseFilters', - CourseFilterControls: 'CourseFilterControls', })); -reduxHooks.useHasCourses.mockReturnValue(true); - describe('CourseList', () => { const defaultCourseListData = { filterOptions: {}, @@ -30,22 +21,12 @@ describe('CourseList', () => { visibleList: [], }; useIsCollapsed.mockReturnValue(false); - const createWrapper = (courseListData) => { - useCourseListData.mockReturnValueOnce({ - ...defaultCourseListData, - ...courseListData, - }); - return shallow(); - }; - describe('no courses', () => { - test('snapshot', () => { - reduxHooks.useHasCourses.mockReturnValue(true); - const wrapper = createWrapper(); - expect(wrapper.snapshot).toMatchSnapshot(); - }); - }); - describe('no filters', () => { + const createWrapper = (courseListData = defaultCourseListData) => ( + shallow() + ); + + describe('no courses or filters', () => { test('snapshot', () => { const wrapper = createWrapper(); expect(wrapper.snapshot).toMatchSnapshot(); diff --git a/src/containers/CourseList/NoCoursesView/__snapshots__/index.test.jsx.snap b/src/containers/CoursesPanel/NoCoursesView/__snapshots__/index.test.jsx.snap similarity index 100% rename from src/containers/CourseList/NoCoursesView/__snapshots__/index.test.jsx.snap rename to src/containers/CoursesPanel/NoCoursesView/__snapshots__/index.test.jsx.snap diff --git a/src/containers/CourseList/NoCoursesView/index.jsx b/src/containers/CoursesPanel/NoCoursesView/index.jsx similarity index 100% rename from src/containers/CourseList/NoCoursesView/index.jsx rename to src/containers/CoursesPanel/NoCoursesView/index.jsx diff --git a/src/containers/CourseList/NoCoursesView/index.scss b/src/containers/CoursesPanel/NoCoursesView/index.scss similarity index 100% rename from src/containers/CourseList/NoCoursesView/index.scss rename to src/containers/CoursesPanel/NoCoursesView/index.scss diff --git a/src/containers/CourseList/NoCoursesView/index.test.jsx b/src/containers/CoursesPanel/NoCoursesView/index.test.jsx similarity index 100% rename from src/containers/CourseList/NoCoursesView/index.test.jsx rename to src/containers/CoursesPanel/NoCoursesView/index.test.jsx diff --git a/src/containers/CourseList/NoCoursesView/messages.js b/src/containers/CoursesPanel/NoCoursesView/messages.js similarity index 100% rename from src/containers/CourseList/NoCoursesView/messages.js rename to src/containers/CoursesPanel/NoCoursesView/messages.js diff --git a/src/containers/CoursesPanel/__snapshots__/index.test.jsx.snap b/src/containers/CoursesPanel/__snapshots__/index.test.jsx.snap new file mode 100644 index 0000000..4ac541b --- /dev/null +++ b/src/containers/CoursesPanel/__snapshots__/index.test.jsx.snap @@ -0,0 +1,51 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CoursesPanel no courses snapshot 1`] = ` +
+
+

+ My Courses +

+
+ +
+
+ +
+`; + +exports[`CoursesPanel with courses snapshot 1`] = ` +
+
+

+ My Courses +

+
+ +
+
+ +
+`; diff --git a/src/containers/CourseList/hooks.js b/src/containers/CoursesPanel/hooks.js similarity index 82% rename from src/containers/CourseList/hooks.js rename to src/containers/CoursesPanel/hooks.js index f585b22..dcc5a60 100644 --- a/src/containers/CourseList/hooks.js +++ b/src/containers/CoursesPanel/hooks.js @@ -1,6 +1,5 @@ import React from 'react'; -import { useWindowSize, breakpoints } from '@openedx/paragon'; import queryString from 'query-string'; import { ListPageSize, SortKeys } from 'data/constants/app'; @@ -9,21 +8,16 @@ import { StrictDict } from 'utils'; import * as module from './hooks'; -export const useIsCollapsed = () => { - const { width } = useWindowSize(); - return width < breakpoints.medium.maxWidth; -}; - export const state = StrictDict({ sortBy: (val) => React.useState(val), // eslint-disable-line }); /** * Filters are fetched from the store and used to generate a list of "visible" courses. - * Other values returned and used for the layout of the CourseList component are: + * Other values returned and used for the layout of the CoursesPanel component are: * the current page number, the sorting method, and whether or not to enable filters and pagination. * - * @returns data for the CourseList component + * @returns data for the CoursesPanel component */ export const useCourseListData = () => { const filters = reduxHooks.useFilters(); diff --git a/src/containers/CourseList/hooks.test.js b/src/containers/CoursesPanel/hooks.test.js similarity index 100% rename from src/containers/CourseList/hooks.test.js rename to src/containers/CoursesPanel/hooks.test.js diff --git a/src/containers/CoursesPanel/index.jsx b/src/containers/CoursesPanel/index.jsx new file mode 100644 index 0000000..8fd1e56 --- /dev/null +++ b/src/containers/CoursesPanel/index.jsx @@ -0,0 +1,48 @@ +import React from 'react'; + +import { useIntl } from '@edx/frontend-platform/i18n'; + +import { reduxHooks } from 'hooks'; +import { + CourseFilterControls, +} from 'containers/CourseFilterControls'; +import NoCoursesView from './NoCoursesView'; + +import CourseList from './CourseList'; + +import { useCourseListData } from './hooks'; + +import messages from './messages'; + +import './index.scss'; + +/** + * Renders the list of CourseCards, as well as the controls (CourseFilterControls) for modifying the list. + * Also houses the NoCoursesView to display if the user hasn't enrolled in any courses. + * @returns List of courses as CourseCards or empty state +*/ +export const CoursesPanel = () => { + const { formatMessage } = useIntl(); + const hasCourses = reduxHooks.useHasCourses(); + const courseListData = useCourseListData(); + return ( +
+
+

{formatMessage(messages.myCourses)}

+
+ +
+
+ {hasCourses + ? ( + + ) : ( + + )} +
+ ); +}; + +CoursesPanel.propTypes = {}; + +export default CoursesPanel; diff --git a/src/containers/CourseList/index.scss b/src/containers/CoursesPanel/index.scss similarity index 100% rename from src/containers/CourseList/index.scss rename to src/containers/CoursesPanel/index.scss diff --git a/src/containers/CoursesPanel/index.test.jsx b/src/containers/CoursesPanel/index.test.jsx new file mode 100644 index 0000000..72aedb3 --- /dev/null +++ b/src/containers/CoursesPanel/index.test.jsx @@ -0,0 +1,55 @@ +import { shallow } from '@edx/react-unit-test-utils'; + +import { reduxHooks } from 'hooks'; +import { useCourseListData } from './hooks'; +import CoursesPanel from '.'; + +jest.mock('hooks', () => ({ + reduxHooks: { useHasCourses: jest.fn() }, +})); + +jest.mock('./hooks', () => ({ + useCourseListData: jest.fn(), +})); + +jest.mock('containers/CourseCard', () => 'CourseCard'); +jest.mock('containers/CourseFilterControls', () => ({ + ActiveCourseFilters: 'ActiveCourseFilters', + CourseFilterControls: 'CourseFilterControls', +})); +jest.mock('./CourseList', () => 'CourseList'); + +reduxHooks.useHasCourses.mockReturnValue(true); + +describe('CoursesPanel', () => { + const defaultCourseListData = { + filterOptions: {}, + numPages: 1, + setPageNumber: jest.fn().mockName('setPageNumber'), + showFilters: false, + visibleList: [], + }; + + const createWrapper = (courseListData) => { + useCourseListData.mockReturnValueOnce({ + ...defaultCourseListData, + ...courseListData, + }); + return shallow(); + }; + + describe('no courses', () => { + test('snapshot', () => { + reduxHooks.useHasCourses.mockReturnValue(false); + const wrapper = createWrapper(); + expect(wrapper.snapshot).toMatchSnapshot(); + }); + }); + describe('with courses', () => { + test('snapshot', () => { + reduxHooks.useHasCourses.mockReturnValue(true); + const wrapper = createWrapper(); + expect(wrapper.snapshot).toMatchSnapshot(); + }); + }); +}); diff --git a/src/containers/CourseList/messages.js b/src/containers/CoursesPanel/messages.js similarity index 100% rename from src/containers/CourseList/messages.js rename to src/containers/CoursesPanel/messages.js diff --git a/src/containers/Dashboard/__snapshots__/index.test.jsx.snap b/src/containers/Dashboard/__snapshots__/index.test.jsx.snap index 593d90f..67abc57 100644 --- a/src/containers/Dashboard/__snapshots__/index.test.jsx.snap +++ b/src/containers/Dashboard/__snapshots__/index.test.jsx.snap @@ -20,7 +20,7 @@ exports[`Dashboard snapshots courses loaded, show select session modal, no avail - +
@@ -65,7 +65,7 @@ exports[`Dashboard snapshots there are no courses, there ARE available dashboard - +
diff --git a/src/containers/Dashboard/index.jsx b/src/containers/Dashboard/index.jsx index c0c76cc..c6c065b 100644 --- a/src/containers/Dashboard/index.jsx +++ b/src/containers/Dashboard/index.jsx @@ -4,7 +4,7 @@ import { reduxHooks } from 'hooks'; import { RequestKeys } from 'data/constants/requests'; import EnterpriseDashboardModal from 'containers/EnterpriseDashboardModal'; import SelectSessionModal from 'containers/SelectSessionModal'; -import CourseList from 'containers/CourseList'; +import CoursesPanel from 'containers/CoursesPanel'; import LoadedSidebar from 'containers/WidgetContainers/LoadedSidebar'; import NoCoursesSidebar from 'containers/WidgetContainers/NoCoursesSidebar'; @@ -36,7 +36,7 @@ export const Dashboard = () => { ? () : ( - + )} diff --git a/src/containers/Dashboard/index.test.jsx b/src/containers/Dashboard/index.test.jsx index c802205..ffac108 100644 --- a/src/containers/Dashboard/index.test.jsx +++ b/src/containers/Dashboard/index.test.jsx @@ -4,7 +4,7 @@ import { reduxHooks } from 'hooks'; import EnterpriseDashboardModal from 'containers/EnterpriseDashboardModal'; import SelectSessionModal from 'containers/SelectSessionModal'; -import CourseList from 'containers/CourseList'; +import CoursesPanel from 'containers/CoursesPanel'; import LoadedWidgetSidebar from 'containers/WidgetContainers/LoadedSidebar'; import NoCoursesWidgetSidebar from 'containers/WidgetContainers/NoCoursesSidebar'; @@ -24,7 +24,7 @@ jest.mock('hooks', () => ({ })); jest.mock('containers/EnterpriseDashboardModal', () => 'EnterpriseDashboardModal'); -jest.mock('containers/CourseList', () => 'CourseList'); +jest.mock('containers/CoursesPanel', () => 'CoursesPanel'); jest.mock('containers/WidgetContainers/LoadedSidebar', () => 'LoadedWidgetSidebar'); jest.mock('containers/WidgetContainers/NoCoursesSidebar', () => 'NoCoursesWidgetSidebar'); jest.mock('./LoadingView', () => 'LoadingView'); @@ -116,7 +116,7 @@ describe('Dashboard', () => { showSelectSessionModal: true, }, content: ['LoadedView', ( - + )], showEnterpriseModal: false, showSelectSessionModal: true, @@ -132,7 +132,7 @@ describe('Dashboard', () => { showSelectSessionModal: false, }, content: ['Dashboard layout with no courses sidebar and content', ( - + )], showEnterpriseModal: true, showSelectSessionModal: false, diff --git a/src/data/redux/app/selectors/simpleSelectors.test.js b/src/data/redux/app/selectors/simpleSelectors.test.js index 353c528..02dad82 100644 --- a/src/data/redux/app/selectors/simpleSelectors.test.js +++ b/src/data/redux/app/selectors/simpleSelectors.test.js @@ -29,6 +29,7 @@ describe('app simple selectors', () => { keys.selectSessionModal, keys.pageNumber, keys.socialShareSettings, + keys.filters, ])('%s app simple selector forwards corresponding data from app store', (key) => { testState = { app: { [key]: testString, otherField: 'fake string' } }; const { preSelectors, cb } = simpleSelectors[key]; diff --git a/src/widgets/ProductRecommendations/index.jsx b/src/widgets/ProductRecommendations/index.jsx index f3eb316..2b61877 100644 --- a/src/widgets/ProductRecommendations/index.jsx +++ b/src/widgets/ProductRecommendations/index.jsx @@ -1,7 +1,7 @@ import React from 'react'; import './index.scss'; import { reduxHooks } from 'hooks'; -import NoCoursesView from 'containers/CourseList/NoCoursesView'; +import NoCoursesView from 'containers/CoursesPanel/NoCoursesView'; import LoadingView from './components/LoadingView'; import LoadedView from './components/LoadedView'; import hooks from './hooks'; diff --git a/src/widgets/ProductRecommendations/index.test.jsx b/src/widgets/ProductRecommendations/index.test.jsx index ab343b9..8ab3a4e 100644 --- a/src/widgets/ProductRecommendations/index.test.jsx +++ b/src/widgets/ProductRecommendations/index.test.jsx @@ -5,7 +5,7 @@ import hooks from './hooks'; import ProductRecommendations from './index'; import LoadingView from './components/LoadingView'; import LoadedView from './components/LoadedView'; -import NoCoursesView from '../../containers/CourseList/NoCoursesView'; +import NoCoursesView from '../../containers/CoursesPanel/NoCoursesView'; import { mockCrossProductResponse, mockAmplitudeResponse } from './testData'; jest.mock('./hooks', () => ({ @@ -21,7 +21,7 @@ jest.mock('hooks', () => ({ jest.mock('./components/LoadingView', () => 'LoadingView'); jest.mock('./components/LoadedView', () => 'LoadedView'); -jest.mock('containers/CourseList/NoCoursesView', () => 'NoCoursesView'); +jest.mock('containers/CoursesPanel/NoCoursesView', () => 'NoCoursesView'); describe('ProductRecommendations', () => { const defaultValues = {