diff --git a/src/head/Head.jsx b/src/head/Head.jsx
index b84fd32a2..247815391 100644
--- a/src/head/Head.jsx
+++ b/src/head/Head.jsx
@@ -1,21 +1,26 @@
import React from 'react';
import { Helmet } from 'react-helmet';
-import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
+import { useIntl } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import messages from './messages';
-const Head = ({ intl }) => (
-
-
- {intl.formatMessage(messages['profile.page.title'], { siteName: getConfig().SITE_NAME })}
-
-
-
-);
-
-Head.propTypes = {
- intl: intlShape.isRequired,
+const Head = () => {
+ const intl = useIntl();
+ return (
+
+
+ {intl.formatMessage(messages['profile.page.title'], {
+ siteName: getConfig().SITE_NAME,
+ })}
+
+
+
+ );
};
-export default injectIntl(Head);
+export default Head;
diff --git a/src/profile/forms/elements/EditButton.jsx b/src/profile/forms/elements/EditButton.jsx
index 80cb47946..8444a450e 100644
--- a/src/profile/forms/elements/EditButton.jsx
+++ b/src/profile/forms/elements/EditButton.jsx
@@ -1,43 +1,43 @@
import React from 'react';
import PropTypes from 'prop-types';
import { EditOutline } from '@openedx/paragon/icons';
-import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
+import { useIntl } from '@edx/frontend-platform/i18n';
import { Button, OverlayTrigger, Tooltip } from '@openedx/paragon';
import messages from './EditButton.messages';
-const EditButton = ({
- onClick, className, style, intl,
-}) => (
-
-
- {intl.formatMessage(messages['profile.editbutton.edit'])}
-
-
- )}
- >
-
-
-);
+
+
+ );
+};
-export default injectIntl(EditButton);
+export default EditButton;
EditButton.propTypes = {
onClick: PropTypes.func.isRequired,
className: PropTypes.string,
style: PropTypes.object, // eslint-disable-line
- intl: intlShape.isRequired,
};
EditButton.defaultProps = {
diff --git a/src/profile/forms/elements/EditButton.test.jsx b/src/profile/forms/elements/EditButton.test.jsx
new file mode 100644
index 000000000..d37f8666c
--- /dev/null
+++ b/src/profile/forms/elements/EditButton.test.jsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import { render, fireEvent } from '@testing-library/react';
+import { IntlProvider } from '@edx/frontend-platform/i18n';
+import EditButton from './EditButton';
+
+const messages = {
+ 'profile.editbutton.edit': { defaultMessage: 'Edit' },
+};
+
+describe('EditButton', () => {
+ it('renders and calls onClick when clicked', () => {
+ const onClick = jest.fn();
+ const { getByRole } = render(
+
+
+ ,
+ );
+ const button = getByRole('button');
+ fireEvent.click(button);
+ expect(onClick).toHaveBeenCalled();
+ });
+});
diff --git a/src/profile/forms/elements/FormControls.jsx b/src/profile/forms/elements/FormControls.jsx
index ddb286671..304c69850 100644
--- a/src/profile/forms/elements/FormControls.jsx
+++ b/src/profile/forms/elements/FormControls.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button, StatefulButton } from '@openedx/paragon';
-import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
+import { useIntl } from '@edx/frontend-platform/i18n';
import messages from './FormControls.messages';
@@ -9,8 +9,13 @@ import { VisibilitySelect } from './Visibility';
import { useIsVisibilityEnabled } from '../../data/hooks';
const FormControls = ({
- cancelHandler, changeHandler, visibility, visibilityId, saveState, intl,
+ cancelHandler,
+ changeHandler,
+ visibility,
+ visibilityId,
+ saveState,
}) => {
+ const intl = useIntl();
const buttonState = saveState === 'error' ? null : saveState;
const isVisibilityEnabled = useIsVisibilityEnabled();
@@ -42,18 +47,17 @@ const FormControls = ({
type="submit"
state={buttonState}
labels={{
- default: intl.formatMessage(messages['profile.formcontrols.button.save']),
- pending: intl.formatMessage(messages['profile.formcontrols.button.saving']),
- complete: intl.formatMessage(messages['profile.formcontrols.button.saved']),
+ default: intl.formatMessage(
+ messages['profile.formcontrols.button.save'],
+ ),
+ pending: intl.formatMessage(
+ messages['profile.formcontrols.button.saving'],
+ ),
+ complete: intl.formatMessage(
+ messages['profile.formcontrols.button.saved'],
+ ),
}}
onClick={(e) => {
- // Swallow clicks if the state is pending.
- // We do this instead of disabling the button to prevent
- // it from losing focus (disabled elements cannot have focus).
- // Disabling it would causes upstream issues in focus management.
- // Swallowing the onSubmit event on the form would be better, but
- // we would have to add that logic for every field given our
- // current structure of the application.
if (buttonState === 'pending') {
e.preventDefault();
}
@@ -66,7 +70,7 @@ const FormControls = ({
);
};
-export default injectIntl(FormControls);
+export default FormControls;
FormControls.propTypes = {
saveState: PropTypes.oneOf([null, 'pending', 'complete', 'error']),
@@ -74,8 +78,6 @@ FormControls.propTypes = {
visibilityId: PropTypes.string.isRequired,
cancelHandler: PropTypes.func.isRequired,
changeHandler: PropTypes.func.isRequired,
-
- intl: intlShape.isRequired,
};
FormControls.defaultProps = {
diff --git a/src/profile/forms/elements/Visibility.jsx b/src/profile/forms/elements/Visibility.jsx
index cfe67a26e..315c148ff 100644
--- a/src/profile/forms/elements/Visibility.jsx
+++ b/src/profile/forms/elements/Visibility.jsx
@@ -1,17 +1,20 @@
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 { getConfig } from '@edx/frontend-platform';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faEyeSlash, faEye } from '@fortawesome/free-regular-svg-icons';
import messages from './Visibility.messages';
-const Visibility = ({ to, intl }) => {
+const Visibility = ({ to }) => {
+ const intl = useIntl();
const icon = to === 'private' ? faEyeSlash : faEye;
const label = to === 'private'
? intl.formatMessage(messages['profile.visibility.who.just.me'])
- : intl.formatMessage(messages['profile.visibility.who.everyone'], { siteName: getConfig().SITE_NAME });
+ : intl.formatMessage(messages['profile.visibility.who.everyone'], {
+ siteName: getConfig().SITE_NAME,
+ });
return (
@@ -22,14 +25,13 @@ const Visibility = ({ to, intl }) => {
Visibility.propTypes = {
to: PropTypes.oneOf(['private', 'all_users']),
-
- intl: intlShape.isRequired,
};
Visibility.defaultProps = {
to: 'private',
};
-const VisibilitySelect = ({ intl, className, ...props }) => {
+const VisibilitySelect = ({ className, ...props }) => {
+ const intl = useIntl();
const { value } = props;
const icon = value === 'private' ? faEyeSlash : faEye;
@@ -43,7 +45,9 @@ const VisibilitySelect = ({ intl, className, ...props }) => {
{intl.formatMessage(messages['profile.visibility.who.just.me'])}
@@ -56,8 +60,6 @@ VisibilitySelect.propTypes = {
name: PropTypes.string,
value: PropTypes.oneOf(['private', 'all_users']),
onChange: PropTypes.func,
-
- intl: intlShape.isRequired,
};
VisibilitySelect.defaultProps = {
id: null,
@@ -67,10 +69,4 @@ VisibilitySelect.defaultProps = {
onChange: null,
};
-const intlVisibility = injectIntl(Visibility);
-const intlVisibilitySelect = injectIntl(VisibilitySelect);
-
-export {
- intlVisibility as Visibility,
- intlVisibilitySelect as VisibilitySelect,
-};
+export { Visibility, VisibilitySelect };
diff --git a/src/profile/forms/elements/Visibility.test.jsx b/src/profile/forms/elements/Visibility.test.jsx
new file mode 100644
index 000000000..4fab7ef26
--- /dev/null
+++ b/src/profile/forms/elements/Visibility.test.jsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import { IntlProvider } from '@edx/frontend-platform/i18n';
+import { Visibility, VisibilitySelect } from './Visibility';
+import '@testing-library/jest-dom';
+
+const messages = {
+ 'profile.visibility.who.just.me': { defaultMessage: 'Just me' },
+ 'profile.visibility.who.everyone': { defaultMessage: 'Everyone' },
+};
+
+describe('Visibility', () => {
+ it('shows the correct icon and label for private', () => {
+ const { getByText } = render(
+
+
+ ,
+ );
+ expect(getByText(/just me/i)).toBeInTheDocument();
+ });
+ it('shows the correct icon and label for all_users', () => {
+ const { getByText } = render(
+
+
+ ,
+ );
+ expect(getByText(/everyone/i)).toBeInTheDocument();
+ });
+});
+
+describe('VisibilitySelect', () => {
+ it('renders both options', () => {
+ const { getByRole, getAllByRole } = render(
+
+ {}} />
+ ,
+ );
+ const select = getByRole('combobox');
+ const options = getAllByRole('option');
+ expect(select).toBeInTheDocument();
+ expect(options.length).toBe(2);
+ });
+});