test: Deprecate react-unit-test-utils 6/15 (#660)

This commit is contained in:
Diana Villalvazo
2025-06-23 13:22:21 -05:00
committed by GitHub
parent 2e59e24876
commit 8a0b9dca5d
10 changed files with 197 additions and 418 deletions

View File

@@ -1,111 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CourseCard component snapshot: collapsed 1`] = `
<div
className="mb-4.5 course-card"
data-testid="CourseCard"
id="test-card-id"
>
<Card
orientation="vertical"
>
<div
className="d-flex flex-column w-100"
>
<div>
<CourseCardImage
cardId="test-card-id"
orientation="horizontal"
/>
<Card.Body>
<Card.Header
actions={
<CourseCardMenu
cardId="test-card-id"
/>
}
title={
<CourseCardTitle
cardId="test-card-id"
/>
}
/>
<Card.Section
className="pt-0"
>
<CourseCardDetails
cardId="test-card-id"
/>
</Card.Section>
<Card.Footer
orientation="vertical"
>
<CourseCardActions
cardId="test-card-id"
/>
</Card.Footer>
</Card.Body>
</div>
<CourseCardBanners
cardId="test-card-id"
/>
</div>
</Card>
</div>
`;
exports[`CourseCard component snapshot: not collapsed 1`] = `
<div
className="mb-4.5 course-card"
data-testid="CourseCard"
id="test-card-id"
>
<Card
orientation="horizontal"
>
<div
className="d-flex flex-column w-100"
>
<div
className="d-flex"
>
<CourseCardImage
cardId="test-card-id"
orientation="horizontal"
/>
<Card.Body>
<Card.Header
actions={
<CourseCardMenu
cardId="test-card-id"
/>
}
title={
<CourseCardTitle
cardId="test-card-id"
/>
}
/>
<Card.Section
className="pt-0"
>
<CourseCardDetails
cardId="test-card-id"
/>
</Card.Section>
<Card.Footer
orientation="horizontal"
>
<CourseCardActions
cardId="test-card-id"
/>
</Card.Footer>
</Card.Body>
</div>
<CourseCardBanners
cardId="test-card-id"
/>
</div>
</Card>
</div>
`;

View File

@@ -1,61 +1,72 @@
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 { reduxHooks } from 'hooks';
import track from 'tracking';
import useActionDisabledState from './hooks';
import CourseCardImage from './CourseCardImage';
import { CourseCardImage } from './CourseCardImage';
import messages from '../messages';
const homeUrl = 'home-url';
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
jest.mock('tracking', () => ({
course: {
courseImageClicked: jest.fn().mockName('segment.courseImageClicked'),
},
}));
const homeUrl = 'https://example.com';
const bannerImgSrc = 'banner-img-src.jpg';
jest.mock('hooks', () => ({
reduxHooks: {
useCardCourseData: jest.fn(() => ({ bannerImgSrc: 'banner-img-src' })),
useCardCourseData: jest.fn(() => ({ bannerImgSrc })),
useCardCourseRunData: jest.fn(() => ({ homeUrl })),
useCardEnrollmentData: jest.fn(() => ({ isVerified: true })),
useCardEnrollmentData: jest.fn(),
useTrackCourseEvent: jest.fn((eventName, cardId, url) => ({
trackCourseEvent: { eventName, cardId, url },
})),
},
}));
jest.mock('./hooks', () => jest.fn(() => ({ disableCourseTitle: false })));
jest.mock('./hooks', () => jest.fn());
describe('CourseCardImage', () => {
const props = {
cardId: 'cardId',
orientation: 'orientation',
cardId: 'test-card-id',
orientation: 'horizontal',
};
beforeEach(() => {
jest.clearAllMocks();
it('renders course image with correct attributes', () => {
useActionDisabledState.mockReturnValue({ disableCourseTitle: true });
reduxHooks.useCardEnrollmentData.mockReturnValue({ isVerified: true });
render(<IntlProvider locale="en"><CourseCardImage {...props} /></IntlProvider>);
const image = screen.getByRole('img', { name: formatMessage(messages.bannerAlt) });
expect(image).toBeInTheDocument();
expect(image.src).toContain(bannerImgSrc);
expect(image.parentElement).toHaveClass('horizontal');
});
describe('snapshot', () => {
test('renders clickable link course Image', () => {
const wrapper = shallow(<CourseCardImage {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.type).toBe('a');
expect(wrapper.instance.props.onClick).toEqual(
reduxHooks.useTrackCourseEvent(
track.course.courseImageClicked,
props.cardId,
homeUrl,
),
);
});
test('renders disabled link', () => {
useActionDisabledState.mockReturnValueOnce({ disableCourseTitle: true });
const wrapper = shallow(<CourseCardImage {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
expect(wrapper.instance.type).toBe('div');
});
it('isVerified, should render badge', () => {
useActionDisabledState.mockReturnValue({ disableCourseTitle: false });
reduxHooks.useCardEnrollmentData.mockReturnValue({ isVerified: true });
render(<IntlProvider locale="en"><CourseCardImage {...props} /></IntlProvider>);
const badge = screen.getByText(formatMessage(messages.verifiedBanner));
expect(badge).toBeInTheDocument();
const badgeImg = screen.getByRole('img', { name: formatMessage(messages.verifiedBannerRibbonAlt) });
expect(badgeImg).toBeInTheDocument();
});
describe('behavior', () => {
it('renders link with correct href if disableCourseTitle is false', () => {
useActionDisabledState.mockReturnValue({ disableCourseTitle: false });
reduxHooks.useCardEnrollmentData.mockReturnValue({ isVerified: false });
render(<IntlProvider locale="en"><CourseCardImage {...props} /></IntlProvider>);
const link = screen.getByRole('link');
expect(link).toHaveAttribute('href', homeUrl);
});
describe('hooks', () => {
it('initializes', () => {
shallow(<CourseCardImage {...props} />);
useActionDisabledState.mockReturnValue({ disableCourseTitle: false });
reduxHooks.useCardEnrollmentData.mockReturnValue({ isVerified: true });
render(<IntlProvider locale="en"><CourseCardImage {...props} /></IntlProvider>);
expect(reduxHooks.useCardCourseData).toHaveBeenCalledWith(props.cardId);
expect(reduxHooks.useCardCourseRunData).toHaveBeenCalledWith(
props.cardId,

View File

@@ -1,12 +1,10 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { reduxHooks } from 'hooks';
import track from 'tracking';
import useActionDisabledState from './hooks';
import CourseCardTitle from './CourseCardTitle';
const homeUrl = 'home-url';
jest.mock('tracking', () => ({
course: {
courseTitleClicked: jest.fn().mockName('segment.courseTitleClicked'),
@@ -15,53 +13,65 @@ jest.mock('tracking', () => ({
jest.mock('hooks', () => ({
reduxHooks: {
useCardCourseData: jest.fn(() => ({ courseName: 'course-name' })),
useCardCourseRunData: jest.fn(() => ({ homeUrl })),
useTrackCourseEvent: jest.fn((eventName, cardId, url) => ({
trackCourseEvent: { eventName, cardId, url },
})),
useCardCourseData: jest.fn(),
useCardCourseRunData: jest.fn(),
useTrackCourseEvent: jest.fn(),
},
}));
jest.mock('./hooks', () => jest.fn(() => ({ disableCourseTitle: false })));
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
describe('CourseCardTitle', () => {
const props = {
cardId: 'cardId',
cardId: 'test-card-id',
};
const courseName = 'Test Course';
const homeUrl = 'http://test.com';
const handleTitleClick = jest.fn();
beforeEach(() => {
jest.clearAllMocks();
reduxHooks.useCardCourseData.mockReturnValue({ courseName });
reduxHooks.useCardCourseRunData.mockReturnValue({ homeUrl });
reduxHooks.useTrackCourseEvent.mockReturnValue(handleTitleClick);
});
describe('snapshot', () => {
test('renders clickable link course title', () => {
const wrapper = shallow(<CourseCardTitle {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
const title = wrapper.instance.findByTestId('CourseCardTitle');
expect(title[0].type).toBe('a');
expect(title[0].props.onClick).toEqual(
reduxHooks.useTrackCourseEvent(
track.course.courseTitleClicked,
props.cardId,
homeUrl,
),
);
});
test('renders disabled link', () => {
useActionDisabledState.mockReturnValueOnce({ disableCourseTitle: true });
const wrapper = shallow(<CourseCardTitle {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
const title = wrapper.instance.findByTestId('CourseCardTitle');
expect(title[0].type).toBe('span');
expect(title[0].props.onClick).toBeUndefined();
});
it('renders course name as link when not disabled', async () => {
useActionDisabledState.mockReturnValue({ disableCourseTitle: false });
render(<CourseCardTitle {...props} />);
const user = userEvent.setup();
const link = screen.getByRole('link', { name: courseName });
expect(link).toHaveAttribute('href', homeUrl);
await user.click(link);
expect(handleTitleClick).toHaveBeenCalled();
});
describe('behavior', () => {
it('initializes', () => {
shallow(<CourseCardTitle {...props} />);
expect(reduxHooks.useCardCourseData).toHaveBeenCalledWith(props.cardId);
expect(reduxHooks.useCardCourseRunData).toHaveBeenCalledWith(
props.cardId,
);
expect(useActionDisabledState).toHaveBeenCalledWith(props.cardId);
});
it('renders course name as span when disabled', () => {
useActionDisabledState.mockReturnValue({ disableCourseTitle: true });
render(<CourseCardTitle {...props} />);
const text = screen.getByText(courseName);
expect(text).toBeInTheDocument();
expect(text.tagName.toLowerCase()).toBe('span');
});
it('uses correct hooks with cardId', () => {
useActionDisabledState.mockReturnValue({ disableCourseTitle: false });
render(<CourseCardTitle {...props} />);
expect(reduxHooks.useCardCourseData).toHaveBeenCalledWith(props.cardId);
expect(reduxHooks.useCardCourseRunData).toHaveBeenCalledWith(props.cardId);
expect(reduxHooks.useTrackCourseEvent).toHaveBeenCalledWith(
track.course.courseTitleClicked,
props.cardId,
homeUrl,
);
});
});

View File

@@ -1,72 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CourseCardImage snapshot renders clickable link course Image 1`] = `
<a
className="pgn__card-wrapper-image-cap d-inline-block overflow-visible orientation"
href="home-url"
onClick={
{
"trackCourseEvent": {
"cardId": "cardId",
"eventName": [MockFunction segment.courseImageClicked],
"url": "home-url",
},
}
}
tabIndex="-1"
>
<Fragment>
<img
alt="Course thumbnail"
className="pgn__card-image-cap w-100 show"
src="banner-img-src"
/>
<span
className="course-card-verify-ribbon-container"
title="You're enrolled as a verified student"
>
<Badge
as="div"
className="w-100"
variant="success"
>
Verified
</Badge>
<img
alt="ID Verified Ribbon/Badge"
src="test-file-stub"
/>
</span>
</Fragment>
</a>
`;
exports[`CourseCardImage snapshot renders disabled link 1`] = `
<div
className="pgn__card-wrapper-image-cap d-inline-block overflow-visible orientation"
>
<Fragment>
<img
alt="Course thumbnail"
className="pgn__card-image-cap w-100 show"
src="banner-img-src"
/>
<span
className="course-card-verify-ribbon-container"
title="You're enrolled as a verified student"
>
<Badge
as="div"
className="w-100"
variant="success"
>
Verified
</Badge>
<img
alt="ID Verified Ribbon/Badge"
src="test-file-stub"
/>
</span>
</Fragment>
</div>
`;

View File

@@ -1,33 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CourseCardTitle snapshot renders clickable link course title 1`] = `
<h3>
<a
className="course-card-title"
data-testid="CourseCardTitle"
href="home-url"
onClick={
{
"trackCourseEvent": {
"cardId": "cardId",
"eventName": [MockFunction segment.courseTitleClicked],
"url": "home-url",
},
}
}
>
course-name
</a>
</h3>
`;
exports[`CourseCardTitle snapshot renders disabled link 1`] = `
<h3>
<span
className="course-card-title"
data-testid="CourseCardTitle"
>
course-name
</span>
</h3>
`;

View File

@@ -1,5 +1,5 @@
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 CourseCard from '.';
import hooks from './hooks';
@@ -8,22 +8,47 @@ jest.mock('./hooks', () => ({
useIsCollapsed: jest.fn(),
}));
jest.mock('./components/CourseCardBanners', () => 'CourseCardBanners');
jest.mock('./components/CourseCardImage', () => 'CourseCardImage');
jest.mock('./components/CourseCardMenu', () => 'CourseCardMenu');
jest.mock('./components/CourseCardActions', () => 'CourseCardActions');
jest.mock('./components/CourseCardDetails', () => 'CourseCardDetails');
jest.mock('./components/CourseCardTitle', () => 'CourseCardTitle');
const namesMockComponents = [
'CourseCardBanners',
'CourseCardImage',
'CourseCardMenu',
'CourseCardActions',
'CourseCardDetails',
'CourseCardTitle',
];
jest.mock('./components/CourseCardBanners', () => jest.fn(() => <div>CourseCardBanners</div>));
jest.mock('./components/CourseCardImage', () => jest.fn(() => <div>CourseCardImage</div>));
jest.mock('./components/CourseCardMenu', () => jest.fn(() => <div>CourseCardMenu</div>));
jest.mock('./components/CourseCardActions', () => jest.fn(() => <div>CourseCardActions</div>));
jest.mock('./components/CourseCardDetails', () => jest.fn(() => <div>CourseCardDetails</div>));
jest.mock('./components/CourseCardTitle', () => jest.fn(() => <div>CourseCardTitle</div>));
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
const cardId = 'test-card-id';
describe('CourseCard component', () => {
test('snapshot: collapsed', () => {
it('collapsed', () => {
hooks.useIsCollapsed.mockReturnValueOnce(true);
expect(shallow(<CourseCard cardId={cardId} />).snapshot).toMatchSnapshot();
render(<IntlProvider locale="en"><CourseCard cardId={cardId} /></IntlProvider>);
const cardImage = screen.getByText('CourseCardImage');
expect(cardImage.parentElement).not.toHaveClass('d-flex');
});
test('snapshot: not collapsed', () => {
it('not collapsed', () => {
hooks.useIsCollapsed.mockReturnValueOnce(false);
expect(shallow(<CourseCard cardId={cardId} />).snapshot).toMatchSnapshot();
render(<IntlProvider locale="en"><CourseCard cardId={cardId} /></IntlProvider>);
const cardImage = screen.getByText('CourseCardImage');
expect(cardImage.parentElement).toHaveClass('d-flex');
});
it('renders courseCard child components', () => {
hooks.useIsCollapsed.mockReturnValueOnce(false);
render(<IntlProvider locale="en"><CourseCard cardId={cardId} /></IntlProvider>);
namesMockComponents.map((courseCardName) => {
const courseCardComponent = screen.getByText(courseCardName);
return expect(courseCardComponent).toBeInTheDocument();
});
});
});

View File

@@ -1,14 +1,21 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import { formatMessage } from 'testUtils';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { FilterKeys } from 'data/constants/app';
import Checkbox from './Checkbox';
import messages from '../messages';
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
describe('Checkbox', () => {
describe('snapshot', () => {
describe('renders correctly', () => {
Object.keys(FilterKeys).forEach((filterKey) => {
it(`renders ${filterKey}`, () => {
const wrapper = shallow(<Checkbox filterKey={filterKey} />);
expect(wrapper.snapshot).toMatchSnapshot();
render(<IntlProvider locale="en"><Checkbox filterKey={filterKey} /></IntlProvider>);
expect(screen.getByText(formatMessage(messages[filterKey]))).toBeInTheDocument();
});
});
});

View File

@@ -1,29 +1,58 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen, fireEvent } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { formatMessage } from 'testUtils';
import { FilterKeys } from 'data/constants/app';
import FilterForm, { filterOrder } from './FilterForm';
import { FilterForm, filterOrder } from './FilterForm';
import messages from '../messages';
jest.mock('./Checkbox', () => 'Checkbox');
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
const mockHandleFilterChange = jest.fn();
const defaultProps = {
filters: [FilterKeys.inProgress],
handleFilterChange: mockHandleFilterChange,
};
const renderComponent = (props = defaultProps) => render(
<IntlProvider messages={{}}>
<FilterForm {...props} />
</IntlProvider>,
);
describe('FilterForm', () => {
const props = {
filters: ['test-filter'],
handleFilterChange: jest.fn().mockName('handleFilterChange'),
};
describe('snapshot', () => {
test('renders', () => {
const wrapper = shallow(<FilterForm {...props} />);
expect(wrapper.snapshot).toMatchSnapshot();
beforeEach(() => {
jest.clearAllMocks();
});
it('renders all filter checkboxes in correct order', () => {
renderComponent();
const checkboxes = screen.getAllByRole('checkbox');
expect(checkboxes).toHaveLength(filterOrder.length);
checkboxes.forEach((checkbox, index) => {
expect(checkbox).toHaveAttribute('value', filterOrder[index]);
});
});
test('filterOrder', () => {
expect(filterOrder).toEqual([
FilterKeys.inProgress,
FilterKeys.notStarted,
FilterKeys.done,
FilterKeys.notEnrolled,
FilterKeys.upgraded,
]);
it('checks boxes based on filters prop', () => {
const filters = [FilterKeys.inProgress, FilterKeys.done];
renderComponent({ ...defaultProps, filters });
filters.forEach(filter => {
expect(screen.getByRole('checkbox', { name: formatMessage(messages[filter]) })).toBeChecked();
});
});
it('calls handleFilterChange when checkbox is clicked', () => {
renderComponent();
const checkbox = screen.getByRole('checkbox', { name: formatMessage(messages.notStarted) });
fireEvent.click(checkbox);
expect(mockHandleFilterChange).toHaveBeenCalled();
});
it('displays course status heading', () => {
renderComponent();
expect(screen.getByText(/course status/i)).toBeInTheDocument();
});
});

View File

@@ -1,46 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Checkbox snapshot renders done 1`] = `
<Form.Checkbox
className="py-2"
value="done"
>
Done
</Form.Checkbox>
`;
exports[`Checkbox snapshot renders inProgress 1`] = `
<Form.Checkbox
className="py-2"
value="inProgress"
>
In-Progress
</Form.Checkbox>
`;
exports[`Checkbox snapshot renders notEnrolled 1`] = `
<Form.Checkbox
className="py-2"
value="notEnrolled"
>
Not Enrolled
</Form.Checkbox>
`;
exports[`Checkbox snapshot renders notStarted 1`] = `
<Form.Checkbox
className="py-2"
value="notStarted"
>
Not Started
</Form.Checkbox>
`;
exports[`Checkbox snapshot renders upgraded 1`] = `
<Form.Checkbox
className="py-2"
value="upgraded"
>
Upgraded
</Form.Checkbox>
`;

View File

@@ -1,41 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FilterForm snapshot renders 1`] = `
<Form.Group>
<div
className="filter-form-heading mb-1"
>
Course Status
</div>
<Form.CheckboxSet
name="course-status-filters"
onChange={[MockFunction handleFilterChange]}
value={
[
"test-filter",
]
}
>
<Checkbox
filterKey="inProgress"
key="inProgress"
/>
<Checkbox
filterKey="notStarted"
key="notStarted"
/>
<Checkbox
filterKey="done"
key="done"
/>
<Checkbox
filterKey="notEnrolled"
key="notEnrolled"
/>
<Checkbox
filterKey="upgraded"
key="upgraded"
/>
</Form.CheckboxSet>
</Form.Group>
`;