Revert "Upgraded frontend-build version to v12 (#613)"
This reverts commit f0d6a92ab2.
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const { createConfig } = require('@edx/frontend-build');
|
||||
|
||||
module.exports = createConfig('eslint');
|
||||
|
||||
8669
package-lock.json
generated
8669
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -81,7 +81,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@edx/browserslist-config": "^1.1.0",
|
||||
"@edx/frontend-build": "^12.0.3",
|
||||
"@edx/frontend-build": "9.1.2",
|
||||
"@edx/reactifex": "^1.0.3",
|
||||
"@testing-library/jest-dom": "5.15.1",
|
||||
"@testing-library/react": "12.1.5",
|
||||
|
||||
@@ -148,13 +148,28 @@ class AccountSettingsPage extends React.Component {
|
||||
})),
|
||||
}));
|
||||
|
||||
sortDates = (a, b) => {
|
||||
const aTimeSinceEpoch = new Date(a).getTime();
|
||||
const bTimeSinceEpoch = new Date(b).getTime();
|
||||
|
||||
return bTimeSinceEpoch - aTimeSinceEpoch;
|
||||
}
|
||||
|
||||
sortVerifiedNameRecords = verifiedNameHistory => {
|
||||
if (Array.isArray(verifiedNameHistory)) {
|
||||
return [...verifiedNameHistory].sort(this.sortDates);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
handleEditableFieldChange = (name, value) => {
|
||||
this.props.updateDraft(name, value);
|
||||
};
|
||||
}
|
||||
|
||||
handleSubmit = (formId, values) => {
|
||||
this.props.saveSettings(formId, values);
|
||||
};
|
||||
}
|
||||
|
||||
handleSubmitProfileName = (formId, values) => {
|
||||
if (Object.keys(this.props.drafts).includes('useVerifiedNameForCerts')) {
|
||||
@@ -182,7 +197,7 @@ class AccountSettingsPage extends React.Component {
|
||||
} else {
|
||||
this.props.saveSettings(formId, values);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
isEditable(fieldName) {
|
||||
return !this.props.staticFields.includes(fieldName);
|
||||
@@ -267,7 +282,7 @@ class AccountSettingsPage extends React.Component {
|
||||
}
|
||||
|
||||
return this.props.intl.formatMessage(messages[messageString]);
|
||||
};
|
||||
}
|
||||
|
||||
renderVerifiedNameSuccessMessage = (verifiedName, created) => {
|
||||
const dateValue = new Date(created).valueOf();
|
||||
@@ -282,7 +297,7 @@ class AccountSettingsPage extends React.Component {
|
||||
body={this.props.intl.formatMessage(messages['account.settings.field.name.verified.success.message'])}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
renderVerifiedNameFailureMessage = (verifiedName, created) => {
|
||||
const dateValue = new Date(created).valueOf();
|
||||
@@ -313,7 +328,7 @@ class AccountSettingsPage extends React.Component {
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
renderVerifiedNameSubmittedMessage = (willCertNameChange) => (
|
||||
<Alert
|
||||
@@ -331,7 +346,7 @@ class AccountSettingsPage extends React.Component {
|
||||
}
|
||||
</p>
|
||||
</Alert>
|
||||
);
|
||||
)
|
||||
|
||||
renderVerifiedNameMessage = verifiedNameRecord => {
|
||||
const {
|
||||
@@ -372,7 +387,7 @@ class AccountSettingsPage extends React.Component {
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
renderVerifiedNameIcon = (status) => {
|
||||
switch (status) {
|
||||
@@ -383,7 +398,7 @@ class AccountSettingsPage extends React.Component {
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
renderVerifiedNameHelpText = (status, proctoredExamId) => {
|
||||
let messageStr = 'account.settings.field.name.verified.help.text';
|
||||
@@ -408,7 +423,7 @@ class AccountSettingsPage extends React.Component {
|
||||
}
|
||||
|
||||
return this.props.intl.formatMessage(messages[messageStr]);
|
||||
};
|
||||
}
|
||||
|
||||
renderEmptyStaticFieldMessage() {
|
||||
if (this.isManagedProfile()) {
|
||||
|
||||
@@ -128,7 +128,7 @@ function EditableField(props) {
|
||||
options={inputOptions}
|
||||
{...others}
|
||||
/>
|
||||
{others.children}
|
||||
<>{others.children}</>
|
||||
</ValidationFormGroup>
|
||||
<p>
|
||||
<StatefulButton
|
||||
|
||||
@@ -34,7 +34,7 @@ function CertificatePreference({
|
||||
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||
const formId = 'useVerifiedNameForCerts';
|
||||
|
||||
const handleCheckboxChange = () => {
|
||||
function handleCheckboxChange() {
|
||||
if (!checked) {
|
||||
if (fieldName === 'verified_name') {
|
||||
dispatch(updateDraft(formId, true));
|
||||
@@ -44,22 +44,22 @@ function CertificatePreference({
|
||||
} else {
|
||||
setModalIsOpen(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
function handleCancel() {
|
||||
setModalIsOpen(false);
|
||||
dispatch(resetDrafts());
|
||||
};
|
||||
}
|
||||
|
||||
const handleModalChange = (e) => {
|
||||
function handleModalChange(e) {
|
||||
if (e.target.value === 'fullName') {
|
||||
dispatch(updateDraft(formId, false));
|
||||
} else {
|
||||
dispatch(updateDraft(formId, true));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (saveState === 'pending') {
|
||||
@@ -67,7 +67,7 @@ function CertificatePreference({
|
||||
}
|
||||
|
||||
dispatch(saveSettings(formId, useVerifiedNameForCerts));
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (originalVerifiedName) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-import-assign */
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
@@ -17,28 +17,27 @@ import LogoSVG from '../../logo.svg';
|
||||
import { fetchSettings } from '../data/actions';
|
||||
import { coachingConsentPageSelector } from '../data/selectors';
|
||||
|
||||
function Logo({ src, alt, ...attributes }) {
|
||||
return <img src={src} alt={alt} {...attributes} />;
|
||||
}
|
||||
const Logo = ({ src, alt, ...attributes }) => (
|
||||
<>
|
||||
<img src={src} alt={alt} {...attributes} />
|
||||
</>
|
||||
);
|
||||
|
||||
function SuccessMessage(props) {
|
||||
return (
|
||||
<div className="col-12 col-lg-6 shadow-lg mx-auto mt-4 p-5">
|
||||
<FontAwesomeIcon className="text-success" icon={faCheck} size="5x" />
|
||||
<div className="h3">{props.header}</div>
|
||||
<div>{props.message}</div>
|
||||
<Hyperlink destination={props.continueUrl} className="d-block p-2 my-3 text-center text-white bg-primary rounded">
|
||||
{props.continue}
|
||||
</Hyperlink>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const SuccessMessage = props => (
|
||||
<div className="col-12 col-lg-6 shadow-lg mx-auto mt-4 p-5">
|
||||
<FontAwesomeIcon className="text-success" icon={faCheck} size="5x" />
|
||||
<div className="h3">{props.header}</div>
|
||||
<div>{props.message}</div>
|
||||
<Hyperlink destination={props.continueUrl} className="d-block p-2 my-3 text-center text-white bg-primary rounded">
|
||||
{props.continue}
|
||||
</Hyperlink>
|
||||
</div>
|
||||
);
|
||||
|
||||
function AutoRedirect(props) {
|
||||
const AutoRedirect = (props) => {
|
||||
window.location.href = props.redirectUrl;
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <></>;
|
||||
}
|
||||
};
|
||||
|
||||
const VIEWS = {
|
||||
NOT_LOADED: 'NOT_LOADED',
|
||||
@@ -72,23 +71,6 @@ class CoachingConsent extends React.Component {
|
||||
this.props.fetchSettings();
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
const fullName = e.target.fullName.value;
|
||||
const phoneNumber = e.target.phoneNumber.value;
|
||||
const body = {
|
||||
coaching_consent: true,
|
||||
consent_form_seen: true,
|
||||
phone_number: phoneNumber,
|
||||
full_name: fullName,
|
||||
};
|
||||
this.setState({
|
||||
formErrors: {},
|
||||
formSubmitted: true,
|
||||
declineSubmitted: false,
|
||||
}, () => this.patchUsingCoachingConsentForm(body));
|
||||
}
|
||||
|
||||
sanitizeForwardingUrl(url) {
|
||||
// Redirect to root of MFE if invalid next param is sent
|
||||
return url && url.startsWith(getConfig().LMS_BASE_URL) ? url : `${getConfig().LMS_BASE_URL}/dashboard/`;
|
||||
@@ -117,6 +99,23 @@ class CoachingConsent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
const fullName = e.target.fullName.value;
|
||||
const phoneNumber = e.target.phoneNumber.value;
|
||||
const body = {
|
||||
coaching_consent: true,
|
||||
consent_form_seen: true,
|
||||
phone_number: phoneNumber,
|
||||
full_name: fullName,
|
||||
};
|
||||
this.setState({
|
||||
formErrors: {},
|
||||
formSubmitted: true,
|
||||
declineSubmitted: false,
|
||||
}, () => this.patchUsingCoachingConsentForm(body));
|
||||
}
|
||||
|
||||
declineCoaching(e) {
|
||||
e.preventDefault();
|
||||
const body = {
|
||||
@@ -161,7 +160,6 @@ class CoachingConsent extends React.Component {
|
||||
case VIEWS.DECLINED:
|
||||
return <AutoRedirect redirectUrl={this.state.redirectUrl} />;
|
||||
default:
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
@@ -255,12 +253,12 @@ CoachingConsent.propTypes = {
|
||||
}),
|
||||
}).isRequired,
|
||||
formErrors: PropTypes.shape({
|
||||
coaching: PropTypes.shape({}),
|
||||
coaching: PropTypes.object,
|
||||
}).isRequired,
|
||||
confirmationValues: PropTypes.shape({
|
||||
coaching: PropTypes.shape({}),
|
||||
name: PropTypes.shape({}),
|
||||
phone_number: PropTypes.shape({}),
|
||||
coaching: PropTypes.object,
|
||||
name: PropTypes.object,
|
||||
phone_number: PropTypes.object,
|
||||
}).isRequired,
|
||||
fetchSettings: PropTypes.func.isRequired,
|
||||
profileDataManager: PropTypes.string,
|
||||
|
||||
@@ -8,86 +8,82 @@ import PropTypes from 'prop-types';
|
||||
import Alert from '../Alert';
|
||||
import messages from './CoachingConsent.messages';
|
||||
|
||||
function ErrorMessage(props) {
|
||||
return <div className="alert-warning mb-2">{props.message}</div>;
|
||||
}
|
||||
const ErrorMessage = props => (
|
||||
<div className="alert-warning mb-2">{props.message}</div>
|
||||
);
|
||||
|
||||
function ManagedProfileAlert({ profileDataManager }) {
|
||||
return (
|
||||
<Alert className="alert alert-primary" role="alert">
|
||||
<FormattedMessage
|
||||
id="account.settings.coaching.managed.alert"
|
||||
defaultMessage="Your name is managed by {managerTitle}. Contact your administrator for help."
|
||||
description="Alert message informing the user their account data is managed by a third party"
|
||||
values={{
|
||||
managerTitle: <b>{profileDataManager}</b>,
|
||||
}}
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
function CoachingForm(props) {
|
||||
return (
|
||||
<div className="col-12 col-md-6 col-xl-5 mx-auto mt-4 p-5 shadow-lg">
|
||||
<h2 className="h2">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.welcome.header'])}
|
||||
</h2>
|
||||
<p>{props.intl.formatMessage(messages['account.settings.coaching.consent.description'])}</p>
|
||||
<div>
|
||||
<form onSubmit={props.onSubmit}>
|
||||
<div className="py-3">
|
||||
{!!props.profileDataManager && (
|
||||
<ManagedProfileAlert profileDataManager={props.profileDataManager} />
|
||||
)}
|
||||
<ErrorMessage message={props.formErrors.full_name} />
|
||||
<label className="h6" htmlFor="fullName">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.label.name'])}
|
||||
</label>
|
||||
<Input
|
||||
type="text"
|
||||
name="full-name"
|
||||
id="fullName"
|
||||
disabled={!!props.profileDataManager}
|
||||
defaultValue={props.formValues.name}
|
||||
/>
|
||||
</div>
|
||||
<div className="py-3">
|
||||
<ErrorMessage message={props.formErrors.phone_number} />
|
||||
<label className="h6" htmlFor="phoneNumber">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.label.phone-number'])}
|
||||
</label>
|
||||
<Input
|
||||
type="text"
|
||||
name="phone_number"
|
||||
id="phoneNumber"
|
||||
defaultValue={props.formValues.phone_number}
|
||||
/>
|
||||
</div>
|
||||
<div className=" py-3">
|
||||
<p className="small font-italic">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.text-messaging.disclaimer'])}
|
||||
</p>
|
||||
</div>
|
||||
<ErrorMessage message={props.formErrors.coaching} />
|
||||
<div className="d-flex flex-column align-items-center">
|
||||
<Button variant="outline-primary" className="w-100" type="submit">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.accept-coaching'])}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<Hyperlink
|
||||
className="mt-3 text-dark btn-link small"
|
||||
destination={props.redirectUrl}
|
||||
onClick={props.declineCoaching}
|
||||
>
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.decline-coaching'])}
|
||||
</Hyperlink>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
const ManagedProfileAlert = ({ profileDataManager }) => (
|
||||
<Alert className="alert alert-primary" role="alert">
|
||||
<FormattedMessage
|
||||
id="account.settings.coaching.managed.alert"
|
||||
defaultMessage="Your name is managed by {managerTitle}. Contact your administrator for help."
|
||||
description="Alert message informing the user their account data is managed by a third party"
|
||||
values={{
|
||||
managerTitle: <b>{profileDataManager}</b>,
|
||||
}}
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
const CoachingForm = props => (
|
||||
<div className="col-12 col-md-6 col-xl-5 mx-auto mt-4 p-5 shadow-lg">
|
||||
<h2 className="h2">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.welcome.header'])}
|
||||
</h2>
|
||||
<p>{props.intl.formatMessage(messages['account.settings.coaching.consent.description'])}</p>
|
||||
<div>
|
||||
<form onSubmit={props.onSubmit}>
|
||||
<div className="py-3">
|
||||
{!!props.profileDataManager && (
|
||||
<ManagedProfileAlert profileDataManager={props.profileDataManager} />
|
||||
)}
|
||||
<ErrorMessage message={props.formErrors.full_name} />
|
||||
<label className="h6" htmlFor="fullName">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.label.name'])}
|
||||
</label>
|
||||
<Input
|
||||
type="text"
|
||||
name="full-name"
|
||||
id="fullName"
|
||||
disabled={!!props.profileDataManager}
|
||||
defaultValue={props.formValues.name}
|
||||
/>
|
||||
</div>
|
||||
<div className="py-3">
|
||||
<ErrorMessage message={props.formErrors.phone_number} />
|
||||
<label className="h6" htmlFor="phoneNumber">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.label.phone-number'])}
|
||||
</label>
|
||||
<Input
|
||||
type="text"
|
||||
name="phone_number"
|
||||
id="phoneNumber"
|
||||
defaultValue={props.formValues.phone_number}
|
||||
/>
|
||||
</div>
|
||||
<div className=" py-3">
|
||||
<p className="small font-italic">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.text-messaging.disclaimer'])}
|
||||
</p>
|
||||
</div>
|
||||
<ErrorMessage message={props.formErrors.coaching} />
|
||||
<div className="d-flex flex-column align-items-center">
|
||||
<Button variant="outline-primary" className="w-100" type="submit">
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.accept-coaching'])}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<Hyperlink
|
||||
className="mt-3 text-dark btn-link small"
|
||||
destination={props.redirectUrl}
|
||||
onClick={props.declineCoaching}
|
||||
>
|
||||
{props.intl.formatMessage(messages['account.settings.coaching.consent.decline-coaching'])}
|
||||
</Hyperlink>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
CoachingForm.defaultProps = {
|
||||
formErrors: {
|
||||
|
||||
@@ -8,69 +8,66 @@ import { editableFieldSelector } from '../data/selectors';
|
||||
import { saveSettings, updateDraft, saveMultipleSettings } from '../data/actions';
|
||||
import EditableField from '../EditableField';
|
||||
|
||||
function CoachingToggle(props) {
|
||||
return (
|
||||
<>
|
||||
<EditableField
|
||||
name="phone_number"
|
||||
type="text"
|
||||
value={props.phone_number}
|
||||
label={props.intl.formatMessage(messages['account.settings.field.phone_number'])}
|
||||
emptyLabel={props.intl.formatMessage(messages['account.settings.field.phone_number.empty'])}
|
||||
onChange={props.updateDraft}
|
||||
onSubmit={() => {
|
||||
const { coaching } = props;
|
||||
if (coaching.coaching_consent === true) {
|
||||
return props.saveMultipleSettings([
|
||||
{
|
||||
formId: 'coaching',
|
||||
commitValues: {
|
||||
...coaching,
|
||||
phone_number: props.phone_number,
|
||||
},
|
||||
const CoachingToggle = props => (
|
||||
<>
|
||||
<EditableField
|
||||
name="phone_number"
|
||||
type="text"
|
||||
value={props.phone_number}
|
||||
label={props.intl.formatMessage(messages['account.settings.field.phone_number'])}
|
||||
emptyLabel={props.intl.formatMessage(messages['account.settings.field.phone_number.empty'])}
|
||||
onChange={props.updateDraft}
|
||||
onSubmit={() => {
|
||||
const { coaching } = props;
|
||||
if (coaching.coaching_consent === true) {
|
||||
return props.saveMultipleSettings([
|
||||
{
|
||||
formId: 'coaching',
|
||||
commitValues: {
|
||||
...coaching,
|
||||
phone_number: props.phone_number,
|
||||
},
|
||||
{
|
||||
formId: 'phone_number',
|
||||
commitValues: props.phone_number,
|
||||
},
|
||||
], 'phone_number');
|
||||
}
|
||||
return props.saveSettings('phone_number', props.phone_number);
|
||||
},
|
||||
{
|
||||
formId: 'phone_number',
|
||||
commitValues: props.phone_number,
|
||||
},
|
||||
], 'phone_number');
|
||||
}
|
||||
return props.saveSettings('phone_number', props.phone_number);
|
||||
}}
|
||||
/>
|
||||
<ValidationFormGroup
|
||||
for="coachingConsent"
|
||||
helpText={props.intl.formatMessage(messages['account.settings.field.coaching_consent.tooltip'])}
|
||||
invalid={!!props.error}
|
||||
invalidMessage={props.intl.formatMessage(messages['account.settings.field.coaching_consent.error'])}
|
||||
className="custom-control custom-switch"
|
||||
>
|
||||
<Input
|
||||
name={props.name}
|
||||
className="custom-control-input"
|
||||
disabled={props.saveState === 'pending'}
|
||||
type="checkbox"
|
||||
id="coachingConsent"
|
||||
checked={props.coaching.coaching_consent}
|
||||
value={props.coaching.coaching_consent}
|
||||
onChange={async (e) => {
|
||||
const { name } = e.target;
|
||||
// eslint-disable-next-line camelcase
|
||||
const { user, eligible_for_coaching } = props.coaching;
|
||||
const value = {
|
||||
user,
|
||||
eligible_for_coaching,
|
||||
coaching_consent: e.target.checked,
|
||||
};
|
||||
props.saveSettings(name, value);
|
||||
}}
|
||||
/>
|
||||
<ValidationFormGroup
|
||||
for="coachingConsent"
|
||||
helpText={props.intl.formatMessage(messages['account.settings.field.coaching_consent.tooltip'])}
|
||||
invalid={!!props.error}
|
||||
invalidMessage={props.intl.formatMessage(messages['account.settings.field.coaching_consent.error'])}
|
||||
className="custom-control custom-switch"
|
||||
>
|
||||
<Input
|
||||
name={props.name}
|
||||
className="custom-control-input"
|
||||
disabled={props.saveState === 'pending'}
|
||||
type="checkbox"
|
||||
id="coachingConsent"
|
||||
checked={props.coaching.coaching_consent}
|
||||
value={props.coaching.coaching_consent}
|
||||
onChange={async (e) => {
|
||||
const { name } = e.target;
|
||||
// eslint-disable-next-line camelcase
|
||||
const { user, eligible_for_coaching } = props.coaching;
|
||||
const value = {
|
||||
user,
|
||||
// eslint-disable-next-line camelcase
|
||||
eligible_for_coaching,
|
||||
coaching_consent: e.target.checked,
|
||||
};
|
||||
props.saveSettings(name, value);
|
||||
}}
|
||||
/>
|
||||
<label className="custom-control-label" htmlFor="coachingConsent">{props.intl.formatMessage(messages['account.settings.field.coaching_consent'])}</label>
|
||||
</ValidationFormGroup>
|
||||
</>
|
||||
);
|
||||
}
|
||||
<label className="custom-control-label" htmlFor="coachingConsent">{props.intl.formatMessage(messages['account.settings.field.coaching_consent'])}</label>
|
||||
</ValidationFormGroup>
|
||||
</>
|
||||
);
|
||||
|
||||
CoachingToggle.defaultProps = {
|
||||
phone_number: '',
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-import-assign */
|
||||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
@@ -41,7 +41,7 @@ export const defaultState = {
|
||||
verifiedNameHistory: {},
|
||||
};
|
||||
|
||||
const reducer = (state = defaultState, action = {}) => {
|
||||
const reducer = (state = defaultState, action) => {
|
||||
let dispatcherIsOpenForm;
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
@@ -179,7 +179,7 @@ const formValuesSelector = createSelector(
|
||||
|
||||
const transformTimeZonesToOptions = timeZoneArr => timeZoneArr
|
||||
.map(({ time_zone, description }) => ({ // eslint-disable-line camelcase
|
||||
value: time_zone, label: description, // eslint-disable-line camelcase
|
||||
value: time_zone, label: description,
|
||||
}));
|
||||
|
||||
const timeZonesSelector = createSelector(
|
||||
|
||||
@@ -12,7 +12,7 @@ import messages from './messages';
|
||||
// Components
|
||||
import Alert from '../Alert';
|
||||
|
||||
function BeforeProceedingBanner(props) {
|
||||
const BeforeProceedingBanner = (props) => {
|
||||
const { instructionMessageId, intl, supportArticleUrl } = props;
|
||||
|
||||
return (
|
||||
@@ -35,7 +35,7 @@ function BeforeProceedingBanner(props) {
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
BeforeProceedingBanner.propTypes = {
|
||||
instructionMessageId: PropTypes.string.isRequired,
|
||||
|
||||
@@ -92,10 +92,8 @@ export class DeleteAccount extends React.Component {
|
||||
<PrintingInstructions />
|
||||
</p>
|
||||
<p className="text-danger h6">
|
||||
{intl.formatMessage(
|
||||
messages['account.settings.delete.account.text.warning'],
|
||||
{ siteName: getConfig().SITE_NAME },
|
||||
)}
|
||||
{intl.formatMessage(messages['account.settings.delete.account.text.warning'],
|
||||
{ siteName: getConfig().SITE_NAME })}
|
||||
</p>
|
||||
<p>
|
||||
<Hyperlink destination="https://support.edx.org/hc/en-us/sections/115004139268-Manage-Your-Account-Settings">
|
||||
|
||||
@@ -3,12 +3,8 @@ import renderer from 'react-test-renderer';
|
||||
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
// Testing the modals separately, they just clutter up the snapshots if included here.
|
||||
jest.mock('./ConfirmationModal', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('./SuccessModal', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('./ConfirmationModal', () => () => (<></>));
|
||||
jest.mock('./SuccessModal', () => () => (<></>));
|
||||
|
||||
import { DeleteAccount } from './DeleteAccount'; // eslint-disable-line import/first
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Hyperlink } from '@edx/paragon';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import messages from './messages';
|
||||
|
||||
function PrintingInstructions(props) {
|
||||
const PrintingInstructions = (props) => {
|
||||
const actionLink = (
|
||||
<Hyperlink
|
||||
// TODO: What would a generic version of this link look like? Should
|
||||
@@ -38,7 +38,7 @@ function PrintingInstructions(props) {
|
||||
values={{ actionLink }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
PrintingInstructions.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Modal } from '@edx/paragon';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
export function SuccessModal(props) {
|
||||
export const SuccessModal = (props) => {
|
||||
const { status, intl, onClose } = props;
|
||||
return (
|
||||
<Modal
|
||||
@@ -23,7 +23,7 @@ export function SuccessModal(props) {
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
SuccessModal.propTypes = {
|
||||
status: PropTypes.oneOf(['confirming', 'pending', 'deleted', 'failed']),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// eslint-disable-next-line no-restricted-exports
|
||||
export { default } from './DeleteAccount';
|
||||
export { default as reducer } from './data/reducers';
|
||||
export { default as saga } from './data/sagas';
|
||||
|
||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import { CheckBox } from '@edx/paragon';
|
||||
import { DECLINED } from '../data/constants';
|
||||
|
||||
function Checkboxes(props) {
|
||||
const Checkboxes = (props) => {
|
||||
const {
|
||||
id,
|
||||
options,
|
||||
@@ -59,7 +59,7 @@ function Checkboxes(props) {
|
||||
{renderCheckboxes()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Checkboxes.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
|
||||
@@ -75,7 +75,7 @@ class DemographicsSection extends React.Component {
|
||||
const matchingOption = demographicsEthnicityOptions.filter(option => option.value === e)[0];
|
||||
return matchingOption && matchingOption.label;
|
||||
}).join(', ');
|
||||
};
|
||||
}
|
||||
|
||||
handleEditableFieldChange = (name, value) => {
|
||||
this.props.updateDraft(name, value);
|
||||
@@ -317,7 +317,7 @@ DemographicsSection.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
formValues: PropTypes.shape({
|
||||
demographics_gender: PropTypes.string,
|
||||
demographics_user_ethnicity: PropTypes.shape([]),
|
||||
demographics_user_ethnicity: PropTypes.array,
|
||||
demographics_income: PropTypes.string,
|
||||
demographics_military_history: PropTypes.string,
|
||||
demographics_learner_education_level: PropTypes.string,
|
||||
@@ -327,11 +327,11 @@ DemographicsSection.propTypes = {
|
||||
demographics_future_work_sector: PropTypes.string,
|
||||
demographics_work_status_description: PropTypes.string,
|
||||
demographics_gender_description: PropTypes.string,
|
||||
demographicsOptions: PropTypes.shape({}),
|
||||
demographicsOptions: PropTypes.object,
|
||||
}).isRequired,
|
||||
drafts: PropTypes.shape({
|
||||
demographics_gender: PropTypes.string,
|
||||
demographics_user_ethnicity: PropTypes.shape([]),
|
||||
demographics_user_ethnicity: PropTypes.array,
|
||||
demographics_income: PropTypes.string,
|
||||
demographics_military_history: PropTypes.string,
|
||||
demographics_learner_education_level: PropTypes.string,
|
||||
@@ -341,7 +341,7 @@ DemographicsSection.propTypes = {
|
||||
demographics_future_work_sector: PropTypes.string,
|
||||
demographics_work_status_description: PropTypes.string,
|
||||
demographics_gender_description: PropTypes.string,
|
||||
demographicsOptions: PropTypes.shape({}),
|
||||
demographicsOptions: PropTypes.object,
|
||||
}).isRequired,
|
||||
formErrors: PropTypes.shape({
|
||||
demographicsError: PropTypes.string,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-import-assign */
|
||||
import * as auth from '@edx/frontend-platform/auth';
|
||||
|
||||
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// eslint-disable-next-line no-restricted-exports
|
||||
export { default } from './AccountSettingsPage';
|
||||
export { default as reducer } from './data/reducers';
|
||||
export { default as saga } from './data/sagas';
|
||||
|
||||
@@ -39,9 +39,9 @@ function NameChangeModal({
|
||||
dispatch(requestNameChangeReset());
|
||||
}, [dispatch]);
|
||||
|
||||
const handleChange = (e) => {
|
||||
function handleChange(e) {
|
||||
setVerifiedNameInput(e.target.value);
|
||||
};
|
||||
}
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
resetLocalState();
|
||||
@@ -49,7 +49,7 @@ function NameChangeModal({
|
||||
dispatch(saveSettingsReset());
|
||||
}, [dispatch, resetLocalState, targetFormId]);
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (saveState === 'pending') {
|
||||
@@ -64,7 +64,7 @@ function NameChangeModal({
|
||||
const draftProfileName = targetFormId === 'name' ? formValues.name : null;
|
||||
dispatch(requestNameChange(username, draftProfileName, verifiedNameInput));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (saveState === 'complete') {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// eslint-disable-next-line no-restricted-exports
|
||||
export { default } from './NameChange';
|
||||
export { default as reducer } from './data/reducers';
|
||||
export { default as saga } from './data/sagas';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-import-assign */
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
@@ -7,7 +7,7 @@ import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import Alert from '../Alert';
|
||||
|
||||
function ConfirmationAlert(props) {
|
||||
const ConfirmationAlert = (props) => {
|
||||
const { email } = props;
|
||||
|
||||
const technicalSupportLink = (
|
||||
@@ -38,7 +38,7 @@ function ConfirmationAlert(props) {
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
ConfirmationAlert.propTypes = {
|
||||
email: PropTypes.string.isRequired,
|
||||
|
||||
@@ -5,19 +5,17 @@ import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import Alert from '../Alert';
|
||||
|
||||
function RequestInProgressAlert() {
|
||||
return (
|
||||
<Alert
|
||||
className="alert-warning mt-n2"
|
||||
icon={<FontAwesomeIcon className="mr-2" icon={faExclamationTriangle} />}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="account.settings.editable.field.password.reset.button.forbidden"
|
||||
defaultMessage="Your previous request is in progress, please try again in few moments."
|
||||
description="A message displayed when a previous password reset request is still in progress."
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
const RequestInProgressAlert = () => (
|
||||
<Alert
|
||||
className="alert-warning mt-n2"
|
||||
icon={<FontAwesomeIcon className="mr-2" icon={faExclamationTriangle} />}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="account.settings.editable.field.password.reset.button.forbidden"
|
||||
defaultMessage="Your previous request is in progress, please try again in few moments."
|
||||
description="A message displayed when a previous password reset request is still in progress."
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
|
||||
export default RequestInProgressAlert;
|
||||
|
||||
@@ -9,7 +9,7 @@ import messages from './messages';
|
||||
import ConfirmationAlert from './ConfirmationAlert';
|
||||
import RequestInProgressAlert from './RequestInProgressAlert';
|
||||
|
||||
function ResetPassword(props) {
|
||||
const ResetPassword = (props) => {
|
||||
const { email, intl, status } = props;
|
||||
return (
|
||||
<div className="form-group">
|
||||
@@ -47,7 +47,7 @@ function ResetPassword(props) {
|
||||
{status === 'forbidden' ? <RequestInProgressAlert /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
ResetPassword.propTypes = {
|
||||
email: PropTypes.string,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// eslint-disable-next-line no-restricted-exports
|
||||
export { default } from './ResetPassword';
|
||||
export { default as reducer } from './data/reducers';
|
||||
export { RESET_PASSWORD } from './data/actions';
|
||||
|
||||
@@ -16,7 +16,7 @@ class ThirdPartyAuth extends Component {
|
||||
}
|
||||
const disconnectUrl = e.currentTarget.getAttribute('data-disconnect-url');
|
||||
this.props.disconnectAuth(disconnectUrl, providerId);
|
||||
};
|
||||
}
|
||||
|
||||
renderUnconnectedProvider(url, name) {
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// eslint-disable-next-line no-restricted-exports
|
||||
export { default } from './ThirdPartyAuth';
|
||||
export { default as reducer } from './data/reducers';
|
||||
export { default as saga } from './data/sagas';
|
||||
|
||||
@@ -5,16 +5,14 @@ import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
function Head({ intl }) {
|
||||
return (
|
||||
<Helmet>
|
||||
<title>
|
||||
{intl.formatMessage(messages['account.page.title'], { siteName: getConfig().SITE_NAME })}
|
||||
</title>
|
||||
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
const Head = ({ intl }) => (
|
||||
<Helmet>
|
||||
<title>
|
||||
{intl.formatMessage(messages['account.page.title'], { siteName: getConfig().SITE_NAME })}
|
||||
</title>
|
||||
<link rel="shortcut icon" href={getConfig().FAVICON_URL} type="image/x-icon" />
|
||||
</Helmet>
|
||||
);
|
||||
|
||||
Head.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
|
||||
@@ -175,7 +175,7 @@ class Camera extends React.Component {
|
||||
if (predictions.length === 0) {
|
||||
this.giveFeedback(predictions.length, [], false);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
startDetection() {
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -14,14 +14,14 @@ function CameraHelpWithUpload(props) {
|
||||
const { setIdPhotoFile, idPhotoFile, userId } = useContext(IdVerificationContext);
|
||||
const [hasUploadedImage, setHasUploadedImage] = useState(false);
|
||||
|
||||
const setAndTrackIdPhotoFile = (image) => {
|
||||
function setAndTrackIdPhotoFile(image) {
|
||||
sendTrackEvent('edx.id_verification.upload_id', {
|
||||
category: 'id_verification',
|
||||
user_id: userId,
|
||||
});
|
||||
setHasUploadedImage(true);
|
||||
setIdPhotoFile(image);
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -11,7 +11,7 @@ function CollapsibleImageHelp(props) {
|
||||
userId, useCameraForId, setUseCameraForId,
|
||||
} = useContext(IdVerificationContext);
|
||||
|
||||
const handleClick = () => {
|
||||
function handleClick() {
|
||||
const toggleTo = useCameraForId ? 'upload' : 'camera';
|
||||
const eventName = `edx.id_verification.toggle_to.${toggleTo}`;
|
||||
sendTrackEvent(eventName, {
|
||||
@@ -19,7 +19,7 @@ function CollapsibleImageHelp(props) {
|
||||
user_id: userId,
|
||||
});
|
||||
setUseCameraForId(!useCameraForId);
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<Collapsible
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import React, {
|
||||
useState, useContext, useEffect, useMemo,
|
||||
} from 'react';
|
||||
import React, { useState, useContext, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
|
||||
@@ -72,7 +70,7 @@ export default function IdVerificationContextProvider({ children }) {
|
||||
}
|
||||
}
|
||||
|
||||
const contextValue = useMemo(() => ({
|
||||
const contextValue = {
|
||||
existingIdVerification,
|
||||
facePhotoFile,
|
||||
idPhotoFile,
|
||||
@@ -110,9 +108,7 @@ export default function IdVerificationContextProvider({ children }) {
|
||||
setMediaStream(null);
|
||||
}
|
||||
},
|
||||
}), [authenticatedUser.name, authenticatedUser.userId, existingIdVerification, facePhotoFile,
|
||||
idPhotoFile, idPhotoName, mediaAccess, mediaStream, profileDataManager, reachedSummary,
|
||||
useCameraForId, verifiedName]);
|
||||
};
|
||||
|
||||
const loadingStatuses = [IDLE_STATUS, LOADING_STATUS];
|
||||
// If we are waiting for verification status or verified name history endpoint, show spinner.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { createContext, useMemo } from 'react';
|
||||
import React, { createContext } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { getVerifiedNameHistory } from '../account-settings/data/service';
|
||||
@@ -18,10 +18,10 @@ export function VerifiedNameContextProvider({ children }) {
|
||||
verifiedName = getMostRecentApprovedOrPendingVerifiedName(results);
|
||||
}
|
||||
|
||||
const value = useMemo(() => ({
|
||||
const value = {
|
||||
verifiedNameHistoryCallStatus: status,
|
||||
verifiedName,
|
||||
}), [status, verifiedName]);
|
||||
};
|
||||
|
||||
return (<VerifiedNameContext.Provider value={value}>{children}</VerifiedNameContext.Provider>);
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
// eslint-disable-next-line no-restricted-exports
|
||||
export { default } from './IdVerificationPage';
|
||||
|
||||
@@ -63,7 +63,6 @@ export function EnableCameraDirectionsPanel(props) {
|
||||
</>
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <></>;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,12 +30,12 @@ function GetNameIdPanel(props) {
|
||||
}
|
||||
}, [idPhotoName, location.state, nameOnAccountValue, setIdPhotoName]);
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
if (idPhotoName) {
|
||||
push(nextPanelSlug);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<BasePanel
|
||||
|
||||
@@ -59,9 +59,8 @@ function SummaryPanel(props) {
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/no-unstable-nested-components
|
||||
function SubmitButton() {
|
||||
const handleClick = async () => {
|
||||
async function handleClick() {
|
||||
setIsSubmitting(true);
|
||||
const verificationData = {
|
||||
facePhotoFile,
|
||||
@@ -86,7 +85,7 @@ function SummaryPanel(props) {
|
||||
setIsSubmitting(false);
|
||||
setSubmissionError(result);
|
||||
}
|
||||
};
|
||||
}
|
||||
return (
|
||||
<Button
|
||||
title="Confirmation"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-import-assign */
|
||||
import React from 'react';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { createMemoryHistory } from 'history';
|
||||
|
||||
@@ -13,7 +13,6 @@ jest.mock('jslib-html5-camera-photo');
|
||||
jest.mock('@tensorflow-models/blazeface');
|
||||
jest.mock('@edx/frontend-platform/analytics');
|
||||
|
||||
// eslint-disable-next-line no-import-assign
|
||||
analytics.sendTrackEvent = jest.fn();
|
||||
|
||||
window.HTMLMediaElement.prototype.play = () => {};
|
||||
|
||||
@@ -18,33 +18,15 @@ jest.mock('../VerifiedNameContext', () => {
|
||||
VerifiedNameContextProvider: jest.fn(({ children }) => children),
|
||||
};
|
||||
});
|
||||
jest.mock('../panels/ReviewRequirementsPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/RequestCameraAccessPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/PortraitPhotoContextPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/TakePortraitPhotoPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/IdContextPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/GetNameIdPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/TakeIdPhotoPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/SummaryPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/SubmittedPanel', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../panels/ReviewRequirementsPanel', () => () => (<></>));
|
||||
jest.mock('../panels/RequestCameraAccessPanel', () => () => (<></>));
|
||||
jest.mock('../panels/PortraitPhotoContextPanel', () => () => (<></>));
|
||||
jest.mock('../panels/TakePortraitPhotoPanel', () => () => (<></>));
|
||||
jest.mock('../panels/IdContextPanel', () => () => (<></>));
|
||||
jest.mock('../panels/GetNameIdPanel', () => () => (<></>));
|
||||
jest.mock('../panels/TakeIdPhotoPanel', () => () => (<></>));
|
||||
jest.mock('../panels/SummaryPanel', () => () => (<></>));
|
||||
jest.mock('../panels/SubmittedPanel', () => () => (<></>));
|
||||
|
||||
const IntlIdVerificationPage = injectIntl(IdVerificationPage);
|
||||
|
||||
|
||||
@@ -4,12 +4,14 @@ import { render, cleanup, waitFor } from '@testing-library/react';
|
||||
import { getVerifiedNameHistory } from '../../account-settings/data/service';
|
||||
import { VerifiedNameContext, VerifiedNameContextProvider } from '../VerifiedNameContext';
|
||||
|
||||
function VerifiedNameContextTestComponent() {
|
||||
const VerifiedNameContextTestComponent = () => {
|
||||
const { verifiedName } = useContext(VerifiedNameContext);
|
||||
return (
|
||||
verifiedName && (<div data-testid="verified-name">{verifiedName}</div>)
|
||||
<>
|
||||
{verifiedName && (<div data-testid="verified-name">{verifiedName}</div>)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
jest.mock('../../account-settings/data/service', () => ({
|
||||
getVerifiedNameHistory: jest.fn(() => ({})),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-import-assign */
|
||||
import React from 'react';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { createMemoryHistory } from 'history';
|
||||
|
||||
@@ -12,9 +12,7 @@ jest.mock('@edx/frontend-platform/analytics', () => ({
|
||||
sendTrackEvent: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../Camera', () => function () {
|
||||
return null;
|
||||
});
|
||||
jest.mock('../../Camera', () => () => (<></>));
|
||||
|
||||
const history = createMemoryHistory();
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { render, waitFor } from '@testing-library/react';
|
||||
import { useAsyncCall } from '../hooks';
|
||||
import { LOADING_STATUS, SUCCESS_STATUS, FAILURE_STATUS } from '../constants';
|
||||
|
||||
function TestUseAsyncCallHookComponent({ asyncFunc }) {
|
||||
const TestUseAsyncCallHookComponent = ({ asyncFunc }) => {
|
||||
const { status, data } = useAsyncCall(asyncFunc);
|
||||
return (
|
||||
<>
|
||||
@@ -12,7 +12,7 @@ function TestUseAsyncCallHookComponent({ asyncFunc }) {
|
||||
{data && Object.keys(data).length !== 0 && <div data-testid="data">{ data.data }</div>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
TestUseAsyncCallHookComponent.propTypes = {
|
||||
asyncFunc: PropTypes.func.isRequired,
|
||||
|
||||
Reference in New Issue
Block a user