mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 07:38:07 -05:00
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:
commit
5f3d6506c0
5 changed files with 69 additions and 3 deletions
|
@ -56,7 +56,11 @@ class EmailStep extends React.Component {
|
||||||
this.emailInput = emailInputRef;
|
this.emailInput = emailInputRef;
|
||||||
}
|
}
|
||||||
onCaptchaError () {
|
onCaptchaError () {
|
||||||
// TODO send user to error step once we have one.
|
this.props.onRegistrationError(
|
||||||
|
this.props.intl.formatMessage({
|
||||||
|
id: 'registation.troubleReload'
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
onCaptchaLoad () {
|
onCaptchaLoad () {
|
||||||
this.setState({captchaIsLoading: false});
|
this.setState({captchaIsLoading: false});
|
||||||
|
@ -64,9 +68,9 @@ class EmailStep extends React.Component {
|
||||||
if (!this.grecaptcha) {
|
if (!this.grecaptcha) {
|
||||||
// According to the reCaptcha documentation, this callback shouldn't get
|
// According to the reCaptcha documentation, this callback shouldn't get
|
||||||
// called unless window.grecaptcha exists. This is just here to be extra defensive.
|
// 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,
|
this.widgetId = this.grecaptcha.render(this.captchaRef,
|
||||||
{
|
{
|
||||||
callback: this.captchaSolved,
|
callback: this.captchaSolved,
|
||||||
|
@ -208,6 +212,7 @@ class EmailStep extends React.Component {
|
||||||
EmailStep.propTypes = {
|
EmailStep.propTypes = {
|
||||||
intl: intlShape,
|
intl: intlShape,
|
||||||
onNextStep: PropTypes.func,
|
onNextStep: PropTypes.func,
|
||||||
|
onRegistrationError: PropTypes.func,
|
||||||
waiting: PropTypes.bool
|
waiting: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ class JoinFlow extends React.Component {
|
||||||
super(props);
|
super(props);
|
||||||
bindAll(this, [
|
bindAll(this, [
|
||||||
'handleAdvanceStep',
|
'handleAdvanceStep',
|
||||||
|
'handleRegistrationError',
|
||||||
'handlePrepareToRegister',
|
'handlePrepareToRegister',
|
||||||
'handleRegistrationResponse',
|
'handleRegistrationResponse',
|
||||||
'handleSubmitRegistration'
|
'handleSubmitRegistration'
|
||||||
|
@ -34,6 +35,14 @@ class JoinFlow extends React.Component {
|
||||||
waiting: false
|
waiting: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
handleRegistrationError (message) {
|
||||||
|
if (!message) {
|
||||||
|
message = this.props.intl.formatMessage({
|
||||||
|
id: 'registration.generalError'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setState({registrationError: message});
|
||||||
|
}
|
||||||
handlePrepareToRegister (newFormData) {
|
handlePrepareToRegister (newFormData) {
|
||||||
newFormData = newFormData || {};
|
newFormData = newFormData || {};
|
||||||
const newState = {
|
const newState = {
|
||||||
|
@ -143,6 +152,7 @@ class JoinFlow extends React.Component {
|
||||||
<EmailStep
|
<EmailStep
|
||||||
waiting={this.state.waiting}
|
waiting={this.state.waiting}
|
||||||
onNextStep={this.handlePrepareToRegister}
|
onNextStep={this.handlePrepareToRegister}
|
||||||
|
onRegistrationError={this.handleRegistrationError}
|
||||||
/>
|
/>
|
||||||
<WelcomeStep
|
<WelcomeStep
|
||||||
email={this.state.formData.email}
|
email={this.state.formData.email}
|
||||||
|
|
|
@ -187,6 +187,7 @@
|
||||||
"registration.selectCountry": "select country",
|
"registration.selectCountry": "select country",
|
||||||
"registration.studentPersonalStepDescription": "This information will not appear on the Scratch website.",
|
"registration.studentPersonalStepDescription": "This information will not appear on the Scratch website.",
|
||||||
"registration.showPassword": "Show password",
|
"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.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. It’s free!",
|
"registration.usernameStepDescriptionNonEducator": "Create projects, share ideas, make friends. It’s free!",
|
||||||
"registration.usernameStepRealName": "Please do not use any portion of your real name in your username.",
|
"registration.usernameStepRealName": "Please do not use any portion of your real name in your username.",
|
||||||
|
|
|
@ -50,6 +50,7 @@ describe('EmailStep test', () => {
|
||||||
expect(emailInputWrapper.props().onSetRef).toEqual(formikWrapper.instance().handleSetEmailRef);
|
expect(emailInputWrapper.props().onSetRef).toEqual(formikWrapper.instance().handleSetEmailRef);
|
||||||
expect(emailInputWrapper.props().validate).toEqual(formikWrapper.instance().validateEmail);
|
expect(emailInputWrapper.props().validate).toEqual(formikWrapper.instance().validateEmail);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('props sent to FormikCheckbox for subscribe', () => {
|
test('props sent to FormikCheckbox for subscribe', () => {
|
||||||
const wrapper = shallowWithIntl(<EmailStep />);
|
const wrapper = shallowWithIntl(<EmailStep />);
|
||||||
// Dive to get past the intl wrapper
|
// 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().label).toEqual('registration.receiveEmails');
|
||||||
expect(checkboxWrapper.first().props().name).toEqual('subscribe');
|
expect(checkboxWrapper.first().props().name).toEqual('subscribe');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('handleValidSubmit passes formData to next step', () => {
|
test('handleValidSubmit passes formData to next step', () => {
|
||||||
const formikBag = {
|
const formikBag = {
|
||||||
setSubmitting: jest.fn()
|
setSubmitting: jest.fn()
|
||||||
|
@ -82,6 +84,7 @@ describe('EmailStep test', () => {
|
||||||
expect(formikBag.setSubmitting).toHaveBeenCalledWith(false);
|
expect(formikBag.setSubmitting).toHaveBeenCalledWith(false);
|
||||||
expect(global.grecaptcha.execute).toHaveBeenCalled();
|
expect(global.grecaptcha.execute).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('captchaSolved sets token and goes to next step', () => {
|
test('captchaSolved sets token and goes to next step', () => {
|
||||||
const props = {
|
const props = {
|
||||||
onNextStep: jest.fn()
|
onNextStep: jest.fn()
|
||||||
|
@ -116,6 +119,38 @@ describe('EmailStep test', () => {
|
||||||
}));
|
}));
|
||||||
expect(formikBag.setSubmitting).toHaveBeenCalledWith(true);
|
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', () => {
|
test('validateEmail test email empty', () => {
|
||||||
const wrapper = shallowWithIntl(
|
const wrapper = shallowWithIntl(
|
||||||
<EmailStep />);
|
<EmailStep />);
|
||||||
|
@ -123,6 +158,7 @@ describe('EmailStep test', () => {
|
||||||
const val = formikWrapper.instance().validateEmail('');
|
const val = formikWrapper.instance().validateEmail('');
|
||||||
expect(val).toBe('general.required');
|
expect(val).toBe('general.required');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('validateEmail test email null', () => {
|
test('validateEmail test email null', () => {
|
||||||
const wrapper = shallowWithIntl(
|
const wrapper = shallowWithIntl(
|
||||||
<EmailStep />);
|
<EmailStep />);
|
||||||
|
@ -130,6 +166,7 @@ describe('EmailStep test', () => {
|
||||||
const val = formikWrapper.instance().validateEmail(null);
|
const val = formikWrapper.instance().validateEmail(null);
|
||||||
expect(val).toBe('general.required');
|
expect(val).toBe('general.required');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('validateEmail test email undefined', () => {
|
test('validateEmail test email undefined', () => {
|
||||||
const wrapper = shallowWithIntl(
|
const wrapper = shallowWithIntl(
|
||||||
<EmailStep />);
|
<EmailStep />);
|
||||||
|
|
|
@ -126,6 +126,19 @@ describe('JoinFlow', () => {
|
||||||
expect(joinFlowInstance.props.refreshSession).not.toHaveBeenCalled();
|
expect(joinFlowInstance.props.refreshSession).not.toHaveBeenCalled();
|
||||||
expect(joinFlowInstance.state.registrationError).toBe('registration.generalError (400)');
|
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', () => {
|
test('handleAdvanceStep', () => {
|
||||||
const joinFlowInstance = getJoinFlowWrapper().instance();
|
const joinFlowInstance = getJoinFlowWrapper().instance();
|
||||||
|
|
Loading…
Reference in a new issue