mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-26 17:16:11 -05:00
357 lines
15 KiB
JavaScript
357 lines
15 KiB
JavaScript
const React = require('react');
|
|
const {shallowWithIntl} = require('../../helpers/intl-helpers.jsx');
|
|
const {mountWithIntl} = require('../../helpers/intl-helpers.jsx');
|
|
const JoinFlowStep = require('../../../src/components/join-flow/join-flow-step.jsx');
|
|
const FormikInput = require('../../../src/components/formik-forms/formik-input.jsx');
|
|
const FormikCheckbox = require('../../../src/components/formik-forms/formik-checkbox.jsx');
|
|
|
|
const requestSuccessResponse = {
|
|
requestSucceeded: true,
|
|
valid: false,
|
|
errMsgId: 'registration.validationEmailInvalid'
|
|
};
|
|
const requestFailureResponse = {
|
|
requestSucceeded: false,
|
|
valid: false,
|
|
errMsgId: 'general.error'
|
|
};
|
|
// mockedValidateEmailRemotely will return a promise resolving with remoteRequestResponse.
|
|
// Using remoteRequestResponse, rather than using requestSuccessResponse directly,
|
|
// lets us change where remoteRequestResponse points later, without actually changing
|
|
// mockedValidateEmailRemotely.
|
|
let remoteRequestResponse = requestSuccessResponse;
|
|
let mockedValidateEmailRemotely = jest.fn(() => (
|
|
/* eslint-disable no-undef */
|
|
Promise.resolve(remoteRequestResponse)
|
|
/* eslint-enable no-undef */
|
|
));
|
|
|
|
jest.mock('../../../src/lib/validate.js', () => (
|
|
{
|
|
...(jest.requireActual('../../../src/lib/validate.js')),
|
|
validateEmailRemotely: mockedValidateEmailRemotely
|
|
}
|
|
));
|
|
|
|
// must come after validation mocks, so validate.js will be mocked before it is required
|
|
const EmailStep = require('../../../src/components/join-flow/email-step.jsx');
|
|
|
|
describe('EmailStep test', () => {
|
|
const defaultProps = () => ({
|
|
sendAnalytics: jest.fn()
|
|
});
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
test('send correct props to formik', () => {
|
|
const intlWrapper = shallowWithIntl(<EmailStep
|
|
{...defaultProps()}
|
|
/>);
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
expect(emailStepWrapper.props().initialValues.subscribe).toBe(false);
|
|
expect(emailStepWrapper.props().initialValues.email).toBe('');
|
|
expect(emailStepWrapper.props().validateOnBlur).toBe(false);
|
|
expect(emailStepWrapper.props().validateOnChange).toBe(false);
|
|
expect(emailStepWrapper.props().validate).toBe(emailStepWrapper.instance().validateForm);
|
|
expect(emailStepWrapper.props().onSubmit).toBe(emailStepWrapper.instance().handleValidSubmit);
|
|
});
|
|
|
|
test('props sent to JoinFlowStep', () => {
|
|
const intlWrapper = shallowWithIntl(<EmailStep
|
|
{...defaultProps()}
|
|
/>);
|
|
// Dive to get past the intl wrapper
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
// Dive to get past the anonymous component.
|
|
const joinFlowWrapper = emailStepWrapper.dive().find(JoinFlowStep);
|
|
expect(joinFlowWrapper).toHaveLength(1);
|
|
expect(joinFlowWrapper.props().footerContent.props.id).toBe('registration.acceptTermsOfUse');
|
|
expect(joinFlowWrapper.props().headerImgSrc).toBe('/images/join-flow/email-header.png');
|
|
expect(joinFlowWrapper.props().innerClassName).toBe('join-flow-inner-email-step');
|
|
expect(joinFlowWrapper.props().nextButton).toBe('registration.createAccount');
|
|
expect(joinFlowWrapper.props().title).toBe('registration.emailStepTitle');
|
|
expect(joinFlowWrapper.props().titleClassName).toBe('join-flow-email-title');
|
|
expect(joinFlowWrapper.props().waiting).toBe(true);
|
|
});
|
|
|
|
test('props sent to FormikInput for email', () => {
|
|
const intlWrapper = shallowWithIntl(<EmailStep
|
|
{...defaultProps()}
|
|
/>);
|
|
// Dive to get past the intl wrapper
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
// Dive to get past the anonymous component.
|
|
const joinFlowWrapper = emailStepWrapper.dive().find(JoinFlowStep);
|
|
expect(joinFlowWrapper).toHaveLength(1);
|
|
const emailInputWrapper = joinFlowWrapper.find(FormikInput).first();
|
|
expect(emailInputWrapper.props().id).toEqual('email');
|
|
expect(emailInputWrapper.props().error).toBeUndefined();
|
|
expect(emailInputWrapper.props().name).toEqual('email');
|
|
expect(emailInputWrapper.props().placeholder).toEqual('general.emailAddress');
|
|
expect(emailInputWrapper.props().validationClassName).toEqual('validation-full-width-input');
|
|
expect(emailInputWrapper.props().onSetRef).toEqual(emailStepWrapper.instance().handleSetEmailRef);
|
|
expect(emailInputWrapper.props().validate).toEqual(emailStepWrapper.instance().validateEmail);
|
|
});
|
|
|
|
test('props sent to FormikCheckbox for subscribe', () => {
|
|
const intlWrapper = shallowWithIntl(<EmailStep
|
|
{...defaultProps()}
|
|
/>);
|
|
|
|
// Dive to get past the intl wrapper
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
// Dive to get past the anonymous component.
|
|
const joinFlowWrapper = emailStepWrapper.dive().find(JoinFlowStep);
|
|
expect(joinFlowWrapper).toHaveLength(1);
|
|
const checkboxWrapper = joinFlowWrapper.find(FormikCheckbox).first();
|
|
expect(checkboxWrapper).toHaveLength(1);
|
|
expect(checkboxWrapper.first().props().id).toEqual('subscribeCheckbox');
|
|
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()
|
|
};
|
|
|
|
const captchaRef = {
|
|
executeCaptcha: jest.fn()
|
|
};
|
|
const formData = {item1: 'thing', item2: 'otherthing'};
|
|
const intlWrapper = shallowWithIntl(
|
|
<EmailStep
|
|
{...defaultProps()}
|
|
/>);
|
|
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
emailStepWrapper.instance().setCaptchaRef(captchaRef);
|
|
emailStepWrapper.instance().handleValidSubmit(formData, formikBag);
|
|
|
|
expect(formikBag.setSubmitting).toHaveBeenCalledWith(false);
|
|
expect(captchaRef.executeCaptcha).toHaveBeenCalled();
|
|
});
|
|
|
|
test('captchaSolved sets token and goes to next step', () => {
|
|
const props = {
|
|
onNextStep: jest.fn()
|
|
};
|
|
const formikBag = {
|
|
setSubmitting: jest.fn()
|
|
};
|
|
const captchaRef = {
|
|
executeCaptcha: jest.fn()
|
|
};
|
|
const formData = {item1: 'thing', item2: 'otherthing'};
|
|
const intlWrapper = shallowWithIntl(
|
|
<EmailStep
|
|
{...defaultProps()}
|
|
{...props}
|
|
/>);
|
|
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
// Call these to setup captcha.
|
|
emailStepWrapper.instance().setCaptchaRef(captchaRef); // to setup catpcha state
|
|
emailStepWrapper.instance().handleValidSubmit(formData, formikBag);
|
|
|
|
const captchaToken = 'abcd';
|
|
emailStepWrapper.instance().handleCaptchaSolved(captchaToken);
|
|
// Make sure captchaSolved calls onNextStep with formData that has
|
|
// a captcha token and left everything else in the object in place.
|
|
expect(props.onNextStep).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
'item1': formData.item1,
|
|
'item2': formData.item2,
|
|
'g-recaptcha-response': captchaToken
|
|
}));
|
|
expect(formikBag.setSubmitting).toHaveBeenCalledWith(true);
|
|
});
|
|
|
|
test('Component logs analytics', () => {
|
|
const sendAnalyticsFn = jest.fn();
|
|
const onCaptchaError = jest.fn();
|
|
mountWithIntl(
|
|
<EmailStep
|
|
sendAnalytics={sendAnalyticsFn}
|
|
onCaptchaError={onCaptchaError}
|
|
/>);
|
|
expect(sendAnalyticsFn).toHaveBeenCalledWith('join-email');
|
|
});
|
|
|
|
test('validateEmail test email empty', () => {
|
|
const intlWrapper = shallowWithIntl(
|
|
<EmailStep
|
|
{...defaultProps()}
|
|
/>);
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
const val = emailStepWrapper.instance().validateEmail('');
|
|
expect(val).toBe('general.required');
|
|
});
|
|
|
|
test('validateEmail test email null', () => {
|
|
const intlWrapper = shallowWithIntl(
|
|
<EmailStep
|
|
{...defaultProps()}
|
|
/>);
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
const val = emailStepWrapper.instance().validateEmail(null);
|
|
expect(val).toBe('general.required');
|
|
});
|
|
|
|
test('validateEmail test email undefined', () => {
|
|
const intlWrapper = shallowWithIntl(
|
|
<EmailStep
|
|
{...defaultProps()}
|
|
/>);
|
|
const emailStepWrapper = intlWrapper.dive();
|
|
const val = emailStepWrapper.instance().validateEmail();
|
|
expect(val).toBe('general.required');
|
|
});
|
|
});
|
|
|
|
describe('validateEmailRemotelyWithCache test with successful requests', () => {
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
test('validateEmailRemotelyWithCache calls validate.validateEmailRemotely', done => {
|
|
const intlWrapper = shallowWithIntl(
|
|
<EmailStep />
|
|
);
|
|
const instance = intlWrapper.dive().instance();
|
|
|
|
instance.validateEmailRemotelyWithCache('some-email@some-domain.com')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalled();
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('registration.validationEmailInvalid');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('validateEmailRemotelyWithCache, called twice with different data, makes two remote requests', done => {
|
|
const intlWrapper = shallowWithIntl(
|
|
<EmailStep />
|
|
);
|
|
const instance = intlWrapper.dive().instance();
|
|
|
|
instance.validateEmailRemotelyWithCache('some-email@some-domain.com')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalledTimes(1);
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('registration.validationEmailInvalid');
|
|
})
|
|
.then(() => {
|
|
// make the same request a second time
|
|
instance.validateEmailRemotelyWithCache('different-email@some-domain.org')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalledTimes(2);
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('registration.validationEmailInvalid');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
test('validateEmailRemotelyWithCache, called twice with same data, only makes one remote request', done => {
|
|
const intlWrapper = shallowWithIntl(
|
|
<EmailStep />
|
|
);
|
|
const instance = intlWrapper.dive().instance();
|
|
|
|
instance.validateEmailRemotelyWithCache('some-email@some-domain.com')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalledTimes(1);
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('registration.validationEmailInvalid');
|
|
})
|
|
.then(() => {
|
|
// make the same request a second time
|
|
instance.validateEmailRemotelyWithCache('some-email@some-domain.com')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalledTimes(1);
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('registration.validationEmailInvalid');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
describe('validateEmailRemotelyWithCache test with failing requests', () => {
|
|
|
|
beforeEach(() => {
|
|
// needs to be wrapped inside beforeEach, because if not, it gets run as this
|
|
// test file is loaded, and goes into effect before any of the earlier tests run!
|
|
remoteRequestResponse = requestFailureResponse;
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
test('validateEmailRemotelyWithCache calls validate.validateEmailRemotely', done => {
|
|
const wrapper = shallowWithIntl(
|
|
<EmailStep />);
|
|
const instance = wrapper.dive().instance();
|
|
|
|
instance.validateEmailRemotelyWithCache('some-email@some-domain.com')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalled();
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('general.error');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('validateEmailRemotelyWithCache, called twice with different data, makes two remote requests', done => {
|
|
const wrapper = shallowWithIntl(
|
|
<EmailStep />
|
|
);
|
|
const instance = wrapper.dive().instance();
|
|
|
|
instance.validateEmailRemotelyWithCache('some-email@some-domain.com')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalledTimes(1);
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('general.error');
|
|
})
|
|
.then(() => {
|
|
// make the same request a second time
|
|
instance.validateEmailRemotelyWithCache('different-email@some-domain.org')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalledTimes(2);
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('general.error');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
test('validateEmailRemotelyWithCache, called 2x w/same data, makes 2 requests, since 1st not stored', done => {
|
|
const wrapper = shallowWithIntl(
|
|
<EmailStep />
|
|
);
|
|
const instance = wrapper.dive().instance();
|
|
|
|
instance.validateEmailRemotelyWithCache('some-email@some-domain.com')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalledTimes(1);
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('general.error');
|
|
})
|
|
.then(() => {
|
|
// make the same request a second time
|
|
instance.validateEmailRemotelyWithCache('some-email@some-domain.com')
|
|
.then(response => {
|
|
expect(mockedValidateEmailRemotely).toHaveBeenCalledTimes(2);
|
|
expect(response.valid).toBe(false);
|
|
expect(response.errMsgId).toBe('general.error');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|