refactor: replacing injectIntl with useIntl() part 3 (#460)

This commit is contained in:
Jacobo Dominguez
2025-08-14 08:48:34 -06:00
committed by GitHub
parent f49c6a55f2
commit 3115fc275c
12 changed files with 91 additions and 103 deletions

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
ActionRow,
AlertModal,
@@ -11,29 +11,30 @@ import {
import messages from './messages';
export const DemoAlert = ({
intl: { formatMessage },
isOpen,
onClose,
}) => (
<AlertModal
title={formatMessage(messages.title)}
isOpen={isOpen}
onClose={onClose}
footerNode={(
<ActionRow>
<Button variant="primary" onClick={onClose}>
{formatMessage(messages.confirm)}
</Button>
</ActionRow>
}) => {
const { formatMessage } = useIntl();
return (
<AlertModal
title={formatMessage(messages.title)}
isOpen={isOpen}
onClose={onClose}
footerNode={(
<ActionRow>
<Button variant="primary" onClick={onClose}>
{formatMessage(messages.confirm)}
</Button>
</ActionRow>
)}
>
<p>{formatMessage(messages.warningMessage)}</p>
</AlertModal>
);
>
<p>{formatMessage(messages.warningMessage)}</p>
</AlertModal>
);
};
DemoAlert.propTypes = {
intl: intlShape.isRequired,
isOpen: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
};
export default injectIntl(DemoAlert);
export default DemoAlert;

View File

@@ -9,7 +9,6 @@ jest.unmock('react');
describe('DemoAlert component', () => {
const props = {
intl: { formatMessage },
isOpen: true,
onClose: jest.fn().mockName('props.onClose'),
};

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import FileCard from './FileCard';
import { ErrorBanner, LoadingBanner } from './Banners';
@@ -12,8 +12,8 @@ import { renderHooks } from './hooks';
*/
export const FileRenderer = ({
file,
intl,
}) => {
const intl = useIntl();
const {
Renderer,
isLoading,
@@ -39,8 +39,6 @@ FileRenderer.propTypes = {
name: PropTypes.string,
downloadUrl: PropTypes.string,
}).isRequired,
// injected
intl: intlShape.isRequired,
};
export default injectIntl(FileRenderer);
export default FileRenderer;

View File

@@ -1,5 +1,4 @@
import { render, screen } from '@testing-library/react';
import { formatMessage } from 'testUtils';
import { keyStore } from 'utils';
import { ErrorStatuses } from 'data/constants/requests';
import { FileRenderer } from './FileRenderer';
@@ -16,7 +15,6 @@ const props = {
name: 'filename.txt',
description: 'A text file',
},
intl: { formatMessage },
};
describe('FileRenderer', () => {
describe('component', () => {

View File

@@ -8,7 +8,7 @@ import {
IconButton,
} from '@openedx/paragon';
import { InfoOutline } from '@openedx/paragon/icons';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { nullMethod } from 'hooks';
@@ -17,27 +17,35 @@ import messages from './messages';
/**
* <InfoPopover />
*/
export const InfoPopover = ({ onClick, children, intl }) => (
<OverlayTrigger
trigger="focus"
placement="right-end"
flip
overlay={(
<Popover id="info-popover" className="overlay-help-popover">
<Popover.Content>{children}</Popover.Content>
</Popover>
)}
>
<IconButton
className="esg-help-icon"
data-testid="esg-help-icon"
src={InfoOutline}
alt={intl.formatMessage(messages.altText)}
iconAs={Icon}
onClick={onClick}
/>
</OverlayTrigger>
);
export const InfoPopover = (
{
onClick,
children,
},
) => {
const intl = useIntl();
return (
<OverlayTrigger
trigger="focus"
placement="right-end"
flip
overlay={(
<Popover id="info-popover" className="overlay-help-popover">
<Popover.Content>{children}</Popover.Content>
</Popover>
)}
>
<IconButton
className="esg-help-icon"
data-testid="esg-help-icon"
src={InfoOutline}
alt={intl.formatMessage(messages.altText)}
iconAs={Icon}
onClick={onClick}
/>
</OverlayTrigger>
);
};
InfoPopover.defaultProps = {
onClick: nullMethod,
@@ -48,7 +56,6 @@ InfoPopover.propTypes = {
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]).isRequired,
intl: intlShape.isRequired,
};
export default injectIntl(InfoPopover);
export default InfoPopover;

View File

@@ -1,5 +1,4 @@
import { render, fireEvent } from '@testing-library/react';
import { formatMessage } from 'testUtils';
import { InfoPopover } from '.';
jest.unmock('@openedx/paragon');
@@ -12,7 +11,7 @@ describe('Info Popover Component', () => {
describe('Component', () => {
it('renders the help icon button', () => {
const { getByTestId } = render(
<InfoPopover onClick={onClick} intl={{ formatMessage }}>
<InfoPopover onClick={onClick}>
{child}
</InfoPopover>,
);
@@ -21,7 +20,7 @@ describe('Info Popover Component', () => {
it('calls onClick when the help icon is clicked', () => {
const { getByTestId } = render(
<InfoPopover onClick={onClick} intl={{ formatMessage }}>
<InfoPopover onClick={onClick}>
{child}
</InfoPopover>,
);

View File

@@ -2,14 +2,15 @@ import React from 'react';
import { useDispatch } from 'react-redux';
import { Button } from '@openedx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import StopGradingConfirmModal from '../StopGradingConfirmModal';
import OverrideGradeConfirmModal from '../OverrideGradeConfirmModal';
import * as hooks from './hooks';
export const StartGradingButton = ({ intl }) => {
export const StartGradingButton = () => {
const intl = useIntl();
const dispatch = useDispatch();
const {
hide,
@@ -31,8 +32,4 @@ export const StartGradingButton = ({ intl }) => {
);
};
StartGradingButton.propTypes = {
intl: intlShape.isRequired,
};
export default injectIntl(StartGradingButton);
export default StartGradingButton;

View File

@@ -3,7 +3,6 @@ import { shallow } from '@edx/react-unit-test-utils';
import { useDispatch } from 'react-redux';
import { formatMessage } from 'testUtils';
import * as hooks from './hooks';
import { StartGradingButton } from '.';
@@ -14,13 +13,10 @@ jest.mock('./hooks', () => ({
buttonHooks: jest.fn(),
}));
const intl = { formatMessage };
let el;
describe('StartGradingButton component', () => {
describe('component', () => {
const dispatch = useDispatch();
const props = { intl };
const buttonHooks = {
hide: false,
buttonArgs: { props: 'hooks.buttonArgs' },
@@ -30,20 +26,21 @@ describe('StartGradingButton component', () => {
describe('behavior', () => {
it('initializes buttonHooks with dispatch and intl fields', () => {
hooks.buttonHooks.mockReturnValueOnce(buttonHooks);
el = shallow(<StartGradingButton {...props} />);
expect(hooks.buttonHooks).toHaveBeenCalledWith({ dispatch, intl });
el = shallow(<StartGradingButton />);
const expected = { dispatch, intl: { formatMessage: expect.any(Function), formatDate: expect.any(Function) } };
expect(hooks.buttonHooks).toHaveBeenCalledWith(expected);
});
});
describe('snapshots', () => {
test('hide: renders empty component if hook.hide is true', () => {
hooks.buttonHooks.mockReturnValueOnce({ ...buttonHooks, hide: true });
el = shallow(<StartGradingButton {...props} />);
el = shallow(<StartGradingButton />);
expect(el.snapshot).toMatchSnapshot();
expect(el.isEmptyRender()).toEqual(true);
});
test('smoke test: forwards props to components from hooks', () => {
hooks.buttonHooks.mockReturnValueOnce(buttonHooks);
el = shallow(<StartGradingButton {...props} />);
el = shallow(<StartGradingButton />);
expect(el.snapshot).toMatchSnapshot();
expect(el.isEmptyRender()).toEqual(false);
});

View File

@@ -1,39 +1,39 @@
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import ConfirmModal from 'components/ConfirmModal';
import messages from './messages';
export const StopGradingConfirmModal = ({
intl,
isOpen,
isOverride,
onCancel,
onConfirm,
}) => (
<ConfirmModal
title={intl.formatMessage(isOverride
? messages.confirmStopOverrideTitle
: messages.confirmStopGradingTitle)}
content={intl.formatMessage(messages.confirmStopWarning)}
cancelText={intl.formatMessage(messages.goBack)}
confirmText={intl.formatMessage(isOverride
? messages.confirmStopOverrideAction
: messages.confirmStopGradingAction)}
onCancel={onCancel}
onConfirm={onConfirm}
isOpen={isOpen}
/>
);
}) => {
const intl = useIntl();
return (
<ConfirmModal
title={intl.formatMessage(isOverride
? messages.confirmStopOverrideTitle
: messages.confirmStopGradingTitle)}
content={intl.formatMessage(messages.confirmStopWarning)}
cancelText={intl.formatMessage(messages.goBack)}
confirmText={intl.formatMessage(isOverride
? messages.confirmStopOverrideAction
: messages.confirmStopGradingAction)}
onCancel={onCancel}
onConfirm={onConfirm}
isOpen={isOpen}
/>
);
};
StopGradingConfirmModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
isOverride: PropTypes.bool.isRequired,
onCancel: PropTypes.func.isRequired,
onConfirm: PropTypes.func.isRequired,
// injected
intl: intlShape.isRequired,
};
export default injectIntl(StopGradingConfirmModal);
export default StopGradingConfirmModal;

View File

@@ -1,13 +1,11 @@
import { shallow } from '@edx/react-unit-test-utils';
import { formatMessage } from 'testUtils';
import { StopGradingConfirmModal } from './StopGradingConfirmModal';
jest.mock('components/ConfirmModal', () => 'ConfirmModal');
describe('StopGradingConfirmModal', () => {
const props = {
intl: { formatMessage },
isOpen: false,
isOverride: false,
onCancel: jest.fn().mockName('this.props.onCancel'),

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { useIntl } from '@edx/frontend-platform/i18n';
import { rendererHooks } from './hooks';
@@ -10,7 +10,8 @@ import ReviewError from '../ReviewError';
/**
* <SubmitErrors />
*/
export const SubmitErrors = ({ intl }) => {
export const SubmitErrors = () => {
const intl = useIntl();
const dispatch = useDispatch();
const {
show,
@@ -29,9 +30,4 @@ export const SubmitErrors = ({ intl }) => {
);
};
SubmitErrors.propTypes = {
// injected
intl: intlShape.isRequired,
};
export default injectIntl(SubmitErrors);
export default SubmitErrors;

View File

@@ -2,7 +2,6 @@ import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { keyStore } from 'utils';
import { formatMessage } from 'testUtils';
import * as hooks from './hooks';
import { SubmitErrors } from '.';
@@ -11,11 +10,10 @@ jest.mock('../ReviewError', () => 'ReviewError');
const hookKeys = keyStore(hooks);
describe('SubmitErrors component', () => {
const props = { intl: { formatMessage } };
describe('snapshots', () => {
test('snapshot: no failure', () => {
jest.spyOn(hooks, hookKeys.rendererHooks).mockReturnValueOnce({ show: false });
const el = shallow(<SubmitErrors {...props} />);
const el = shallow(<SubmitErrors />);
expect(el.snapshot).toMatchSnapshot();
expect(el.isEmptyRender()).toEqual(true);
});
@@ -30,7 +28,7 @@ describe('SubmitErrors component', () => {
content: 'hooks.content',
};
jest.spyOn(hooks, hookKeys.rendererHooks).mockReturnValueOnce(mockHook);
expect(shallow(<SubmitErrors {...props} />).snapshot).toMatchSnapshot();
expect(shallow(<SubmitErrors />).snapshot).toMatchSnapshot();
});
});
});