test: Deprecate react-unit-test-utils 3/15 (#655)

This commit is contained in:
Diana Villalvazo
2025-06-17 18:00:44 -06:00
committed by GitHub
parent b0daefa2bf
commit 5c4dfd5de3
6 changed files with 185 additions and 159 deletions

View File

@@ -1,8 +1,8 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { reduxHooks } from 'hooks';
import { formatMessage } from 'testUtils';
import track from 'tracking';
import messages from './messages';
@@ -14,15 +14,16 @@ jest.mock('hooks', () => ({
useCardCourseRunData: jest.fn(),
},
}));
jest.mock('./components/CreditContent', () => 'CreditContent');
jest.mock('tracking', () => ({
credit: {
purchase: (...args) => ({ trackCredit: args }),
purchase: jest.fn(),
},
}));
let el;
let component;
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
const cardId = 'test-card-id';
const courseId = 'test-course-id';
@@ -32,50 +33,45 @@ const credit = {
reduxHooks.useCardCreditData.mockReturnValue(credit);
reduxHooks.useCardCourseRunData.mockReturnValue({ courseId });
const render = () => {
el = shallow(<EligibleContent cardId={cardId} />);
};
const loadComponent = () => {
component = el.instance.findByType('CreditContent');
};
const renderEligibleContent = () => render(<IntlProvider locale="en" messages={{}}><EligibleContent cardId={cardId} /></IntlProvider>);
describe('EligibleContent component', () => {
beforeEach(() => {
render();
});
describe('behavior', () => {
describe('hooks', () => {
it('initializes credit data with cardId', () => {
renderEligibleContent();
expect(reduxHooks.useCardCreditData).toHaveBeenCalledWith(cardId);
});
it('initializes course run data with cardId', () => {
renderEligibleContent();
expect(reduxHooks.useCardCourseRunData).toHaveBeenCalledWith(cardId);
});
});
describe('render', () => {
describe('behavior', () => {
describe('rendered CreditContent component', () => {
beforeEach(() => {
loadComponent();
it('action message is formatted getCredit message', () => {
renderEligibleContent();
const button = screen.getByRole('button', { name: messages.getCredit.defaultMessage });
expect(button).toBeInTheDocument();
});
test('action.onClick sends credit purchase track event', () => {
expect(component[0].props.action.onClick).toEqual(
track.credit.purchase(courseId),
);
it('onClick sends credit purchase track event', async () => {
const user = userEvent.setup();
renderEligibleContent();
const button = screen.getByRole('button', { name: messages.getCredit.defaultMessage });
await user.click(button);
expect(track.credit.purchase).toHaveBeenCalledWith(courseId);
});
test('action.message is formatted getCredit message', () => {
expect(component[0].props.action.message).toEqual(formatMessage(messages.getCredit));
it('message is formatted eligible message if provider', () => {
renderEligibleContent();
const eligibleMessage = screen.getByTestId('credit-msg');
expect(eligibleMessage).toBeInTheDocument();
expect(eligibleMessage).toHaveTextContent(credit.providerName);
});
test('message is formatted eligible message if no provider', () => {
reduxHooks.useCardCreditData.mockReturnValueOnce({});
render();
loadComponent();
expect(component[0].props.message).toEqual(formatMessage(
messages.eligible,
{ getCredit: (<b>{formatMessage(messages.getCredit)}</b>) },
));
});
test('message is formatted eligible message if provider', () => {
expect(component[0].props.message).toEqual(
formatMessage(messages.eligibleFromProvider, { providerName: credit.providerName }),
);
it('message is formatted eligible message if no provider', () => {
reduxHooks.useCardCreditData.mockReturnValue({});
renderEligibleContent();
const eligibleMessage = screen.getByTestId('credit-msg');
expect(eligibleMessage).toBeInTheDocument();
expect(eligibleMessage).toHaveTextContent(messages.getCredit.defaultMessage);
});
});
});

View File

@@ -1,73 +1,107 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from 'testUtils';
import { render, screen } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import userEvent from '@testing-library/user-event';
import { reduxHooks } from 'hooks';
import messages from './messages';
import hooks from './hooks';
import ProviderLink from './components/ProviderLink';
import MustRequestContent from './MustRequestContent';
jest.mock('./hooks', () => ({
useCreditRequestData: jest.fn(),
}));
jest.mock('hooks', () => ({
reduxHooks: { useMasqueradeData: jest.fn() },
}));
jest.mock('./components/CreditContent', () => 'CreditContent');
jest.mock('./components/ProviderLink', () => 'ProviderLink');
let el;
let component;
jest.mock('hooks', () => ({
reduxHooks: {
useMasqueradeData: jest.fn(),
useCardCreditData: jest.fn(),
},
}));
jest.unmock('@openedx/paragon');
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('react');
const cardId = 'test-card-id';
const requestData = { test: 'requestData' };
const createCreditRequest = jest.fn().mockName('createCreditRequest');
hooks.useCreditRequestData.mockReturnValue({
requestData,
createCreditRequest,
});
reduxHooks.useMasqueradeData.mockReturnValue({ isMasquerading: false });
const render = () => {
el = shallow(<MustRequestContent cardId={cardId} />);
const requestData = {
url: 'test-request-data-url',
parameters: {
key1: 'val1',
key2: 'val2',
key3: 'val3',
},
};
const providerName = 'test-credit-provider-name';
const providerStatusUrl = 'test-credit-provider-status-url';
const createCreditRequest = jest.fn().mockName('createCreditRequest');
const renderMustRequestContent = () => render(
<IntlProvider locale="en" messages={messages}>
<MustRequestContent cardId={cardId} />
</IntlProvider>,
);
describe('MustRequestContent component', () => {
beforeEach(() => {
render();
jest.clearAllMocks();
hooks.useCreditRequestData.mockReturnValue({
requestData,
createCreditRequest,
});
reduxHooks.useMasqueradeData.mockReturnValue({ isMasquerading: false });
reduxHooks.useCardCreditData.mockReturnValue({
providerName,
providerStatusUrl,
});
});
describe('behavior', () => {
describe('hooks', () => {
it('initializes credit request data with cardId', () => {
renderMustRequestContent();
expect(hooks.useCreditRequestData).toHaveBeenCalledWith(cardId);
});
});
describe('render', () => {
describe('rendered CreditContent component', () => {
describe('behavior', () => {
describe('rendered content', () => {
beforeEach(() => {
component = el.instance.findByType('CreditContent');
renderMustRequestContent();
});
test('action.onClick calls createCreditRequest from useCreditRequestData hook', () => {
expect(component[0].props.action.onClick).toEqual(createCreditRequest);
it('calls createCreditRequest when request credit button is clicked', async () => {
const user = userEvent.setup();
const button = screen.getByRole('button', { name: /request credit/i });
await user.click(button);
expect(createCreditRequest).toHaveBeenCalled();
});
test('action.message is formatted requestCredit message', () => {
expect(component[0].props.action.message).toEqual(
formatMessage(messages.requestCredit),
);
it('shows request credit button that is enabled', () => {
const button = screen.getByRole('button', { name: /request credit/i });
expect(button).toBeEnabled();
});
test('action.disabled is false', () => {
expect(component[0].props.action.disabled).toEqual(false);
it('displays must request message with provider link', () => {
expect(screen.getByTestId('credit-msg')).toHaveTextContent(/request credit/i);
});
test('message is formatted mustRequest message', () => {
expect(component[0].props.message).toEqual(
formatMessage(messages.mustRequest, {
linkToProviderSite: <ProviderLink cardId={cardId} />,
requestCredit: <b>{formatMessage(messages.requestCredit)}</b>,
}),
);
it('renders credit request form with correct data', () => {
const { container } = renderMustRequestContent();
const form = container.querySelector('form');
expect(form).toBeInTheDocument();
expect(form).toHaveAttribute('action', requestData.url);
});
test('requestData drawn from useCreditRequestData hook', () => {
expect(component[0].props.requestData).toEqual(requestData);
});
describe('when masquerading', () => {
beforeEach(() => {
reduxHooks.useMasqueradeData.mockReturnValue({ isMasquerading: true });
renderMustRequestContent();
});
it('disables the request credit button', () => {
const button = screen.getByRole('button', { name: /request credit/i });
expect(button).toHaveClass('disabled');
expect(button).toHaveAttribute('aria-disabled', 'true');
});
});
});

View File

@@ -1,7 +1,6 @@
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 { reduxHooks } from 'hooks';
import messages from './messages';
@@ -10,11 +9,10 @@ import PendingContent from './PendingContent';
jest.mock('hooks', () => ({
reduxHooks: { useCardCreditData: jest.fn(), useMasqueradeData: jest.fn() },
}));
jest.mock('./components/CreditContent', () => 'CreditContent');
jest.mock('./components/ProviderLink', () => 'ProviderLink');
let el;
let component;
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.unmock('react');
const cardId = 'test-card-id';
const providerName = 'test-credit-provider-name';
@@ -25,38 +23,48 @@ reduxHooks.useCardCreditData.mockReturnValue({
});
reduxHooks.useMasqueradeData.mockReturnValue({ isMasquerading: false });
const render = () => {
el = shallow(<PendingContent cardId={cardId} />);
};
const renderPendingContent = () => render(
<IntlProvider messages={{}} locale="en">
<PendingContent cardId={cardId} />
</IntlProvider>,
);
describe('PendingContent component', () => {
beforeEach(() => {
render();
});
describe('behavior', () => {
describe('hooks', () => {
it('initializes card credit data with cardId', () => {
renderPendingContent();
expect(reduxHooks.useCardCreditData).toHaveBeenCalledWith(cardId);
});
});
describe('render', () => {
describe('behavior', () => {
describe('rendered CreditContent component', () => {
beforeEach(() => {
component = el.instance.findByType('CreditContent');
it('action message is formatted requestCredit message', () => {
renderPendingContent();
const button = screen.getByRole('link', { name: messages.viewDetails.defaultMessage });
expect(button).toBeInTheDocument();
});
test('action.href will go to provider status site', () => {
expect(component[0].props.action.href).toEqual(providerStatusUrl);
it('action href will go to provider status site', () => {
renderPendingContent();
const button = screen.getByRole('link', { name: messages.viewDetails.defaultMessage });
expect(button).toHaveAttribute('href', providerStatusUrl);
});
test('action.message is formatted requestCredit message', () => {
expect(component[0].props.action.message).toEqual(
formatMessage(messages.viewDetails),
);
it('action.disabled is false', () => {
renderPendingContent();
const button = screen.getByRole('link', { name: messages.viewDetails.defaultMessage });
expect(button).not.toHaveClass('disabled');
});
test('action.disabled is false', () => {
expect(component[0].props.action.disabled).toEqual(false);
it('message is formatted pending message with provider name', () => {
renderPendingContent();
const component = screen.getByTestId('credit-msg');
expect(component).toBeInTheDocument();
expect(component).toHaveTextContent(`${providerName} has received`);
});
test('message is formatted pending message', () => {
expect(component[0].props.message).toEqual(
formatMessage(messages.received, { providerName }),
);
describe('when masqueradeData is true', () => {
it('disables the view details button', () => {
reduxHooks.useMasqueradeData.mockReturnValue({ isMasquerading: true });
renderPendingContent();
const button = screen.getByRole('link', { name: messages.viewDetails.defaultMessage });
expect(button).toHaveClass('disabled');
});
});
});
});

View File

@@ -1,10 +1,7 @@
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 { reduxHooks } from 'hooks';
import messages from './messages';
import ProviderLink from './components/ProviderLink';
import RejectedContent from './RejectedContent';
jest.mock('hooks', () => ({
@@ -12,8 +9,10 @@ jest.mock('hooks', () => ({
useCardCreditData: jest.fn(),
},
}));
jest.mock('./components/CreditContent', () => 'CreditContent');
jest.mock('./components/ProviderLink', () => 'ProviderLink');
jest.unmock('@openedx/paragon');
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('react');
const cardId = 'test-card-id';
const credit = {
@@ -22,32 +21,27 @@ const credit = {
};
reduxHooks.useCardCreditData.mockReturnValue(credit);
let el;
let component;
const render = () => { el = shallow(<RejectedContent cardId={cardId} />); };
const loadComponent = () => { component = el.instance.findByType('CreditContent'); };
const renderRejectedContent = () => render(<IntlProvider><RejectedContent cardId={cardId} /></IntlProvider>);
describe('RejectedContent component', () => {
beforeEach(render);
describe('behavior', () => {
describe('hooks', () => {
it('initializes credit data with cardId', () => {
renderRejectedContent();
expect(reduxHooks.useCardCreditData).toHaveBeenCalledWith(cardId);
});
});
describe('render', () => {
describe('rendered CreditContent component', () => {
beforeAll(loadComponent);
test('no action is passed', () => {
expect(component[0].props.action).toEqual(undefined);
it('no action is passed', () => {
renderRejectedContent();
const action = screen.queryByTestId('action-row-btn');
expect(action).not.toBeInTheDocument();
});
test('message is formatted rejected message', () => {
expect(component[0].props.message).toEqual(formatMessage(
messages.rejected,
{
linkToProviderSite: <ProviderLink cardId={cardId} />,
providerName: credit.providerName,
},
));
it('message is formatted rejected message', () => {
renderRejectedContent();
const message = screen.getByTestId('credit-msg');
expect(message).toBeInTheDocument();
expect(message).toHaveTextContent(`${credit.providerName} did not approve your request for course credit.`);
});
});
});

View File

@@ -1,14 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`WidgetSidebar snapshots 1`] = `
<PluginSlot
id="org.openedx.frontend.learner_dashboard.widget_sidebar.v1"
idAliases={
[
"widget_sidebar_slot",
]
}
>
<LookingForChallengeWidget />
</PluginSlot>
`;

View File

@@ -1,18 +1,26 @@
import { shallow } from '@edx/react-unit-test-utils';
import { render, screen } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { reduxHooks } from 'hooks';
import WidgetSidebarSlot from '.';
jest.mock('widgets/LookingForChallengeWidget', () => 'LookingForChallengeWidget');
jest.unmock('react');
jest.unmock('@edx/frontend-platform/i18n');
jest.unmock('@openedx/paragon');
jest.mock('@openedx/frontend-plugin-framework', () => ({
PluginSlot: 'PluginSlot',
jest.mock('hooks', () => ({
reduxHooks: {
usePlatformSettingsData: jest.fn(),
},
}));
describe('WidgetSidebar', () => {
beforeEach(() => jest.resetAllMocks());
const courseSearchUrl = 'mock-url';
test('snapshots', () => {
const wrapper = shallow(<WidgetSidebarSlot />);
expect(wrapper.snapshot).toMatchSnapshot();
describe('WidgetSidebar', () => {
it('renders PluginSlot with correct children', () => {
reduxHooks.usePlatformSettingsData.mockReturnValueOnce({ courseSearchUrl });
render(<IntlProvider locale="en"><WidgetSidebarSlot /></IntlProvider>);
const pluginSlot = screen.getByText('Looking for a new challenge?');
expect(pluginSlot).toBeDefined();
});
});