test: Deprecate react-unit-test-utils 7/15 (#662)

This commit is contained in:
Diana Villalvazo
2025-06-24 08:44:25 -05:00
committed by GitHub
parent 8a0b9dca5d
commit ab0f139d75
10 changed files with 166 additions and 409 deletions

View File

@@ -1,17 +1,32 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { formatMessage } from 'testUtils';
import { FilterKeys } from 'data/constants/app';
import ActiveCourseFilters from './ActiveCourseFilters';
import messages from './messages';
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
const filters = Object.values(FilterKeys);
describe('ActiveCourseFilters', () => {
const props = {
filters: Object.values(FilterKeys),
filters,
handleRemoveFilter: jest.fn().mockName('handleRemoveFilter'),
};
describe('snapshot', () => {
test('renders', () => {
const wrapper = shallow(<ActiveCourseFilters {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
it('renders chips correctly', () => {
render(<IntlProvider locale="en"><ActiveCourseFilters {...props} /></IntlProvider>);
filters.map((key) => {
const chip = screen.getByText(formatMessage(messages[key]));
return expect(chip).toBeInTheDocument();
});
});
it('renders button correctly', () => {
render(<IntlProvider locale="en"><ActiveCourseFilters {...props} /></IntlProvider>);
const button = screen.getByRole('button', { name: formatMessage(messages.clearAll) });
expect(button).toBeInTheDocument();
});
});

View File

@@ -1,9 +1,11 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import { formatMessage } from 'testUtils';
import { breakpoints, useWindowSize } from '@openedx/paragon';
import { reduxHooks } from 'hooks';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { FilterKeys, SortKeys } from 'data/constants/app';
import messages from './messages';
import CourseFilterControls from './CourseFilterControls';
import useCourseFilterControlsData from './hooks';
@@ -11,50 +13,67 @@ jest.mock('hooks', () => ({
reduxHooks: { useHasCourses: jest.fn() },
}));
jest.mock('./hooks', () => jest.fn().mockName('useCourseFilterControlsData'));
jest.mock('./hooks', () => jest.fn());
jest.mock('./components/FilterForm', () => 'FilterForm');
jest.mock('./components/SortForm', () => 'SortForm');
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
reduxHooks.useHasCourses.mockReturnValue(true);
jest.mock('@openedx/paragon', () => ({
...jest.requireActual('@openedx/paragon'),
useWindowSize: jest.fn(),
}));
const filters = Object.values(FilterKeys);
const mockControlsData = {
isOpen: false,
open: jest.fn().mockName('open'),
close: jest.fn().mockName('close'),
target: 'target-test',
setTarget: jest.fn(),
handleFilterChange: jest.fn().mockName('handleFilterChange'),
handleSortChange: jest.fn().mockName('handleSortChange'),
};
describe('CourseFilterControls', () => {
const props = {
sortBy: 'test-sort-by',
sortBy: SortKeys.enrolled,
setSortBy: jest.fn().mockName('setSortBy'),
filters: ['test-filter'],
filters,
};
useCourseFilterControlsData.mockReturnValue({
isOpen: false,
open: jest.fn().mockName('open'),
close: jest.fn().mockName('close'),
target: 'test-target',
setTarget: jest.fn().mockName('setTarget'),
handleFilterChange: jest.fn().mockName('handleFilterChange'),
handleSortChange: jest.fn().mockName('handleSortChange'),
});
describe('no courses', () => {
test('snapshot', () => {
reduxHooks.useHasCourses.mockReturnValueOnce(false);
useWindowSize.mockReturnValueOnce({ width: breakpoints.small.minWidth });
const wrapper = shallow(<CourseFilterControls {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
});
});
describe('mobile', () => {
test('snapshot', () => {
describe('mobile and open', () => {
it('should render sheet', () => {
reduxHooks.useHasCourses.mockReturnValue(true);
useCourseFilterControlsData.mockReturnValue({ ...mockControlsData, isOpen: true });
useWindowSize.mockReturnValueOnce({ width: breakpoints.small.minWidth - 1 });
const wrapper = shallow(<CourseFilterControls {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
render(<IntlProvider locale="en"><CourseFilterControls {...props} /></IntlProvider>);
const sheet = screen.getByRole('presentation', { hidden: true });
expect(sheet).toBeInTheDocument();
expect(sheet.parentElement).toHaveClass('sheet-container');
});
});
describe('is not mobile', () => {
test('snapshot', () => {
it('should have button disabled', () => {
reduxHooks.useHasCourses.mockReturnValue(true);
useCourseFilterControlsData.mockReturnValue({ ...mockControlsData, isOpen: true });
useWindowSize.mockReturnValueOnce({ width: breakpoints.small.minWidth });
const wrapper = shallow(<CourseFilterControls {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
render(<IntlProvider locale="en"><CourseFilterControls {...props} /></IntlProvider>);
const filterForm = screen.getByText(messages.courseStatus.defaultMessage);
const modal = filterForm.closest('div.pgn__modal-popup__tooltip');
expect(modal).toBeInTheDocument();
});
});
describe('no courses', () => {
it('should have button disabled', () => {
reduxHooks.useHasCourses.mockReturnValue(false);
useCourseFilterControlsData.mockReturnValue(mockControlsData);
useWindowSize.mockReturnValue({ width: breakpoints.small.minWidth });
render(<IntlProvider locale="en"><CourseFilterControls {...props} /></IntlProvider>);
const button = screen.getByRole('button', { name: formatMessage(messages.refine) });
expect(button).toBeInTheDocument();
expect(button).toBeDisabled();
});
});
});

View File

@@ -1,39 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ActiveCourseFilters snapshot renders 1`] = `
<div
id="course-list-active-filters"
>
<Chip
key="inProgress"
>
In-Progress
</Chip>
<Chip
key="notStarted"
>
Not Started
</Chip>
<Chip
key="done"
>
Done
</Chip>
<Chip
key="notEnrolled"
>
Not Enrolled
</Chip>
<Chip
key="upgraded"
>
Upgraded
</Chip>
<Button
onClick={[Function]}
variant="link"
>
Clear all
</Button>
</div>
`;

View File

@@ -1,169 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CourseFilterControls is not mobile snapshot 1`] = `
<div
id="course-filter-controls"
>
<Button
disabled={false}
iconBefore={[MockFunction icons.Tune]}
onClick={[MockFunction open]}
variant="outline-primary"
>
Refine
</Button>
<Form>
<ModalPopup
isOpen={false}
onClose={[MockFunction close]}
placement="bottom-end"
positionRef="test-target"
>
<div
className="bg-white p-3 rounded shadow d-flex flex-row"
id="course-filter-controls-card"
>
<div
className="filter-form-col"
>
<FilterForm
filters={
[
"test-filter",
]
}
handleFilterChange={[MockFunction handleFilterChange]}
/>
</div>
<hr
className="h-100 bg-primary-200 mx-3 my-0"
/>
<div
className="filter-form-col text-left m-1"
>
<SortForm
handleSortChange={[MockFunction handleSortChange]}
sortBy="test-sort-by"
/>
</div>
</div>
</ModalPopup>
</Form>
</div>
`;
exports[`CourseFilterControls mobile snapshot 1`] = `
<div
id="course-filter-controls"
>
<Button
disabled={false}
iconBefore={[MockFunction icons.Tune]}
onClick={[MockFunction open]}
variant="outline-primary"
>
Refine
</Button>
<Form>
<Sheet
className="w-75"
onClose={[MockFunction close]}
position="left"
show={false}
>
<div
className="p-1 mr-3"
>
<b>
Refine
</b>
</div>
<hr />
<div
className="filter-form-row"
>
<FilterForm
filters={
[
"test-filter",
]
}
handleFilterChange={[MockFunction handleFilterChange]}
/>
</div>
<div
className="filter-form-row text-left m-1"
>
<SortForm
handleSortChange={[MockFunction handleSortChange]}
sortBy="test-sort-by"
/>
</div>
<div
className="pgn__modal-close-container"
>
<ModalCloseButton
onClick={[MockFunction close]}
variant="tertiary"
>
<Icon
src={[MockFunction icons.Close]}
/>
</ModalCloseButton>
</div>
</Sheet>
</Form>
</div>
`;
exports[`CourseFilterControls no courses snapshot 1`] = `
<div
id="course-filter-controls"
>
<Button
disabled={true}
iconBefore={[MockFunction icons.Tune]}
onClick={[MockFunction open]}
variant="outline-primary"
>
Refine
</Button>
<Form>
<ModalPopup
isOpen={false}
onClose={[MockFunction close]}
placement="bottom-end"
positionRef="test-target"
>
<div
className="bg-white p-3 rounded shadow d-flex flex-row"
id="course-filter-controls-card"
>
<div
className="filter-form-col"
>
<FilterForm
filters={
[
"test-filter",
]
}
handleFilterChange={[MockFunction handleFilterChange]}
/>
</div>
<hr
className="h-100 bg-primary-200 mx-3 my-0"
/>
<div
className="filter-form-col text-left m-1"
>
<SortForm
handleSortChange={[MockFunction handleSortChange]}
sortBy="test-sort-by"
/>
</div>
</div>
</ModalPopup>
</Form>
</div>
`;

View File

@@ -1,19 +1,33 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { formatMessage } from 'testUtils';
import { SortKeys } from 'data/constants/app';
import SortForm from './SortForm';
import messages from '../messages';
jest.mock('./Checkbox', () => 'Checkbox');
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
describe('SortForm', () => {
const props = {
handleSortChange: jest.fn().mockName('handleSortChange'),
sortBy: SortKeys.enrolled,
};
describe('snapshot', () => {
test('renders', () => {
const wrapper = shallow(<SortForm {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
});
it('renders heading', () => {
render(<IntlProvider locale="en"><SortForm {...props} /></IntlProvider>);
const heading = screen.getByText(formatMessage(messages.sort));
expect(heading).toBeInTheDocument();
});
it('renders radio enrolled', () => {
render(<IntlProvider locale="en"><SortForm {...props} /></IntlProvider>);
const enrolled = screen.getByRole('radio', { name: formatMessage(messages.sortLastEnrolled) });
expect(enrolled).toBeInTheDocument();
});
it('renders radio title', () => {
render(<IntlProvider locale="en"><SortForm {...props} /></IntlProvider>);
const title = screen.getByRole('radio', { name: formatMessage(messages.sortTitle) });
expect(title).toBeInTheDocument();
});
});

View File

@@ -1,29 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SortForm snapshot renders 1`] = `
<Fragment>
<div
className="filter-form-heading mb-1"
>
Sort
</div>
<Form.RadioSet
name="sort"
onChange={[MockFunction handleSortChange]}
value="enrolled"
>
<Form.Radio
className="py-2"
value="enrolled"
>
Last enrolled
</Form.Radio>
<Form.Radio
className="py-2"
value="title"
>
Title (A-Z)
</Form.Radio>
</Form.RadioSet>
</Fragment>
`;

View File

@@ -1,70 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CourseList collapsed with multiple courses and pages snapshot 1`] = `
<Fragment>
<div
id="course-list-active-filters-container"
>
<ActiveCourseFilters />
</div>
<div
className="d-flex flex-column flex-grow-1"
>
<CourseCard
cardId="foo"
key="foo"
/>
<CourseCard
cardId="bar"
key="bar"
/>
<CourseCard
cardId="baz"
key="baz"
/>
<Pagination
className="mx-auto mb-2"
pageCount={3}
paginationLabel="Course List"
variant="reduced"
/>
</div>
</Fragment>
`;
exports[`CourseList no courses or filters snapshot 1`] = `
<Fragment>
<div
className="d-flex flex-column flex-grow-1"
/>
</Fragment>
`;
exports[`CourseList with filters snapshot 1`] = `undefined`;
exports[`CourseList with multiple courses and pages snapshot 1`] = `
<Fragment>
<div
className="d-flex flex-column flex-grow-1"
>
<CourseCard
cardId="foo"
key="foo"
/>
<CourseCard
cardId="bar"
key="bar"
/>
<CourseCard
cardId="baz"
key="baz"
/>
<Pagination
className="mx-auto mb-2"
pageCount={3}
paginationLabel="Course List"
variant="secondary"
/>
</div>
</Fragment>
`;

View File

@@ -1,4 +1,4 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import { useIsCollapsed } from './hooks';
import CourseList from '.';
@@ -7,11 +7,15 @@ jest.mock('./hooks', () => ({
useIsCollapsed: jest.fn(),
}));
jest.mock('containers/CourseCard', () => 'CourseCard');
jest.mock('containers/CourseCard', () => jest.fn(() => <div>CourseCard</div>));
jest.mock('containers/CourseFilterControls', () => ({
ActiveCourseFilters: 'ActiveCourseFilters',
ActiveCourseFilters: jest.fn(() => <div>ActiveCourseFilters</div>),
}));
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
describe('CourseList', () => {
const defaultCourseListData = {
filterOptions: {},
@@ -22,43 +26,60 @@ describe('CourseList', () => {
};
useIsCollapsed.mockReturnValue(false);
const createWrapper = (courseListData = defaultCourseListData) => (
shallow(<CourseList courseListData={courseListData} />)
const renderList = (courseListData = defaultCourseListData) => (
render(<CourseList courseListData={courseListData} />)
);
describe('no courses or filters', () => {
test('snapshot', () => {
const wrapper = createWrapper();
expect(wrapper.snapshot).toMatchSnapshot();
it('should not render related components', () => {
renderList();
const filterControls = screen.queryByText('ActiveCourseFilters');
const courseCard = screen.queryByText('CourseCard');
const prevButton = screen.queryByRole('button', { name: 'Previous' });
expect(filterControls).toBeNull();
expect(courseCard).toBeNull();
expect(prevButton).toBeNull();
});
});
describe('with filters', () => {
test('snapshot', () => {
const wrapper = createWrapper({
filterOptions: { abitary: 'filter' },
it('should render filter component', () => {
renderList({
...defaultCourseListData,
showFilters: true,
});
expect(wrapper.snapshot).toMatchSnapshot();
const filterControls = screen.getByText('ActiveCourseFilters');
expect(filterControls).toBeInTheDocument();
});
});
describe('with multiple courses and pages', () => {
test('snapshot', () => {
const wrapper = createWrapper({
visibleList: [{ cardId: 'foo' }, { cardId: 'bar' }, { cardId: 'baz' }],
numPages: 3,
it('render Course Cards and pagination', () => {
const visibleList = [{ cardId: 'foo' }, { cardId: 'bar' }, { cardId: 'baz' }];
const numPages = 3;
renderList({
...defaultCourseListData,
visibleList,
numPages,
});
expect(wrapper.snapshot).toMatchSnapshot();
const courseCards = screen.getAllByText('CourseCard');
expect(courseCards.length).toEqual(visibleList.length);
const pageButtons = screen.getAllByRole('button', { name: /^Page/i });
expect(pageButtons.length).toBe(numPages);
});
});
describe('collapsed with multiple courses and pages', () => {
test('snapshot', () => {
it('should render correct components', () => {
const visibleList = [{ cardId: 'foo' }, { cardId: 'bar' }, { cardId: 'baz' }];
useIsCollapsed.mockReturnValueOnce(true);
const wrapper = createWrapper({
visibleList: [{ cardId: 'foo' }, { cardId: 'bar' }, { cardId: 'baz' }],
renderList({
...defaultCourseListData,
visibleList,
numPages: 3,
showFilters: true,
});
expect(wrapper.snapshot).toMatchSnapshot();
const courseCards = screen.getAllByText('CourseCard');
expect(courseCards.length).toEqual(visibleList.length);
const reducedPagination = screen.getByRole('button', { name: '1 of 3' });
expect(reducedPagination).toBeInTheDocument();
});
});
});

View File

@@ -1,29 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NoCoursesView snapshot 1`] = `
<div
className="d-flex align-items-center justify-content-center mb-4.5"
id="no-courses-content-view"
>
<Image
alt="No Courses view banner"
src="icon/mock/path"
/>
<h3
className="h1"
>
Looking for a new challenge?
</h3>
<p>
Explore our courses to add them to your dashboard.
</p>
<Button
as="a"
href="http://localhost:18000/course-search-url"
iconBefore={[MockFunction icons.Search]}
variant="brand"
>
Explore courses
</Button>
</div>
`;

View File

@@ -1,18 +1,42 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { formatMessage } from 'testUtils';
import { baseAppUrl } from 'data/services/lms/urls';
import EmptyCourse from '.';
import messages from './messages';
const courseSearchUrl = '/course-search-url';
jest.mock('hooks', () => ({
reduxHooks: {
usePlatformSettingsData: jest.fn(() => ({
courseSearchUrl: '/course-search-url',
courseSearchUrl,
})),
},
}));
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
describe('NoCoursesView', () => {
test('snapshot', () => {
expect(shallow(<EmptyCourse />).snapshot).toMatchSnapshot();
it('should display image, heading and button', () => {
render(<IntlProvider locale="en"><EmptyCourse /></IntlProvider>);
const image = screen.getByRole('img', { alt: formatMessage(messages.bannerAlt) });
expect(image).toBeInTheDocument();
});
it('should display heading and prompt', () => {
render(<IntlProvider locale="en"><EmptyCourse /></IntlProvider>);
const heading = screen.getByText(formatMessage(messages.lookingForChallengePrompt));
const prompt = screen.getByText(formatMessage(messages.exploreCoursesPrompt));
expect(heading).toBeInTheDocument();
expect(prompt).toBeInTheDocument();
});
it('should display button', () => {
render(<IntlProvider locale="en"><EmptyCourse /></IntlProvider>);
const button = screen.getByRole('link', { name: formatMessage(messages.exploreCoursesButton) });
expect(button).toBeInTheDocument();
expect(button.href).toBe(baseAppUrl(courseSearchUrl));
});
});