Merge pull request #3367 from picklesrus/captcha-error-handling

Handle errors of captcha loading by setting error state on JoinFlow.
This commit is contained in:
picklesrus 2019-09-23 23:57:13 -04:00 committed by GitHub
commit 5f3d6506c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 3 deletions

View file

@ -56,7 +56,11 @@ class EmailStep extends React.Component {
this.emailInput = emailInputRef;
}
onCaptchaError () {
// TODO send user to error step once we have one.
this.props.onRegistrationError(
this.props.intl.formatMessage({
id: 'registation.troubleReload'
})
);
}
onCaptchaLoad () {
this.setState({captchaIsLoading: false});
@ -64,9 +68,9 @@ class EmailStep extends React.Component {
if (!this.grecaptcha) {
// According to the reCaptcha documentation, this callback shouldn't get
// called unless window.grecaptcha exists. This is just here to be extra defensive.
// TODO: Put up the error screen when we have one.
this.onCaptchaError();
return;
}
// TODO: Add in error callback for render once we have an error screen.
this.widgetId = this.grecaptcha.render(this.captchaRef,
{
callback: this.captchaSolved,
@ -208,6 +212,7 @@ class EmailStep extends React.Component {
EmailStep.propTypes = {
intl: intlShape,
onNextStep: PropTypes.func,
onRegistrationError: PropTypes.func,
waiting: PropTypes.bool
};

View file

@ -23,6 +23,7 @@ class JoinFlow extends React.Component {
super(props);
bindAll(this, [
'handleAdvanceStep',
'handleRegistrationError',
'handlePrepareToRegister',
'handleRegistrationResponse',
'handleSubmitRegistration'
@ -34,6 +35,14 @@ class JoinFlow extends React.Component {
waiting: false
};
}
handleRegistrationError (message) {
if (!message) {
message = this.props.intl.formatMessage({
id: 'registration.generalError'
});
}
this.setState({registrationError: message});
}
handlePrepareToRegister (newFormData) {
newFormData = newFormData || {};
const newState = {
@ -143,6 +152,7 @@ class JoinFlow extends React.Component {
<EmailStep
waiting={this.state.waiting}
onNextStep={this.handlePrepareToRegister}
onRegistrationError={this.handleRegistrationError}
/>
<WelcomeStep
email={this.state.formData.email}

View file

@ -187,6 +187,7 @@
"registration.selectCountry": "select country",
"registration.studentPersonalStepDescription": "This information will not appear on the Scratch website.",
"registration.showPassword": "Show password",
"registration.troubleReload": "Scratch is having trouble finishing registration. Try reloading the page or try again in another browser.",
"registration.usernameStepDescription": "Fill in the following forms to request an account. The approval process may take up to one day.",
"registration.usernameStepDescriptionNonEducator": "Create projects, share ideas, make friends. Its free!",
"registration.usernameStepRealName": "Please do not use any portion of your real name in your username.",

View file

@ -50,6 +50,7 @@ describe('EmailStep test', () => {
expect(emailInputWrapper.props().onSetRef).toEqual(formikWrapper.instance().handleSetEmailRef);
expect(emailInputWrapper.props().validate).toEqual(formikWrapper.instance().validateEmail);
});
test('props sent to FormikCheckbox for subscribe', () => {
const wrapper = shallowWithIntl(<EmailStep />);
// Dive to get past the intl wrapper
@ -63,6 +64,7 @@ describe('EmailStep test', () => {
expect(checkboxWrapper.first().props().label).toEqual('registration.receiveEmails');
expect(checkboxWrapper.first().props().name).toEqual('subscribe');
});
test('handleValidSubmit passes formData to next step', () => {
const formikBag = {
setSubmitting: jest.fn()
@ -82,6 +84,7 @@ describe('EmailStep test', () => {
expect(formikBag.setSubmitting).toHaveBeenCalledWith(false);
expect(global.grecaptcha.execute).toHaveBeenCalled();
});
test('captchaSolved sets token and goes to next step', () => {
const props = {
onNextStep: jest.fn()
@ -116,6 +119,38 @@ describe('EmailStep test', () => {
}));
expect(formikBag.setSubmitting).toHaveBeenCalledWith(true);
});
test('onCaptchaError calls error function with correct message', () => {
const props = {
onRegistrationError: jest.fn()
};
const wrapper = shallowWithIntl(
<EmailStep
{...props}
/>);
const formikWrapper = wrapper.dive();
formikWrapper.instance().onCaptchaError();
expect(props.onRegistrationError).toHaveBeenCalledWith('registation.troubleReload');
});
test('Captcha load error calls error function', () => {
const props = {
onRegistrationError: jest.fn()
};
// Set this to null to force an error.
global.grecaptcha = null;
const wrapper = shallowWithIntl(
<EmailStep
{...props}
/>);
const formikWrapper = wrapper.dive();
formikWrapper.instance().onCaptchaLoad();
expect(props.onRegistrationError).toHaveBeenCalledWith('registation.troubleReload');
});
test('validateEmail test email empty', () => {
const wrapper = shallowWithIntl(
<EmailStep />);
@ -123,6 +158,7 @@ describe('EmailStep test', () => {
const val = formikWrapper.instance().validateEmail('');
expect(val).toBe('general.required');
});
test('validateEmail test email null', () => {
const wrapper = shallowWithIntl(
<EmailStep />);
@ -130,6 +166,7 @@ describe('EmailStep test', () => {
const val = formikWrapper.instance().validateEmail(null);
expect(val).toBe('general.required');
});
test('validateEmail test email undefined', () => {
const wrapper = shallowWithIntl(
<EmailStep />);

View file

@ -126,6 +126,19 @@ describe('JoinFlow', () => {
expect(joinFlowInstance.props.refreshSession).not.toHaveBeenCalled();
expect(joinFlowInstance.state.registrationError).toBe('registration.generalError (400)');
});
test('handleRegistrationError with no message ', () => {
const joinFlowInstance = getJoinFlowWrapper().instance();
joinFlowInstance.setState({});
joinFlowInstance.handleRegistrationError();
expect(joinFlowInstance.state.registrationError).toBe('registration.generalError');
});
test('handleRegistrationError with message ', () => {
const joinFlowInstance = getJoinFlowWrapper().instance();
joinFlowInstance.setState({});
joinFlowInstance.handleRegistrationError('my message');
expect(joinFlowInstance.state.registrationError).toBe('my message');
});
test('handleAdvanceStep', () => {
const joinFlowInstance = getJoinFlowWrapper().instance();