diff --git a/.env.development b/.env.development
index 7b22f46a..bf47dde9 100644
--- a/.env.development
+++ b/.env.development
@@ -36,3 +36,4 @@ ZENDESK_KEY=''
ZENDESK_LOGO_URL=''
APP_ID=''
MFE_CONFIG_API_URL=''
+SHOW_CONFIGURABLE_EDX_FIELDS='true'
diff --git a/src/common-components/RedirectLogistration.jsx b/src/common-components/RedirectLogistration.jsx
index 419c3b0c..ece5f778 100644
--- a/src/common-components/RedirectLogistration.jsx
+++ b/src/common-components/RedirectLogistration.jsx
@@ -24,10 +24,9 @@ function RedirectLogistration(props) {
finalRedirectUrl = redirectUrl;
}
+ // Redirect to Progressive Profiling after successful registration
if (redirectToWelcomePage) {
setCookie('van-504-returning-user', true);
- // use this component to redirect WelcomePage after successful registration
- // return ;
const registrationResult = { redirectUrl: finalRedirectUrl, success };
return (
{
case THIRD_PARTY_AUTH_CONTEXT.SUCCESS:
return {
...state,
- extendedProfile: action.payload.fieldDescriptions.extendedProfile,
+ extendedProfile: action.payload.fieldDescriptions.extended_profile,
fieldDescriptions: action.payload.fieldDescriptions.fields,
optionalFields: action.payload.optionalFields,
thirdPartyAuthContext: action.payload.thirdPartyAuthContext,
diff --git a/src/common-components/tests/Logistration.test.jsx b/src/common-components/tests/Logistration.test.jsx
index 786d7f4d..fb2a6bff 100644
--- a/src/common-components/tests/Logistration.test.jsx
+++ b/src/common-components/tests/Logistration.test.jsx
@@ -10,6 +10,7 @@ import { MemoryRouter } from 'react-router-dom';
import configureStore from 'redux-mock-store';
import { COMPLETE_STATE, LOGIN_PAGE } from '../../data/constants';
+import { backupRegistrationForm } from '../../register/data/actions';
import { RenderInstitutionButton } from '../InstitutionLogistration';
import Logistration from '../Logistration';
@@ -184,4 +185,27 @@ describe('Logistration', () => {
DISABLE_ENTERPRISE_LOGIN: '',
});
});
+
+ it('should fire action to backup registration form on tab click', () => {
+ store = mockStore({
+ login: {
+ loginResult: { success: false, redirectUrl: '' },
+ },
+ register: {
+ registrationResult: { success: false, redirectUrl: '' },
+ registrationError: {},
+ },
+ commonComponents: {
+ thirdPartyAuthContext: {
+ providers: [],
+ secondaryProviders: [],
+ },
+ },
+ });
+
+ store.dispatch = jest.fn(store.dispatch);
+ const logistration = mount(reduxWrapper());
+ logistration.find('a[data-rb-event-key="/login"]').simulate('click');
+ expect(store.dispatch).toHaveBeenCalledWith(backupRegistrationForm());
+ });
});
diff --git a/src/field-renderer/FieldRenderer.jsx b/src/field-renderer/FieldRenderer.jsx
index 34d3b18f..561b35d0 100644
--- a/src/field-renderer/FieldRenderer.jsx
+++ b/src/field-renderer/FieldRenderer.jsx
@@ -7,7 +7,7 @@ import PropTypes from 'prop-types';
const FormFieldRenderer = (props) => {
let formField = null;
const {
- errorMessage, fieldData, onChangeHandler, isRequired, value,
+ className, errorMessage, fieldData, onChangeHandler, isRequired, value,
} = props;
const handleFocus = (e) => {
@@ -26,6 +26,7 @@ const FormFieldRenderer = (props) => {
formField = (
{
formField = (
{
formField = (
{
formField = (
{
return formField;
};
FormFieldRenderer.defaultProps = {
+ className: '',
value: '',
handleBlur: null,
handleFocus: null,
@@ -132,6 +137,7 @@ FormFieldRenderer.defaultProps = {
};
FormFieldRenderer.propTypes = {
+ className: PropTypes.string,
fieldData: PropTypes.shape({
type: PropTypes.string,
label: PropTypes.string,
@@ -142,7 +148,10 @@ FormFieldRenderer.propTypes = {
handleFocus: PropTypes.func,
errorMessage: PropTypes.string,
isRequired: PropTypes.bool,
- value: PropTypes.string,
+ value: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.bool,
+ ]),
};
export default FormFieldRenderer;
diff --git a/src/register/ConfigurableRegistrationForm.jsx b/src/register/ConfigurableRegistrationForm.jsx
index fa7c7427..788d817e 100644
--- a/src/register/ConfigurableRegistrationForm.jsx
+++ b/src/register/ConfigurableRegistrationForm.jsx
@@ -44,6 +44,7 @@ const ConfigurableRegistrationForm = (props) => {
const flags = {
showConfigurableRegistrationFields: getConfig().ENABLE_DYNAMIC_REGISTRATION_FIELDS,
showConfigurableEdxFields: getConfig().SHOW_CONFIGURABLE_EDX_FIELDS,
+ showMarketingEmailOptInCheckbox: getConfig().MARKETING_EMAILS_OPT_IN,
};
useEffect(() => {
@@ -160,6 +161,25 @@ const ConfigurableRegistrationForm = (props) => {
);
}
+ if (flags.showMarketingEmailOptInCheckbox) {
+ formFieldDescriptions.push(
+
+
+ ,
+ );
+ }
+
if (flags.showConfigurableEdxFields || showTermsOfServiceAndHonorCode) {
formFieldDescriptions.push(
@@ -191,6 +211,7 @@ ConfigurableRegistrationForm.propTypes = {
countryCode: PropTypes.string,
}),
honor_code: PropTypes.bool,
+ marketingEmailsOptIn: PropTypes.bool,
}).isRequired,
intl: intlShape.isRequired,
setFieldErrors: PropTypes.func.isRequired,
diff --git a/src/register/RegistrationPage.jsx b/src/register/RegistrationPage.jsx
index c6ec4ea4..efa8f64e 100644
--- a/src/register/RegistrationPage.jsx
+++ b/src/register/RegistrationPage.jsx
@@ -80,6 +80,7 @@ const RegistrationPage = (props) => {
const flags = {
showConfigurableEdxFields: getConfig().SHOW_CONFIGURABLE_EDX_FIELDS,
showConfigurableRegistrationFields: getConfig().ENABLE_DYNAMIC_REGISTRATION_FIELDS,
+ showMarketingEmailOptInCheckbox: getConfig().MARKETING_EMAILS_OPT_IN,
};
const [formFields, setFormFields] = useState({ ...backedUpFormData.formFields });
@@ -240,7 +241,7 @@ const RegistrationPage = (props) => {
case 'username':
if (!value || value.length <= 1 || value.length > 30) {
fieldError = intl.formatMessage(messages['username.validation.message']);
- } else if (!value.match(/^[a-zA-Z\d_-]*$/i)) {
+ } else if (!value.match(/^[a-zA-Z0-9_-]*$/i)) {
fieldError = intl.formatMessage(messages['username.format.validation.message']);
} else if (shouldValidateFromBackend) {
validateFromBackend(payload);
@@ -402,7 +403,7 @@ const RegistrationPage = (props) => {
payload.social_auth_provider = currentProvider;
}
- const { focusedFieldError, countryFieldCode } = focusedField ? (
+ const { fieldError: focusedFieldError, countryFieldCode } = focusedField ? (
validateInput(
focusedField,
(focusedField in fieldDescriptions || focusedField === 'country') ? (
@@ -419,17 +420,19 @@ const RegistrationPage = (props) => {
return;
}
- payload.extendedProfile = [];
Object.keys(configurableFormFields).forEach((fieldName) => {
- if (props.extendedProfile.includes(fieldName)) {
- payload.extendedProfile.push({ fieldName, fieldValue: configurableFormFields[fieldName] });
- } else if (fieldName === 'country') {
+ if (fieldName === 'country') {
payload[fieldName] = focusedField === 'country' ? countryFieldCode : configurableFormFields[fieldName].countryCode;
} else {
payload[fieldName] = configurableFormFields[fieldName];
}
});
+ // Don't send the marketing email opt-in value if the flag is turned off
+ if (!flags.showMarketingEmailOptInCheckbox) {
+ delete payload.marketingEmailsOptIn;
+ }
+
payload = snakeCaseObject(payload);
payload.totalRegistrationTime = totalRegistrationTime;
@@ -521,17 +524,6 @@ const RegistrationPage = (props) => {
floatingLabel={intl.formatMessage(messages['registration.password.label'])}
/>
)}
- {getConfig().MARKETING_EMAILS_OPT_IN
- && (
-
- {intl.formatMessage(messages['registration.opt.in.label'], { siteName: getConfig().SITE_NAME })}
-
- )}
{
registrationError: {},
registrationResult: {},
registrationFormData: {
- configurableFormFields: {},
+ configurableFormFields: {
+ marketingEmailsOptIn: true,
+ },
formFields: {
- name: '', email: '', username: '', password: '', marketingEmailsOptIn: true,
+ name: '', email: '', username: '', password: '',
},
emailSuggestion: {
suggestion: '', type: '',
diff --git a/src/register/registrationFields/CountryField.jsx b/src/register/registrationFields/CountryField.jsx
index ce8a7a29..e310d2f7 100644
--- a/src/register/registrationFields/CountryField.jsx
+++ b/src/register/registrationFields/CountryField.jsx
@@ -20,7 +20,7 @@ const CountryField = (props) => {
const [displayValue, setDisplayValue] = useState('');
const [trailingIcon, setTrailingIcon] = useState(null);
- const onBlurHandler = (event, itemClicked = false) => {
+ const onBlurHandler = (event, itemClicked = false, countryName = '') => {
const { name } = event.target;
const relatedName = event.relatedTarget ? event.relatedTarget.name : '';
// For a better user experience, do not validate when focus out from 'country' field
@@ -28,7 +28,7 @@ const CountryField = (props) => {
if ((relatedName === 'countryItem' || relatedName === 'countryExpand') && name === 'country') {
return;
}
- const countryValue = itemClicked ? event.target.value : displayValue;
+ const countryValue = itemClicked ? countryName : displayValue;
if (props.onBlurHandler) {
props.onBlurHandler({ target: { name: 'country', value: countryValue } });
}
@@ -53,7 +53,7 @@ const CountryField = (props) => {
className="dropdown-item data-hj-suppress"
value={countryName}
key={country[COUNTRY_CODE_KEY]}
- onClick={(event) => onBlurHandler(event, true)}
+ onClick={(event) => onBlurHandler(event, true, countryName)}
>
{countryName.length > 30 ? countryName.substring(0, 30).concat('...') : countryName}
diff --git a/src/register/registrationFields/EmailField.jsx b/src/register/registrationFields/EmailField.jsx
index 243d5234..6ca744eb 100644
--- a/src/register/registrationFields/EmailField.jsx
+++ b/src/register/registrationFields/EmailField.jsx
@@ -34,7 +34,7 @@ const EmailField = (props) => {
);
}
return (
-
+
{intl.formatMessage(messages['did.you.mean.alert.text'])}:{' '}
{
mergeConfig({
@@ -37,15 +41,16 @@ describe('RegistrationPage', () => {
TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com',
USER_SURVEY_COOKIE_NAME: process.env.USER_SURVEY_COOKIE_NAME,
REGISTER_CONVERSION_COOKIE_NAME: process.env.REGISTER_CONVERSION_COOKIE_NAME,
- SHOW_CONFIGURABLE_EDX_FIELDS: true,
});
let props = {};
let store = {};
const registrationFormData = {
- configurableFormFields: {},
+ configurableFormFields: {
+ marketingEmailsOptIn: true,
+ },
formFields: {
- name: '', email: '', username: '', password: '', marketingEmailsOptIn: true,
+ name: '', email: '', username: '', password: '',
},
emailSuggestion: {
suggestion: '', type: '',
@@ -74,6 +79,7 @@ describe('RegistrationPage', () => {
register: {
registrationResult: { success: false, redirectUrl: '' },
registrationError: {},
+ registrationFormData,
},
commonComponents: {
thirdPartyAuthApiStatus: null,
@@ -103,20 +109,24 @@ describe('RegistrationPage', () => {
jest.clearAllMocks();
});
- const populateRequiredFields = (registerPage, payload, isThirdPartyAuth = false) => {
- registerPage.find('input#name').simulate('change', { target: { value: payload.name, name: 'name' } });
- registerPage.find('input#username').simulate('change', { target: { value: payload.username, name: 'username' } });
- registerPage.find('input#email').simulate('change', { target: { value: payload.email, name: 'email' } });
+ const populateRequiredFields = (registrationPage, payload, isThirdPartyAuth = false) => {
+ registrationPage.find('input#name').simulate('change', { target: { value: payload.name, name: 'name' } });
+ registrationPage.find('input#username').simulate('change', { target: { value: payload.username, name: 'username' } });
+ registrationPage.find('input#email').simulate('change', { target: { value: payload.email, name: 'email' } });
- registerPage.find('input#country').simulate('change', { target: { value: payload.country, name: 'country' } });
- registerPage.find('input#country').simulate('blur', { target: { value: payload.country, name: 'country' } });
+ registrationPage.find('input#country').simulate('change', { target: { value: payload.country, name: 'country' } });
+ registrationPage.find('input#country').simulate('blur', { target: { value: payload.country, name: 'country' } });
if (!isThirdPartyAuth) {
- registerPage.find('input#password').simulate('change', { target: { value: payload.password, name: 'password' } });
+ registrationPage.find('input#password').simulate('change', { target: { value: payload.password, name: 'password' } });
}
};
describe('Test Registration Page', () => {
+ mergeConfig({
+ SHOW_CONFIGURABLE_EDX_FIELDS: true,
+ });
+
const emptyFieldValidation = {
name: 'Enter your full name',
username: 'Username must be between 2 and 30 characters',
@@ -153,15 +163,13 @@ describe('RegistrationPage', () => {
country: 'Pakistan',
honor_code: true,
totalRegistrationTime: 0,
- marketing_emails_opt_in: true,
next: '/course/demo-course-url',
- extended_profile: [],
};
store.dispatch = jest.fn(store.dispatch);
- const registerPage = mount(reduxWrapper());
- populateRequiredFields(registerPage, payload);
- registerPage.find('button.btn-brand').simulate('click');
+ const registrationPage = mount(reduxWrapper());
+ populateRequiredFields(registrationPage, payload);
+ registrationPage.find('button.btn-brand').simulate('click');
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload, country: 'PK' }));
});
@@ -176,8 +184,6 @@ describe('RegistrationPage', () => {
honor_code: true,
social_auth_provider: ssoProvider.name,
totalRegistrationTime: 0,
- marketing_emails_opt_in: true,
- extended_profile: [],
};
store = mockStore({
@@ -191,13 +197,42 @@ describe('RegistrationPage', () => {
},
});
store.dispatch = jest.fn(store.dispatch);
- const registerPage = mount(reduxWrapper());
+ const registrationPage = mount(reduxWrapper());
- populateRequiredFields(registerPage, formPayload, true);
- registerPage.find('button.btn-brand').simulate('click');
+ populateRequiredFields(registrationPage, formPayload, true);
+ registrationPage.find('button.btn-brand').simulate('click');
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...formPayload, country: 'PK' }));
});
+ it('should submit form with marketing email opt in value', () => {
+ mergeConfig({
+ MARKETING_EMAILS_OPT_IN: 'true',
+ });
+
+ jest.spyOn(global.Date, 'now').mockImplementation(() => 0);
+
+ const payload = {
+ name: 'John Doe',
+ username: 'john_doe',
+ email: 'john.doe@gmail.com',
+ password: 'password1',
+ country: 'Pakistan',
+ honor_code: true,
+ totalRegistrationTime: 0,
+ marketing_emails_opt_in: true,
+ };
+
+ store.dispatch = jest.fn(store.dispatch);
+ const registrationPage = mount(reduxWrapper());
+ populateRequiredFields(registrationPage, payload);
+ registrationPage.find('button.btn-brand').simulate('click');
+ expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload, country: 'PK' }));
+
+ mergeConfig({
+ MARKETING_EMAILS_OPT_IN: '',
+ });
+ });
+
it('should not dispatch registerNewUser on empty form Submission', () => {
store.dispatch = jest.fn(store.dispatch);
@@ -235,7 +270,15 @@ describe('RegistrationPage', () => {
registrationPage.find('div[feedback-for="password"]').text(),
).toContain('Password criteria has not been met');
- registrationPage.find('input#password').simulate('blur', { target: { value: 'invalid-email', name: 'email' } });
+ registrationPage.find('input#username').simulate('blur', { target: { value: 'u$ername', name: 'username' } });
+ expect(
+ registrationPage.find('div[feedback-for="username"]').text(),
+ ).toContain(
+ 'Usernames can only contain letters (A-Z, a-z), numerals (0-9),'
+ + ' underscores (_), and hyphens (-). Usernames cannot contain spaces',
+ );
+
+ registrationPage.find('input#email').simulate('blur', { target: { value: 'ab', name: 'email' } });
expect(
registrationPage.find('div[feedback-for="email"]').text(),
).toEqual('Enter a valid email address');
@@ -264,18 +307,49 @@ describe('RegistrationPage', () => {
store.dispatch = jest.fn(store.dispatch);
const registrationPage = mount(reduxWrapper());
- // Enter a valid username so that frontend validations are passed
- registrationPage.find('input#username').simulate('change', { target: { value: 'test', name: 'username' } });
- registrationPage.find('input#username').simulate('blur');
+ // Enter a valid name so that frontend validations are passed
+ registrationPage.find('input#name').simulate('change', { target: { value: 'John Doe', name: 'name' } });
+ registrationPage.find('input#name').simulate('blur');
+ expect(store.dispatch).toHaveBeenCalledWith(fetchRealtimeValidations({
+ form_field_key: 'name', email: '', name: 'John Doe', username: '', password: '',
+ }));
- const formPayload = {
- form_field_key: 'username',
- email: '',
- name: '',
- username: 'test',
- password: '',
- };
- expect(store.dispatch).toHaveBeenCalledWith(fetchRealtimeValidations(formPayload));
+ // Enter a valid username so that frontend validations are passed
+ registrationPage.find('input#username').simulate('change', { target: { value: 'john', name: 'username' } });
+ registrationPage.find('input#username').simulate('blur');
+ expect(store.dispatch).toHaveBeenCalledWith(fetchRealtimeValidations({
+ form_field_key: 'username', email: '', name: 'John Doe', username: 'john', password: '',
+ }));
+ });
+
+ it('should run validations for focused field on form submission', () => {
+ const registrationPage = mount(reduxWrapper());
+ registrationPage.find('input#country').simulate('focus');
+ registrationPage.find('button.btn-brand').simulate('click');
+
+ expect(registrationPage.find('div[feedback-for="country"]').text()).toEqual(emptyFieldValidation.country);
+ });
+
+ it('should give email suggestions for common service provider domain typos', () => {
+ store.dispatch = jest.fn(store.dispatch);
+ const registrationPage = mount(reduxWrapper());
+
+ registrationPage.find('input#email').simulate('change', { target: { value: 'john@yopmail.com', name: 'email' } });
+ registrationPage.find('input#email').simulate('blur');
+
+ expect(registrationPage.find('#email-warning').text()).toEqual('Did you mean: john@hotmail.com?');
+ });
+
+ it('should give error for common top level domain mistakes', () => {
+ store.dispatch = jest.fn(store.dispatch);
+ const registrationPage = mount(reduxWrapper());
+
+ registrationPage.find('input#email').simulate(
+ 'change', { target: { value: 'john@gmail.mistake', name: 'email' } },
+ );
+ registrationPage.find('input#email').simulate('blur');
+
+ expect(registrationPage.find('.alert-danger').text()).toEqual('Did you mean john@gmail.com?');
});
it('should update props with validations returned by registration api', () => {
@@ -356,8 +430,8 @@ describe('RegistrationPage', () => {
const expectedMessage = `${'You\'ve successfully signed into Apple! We just need a little more information before '
+ 'you start learning with '}${ getConfig().SITE_NAME }.`;
- const registerPage = mount(reduxWrapper());
- expect(registerPage.find('#tpa-alert').find('p').text()).toEqual(expectedMessage);
+ const registrationPage = mount(reduxWrapper());
+ expect(registrationPage.find('#tpa-alert').find('p').text()).toEqual(expectedMessage);
});
it('should match internal server error message', () => {
@@ -426,8 +500,8 @@ describe('RegistrationPage', () => {
MARKETING_EMAILS_OPT_IN: 'true',
});
- const registerPage = mount(reduxWrapper());
- expect(registerPage.find('div.opt-checkbox').length).toEqual(1);
+ const registrationPage = mount(reduxWrapper());
+ expect(registrationPage.find('div.opt-checkbox').length).toEqual(1);
mergeConfig({
MARKETING_EMAILS_OPT_IN: '',
@@ -524,8 +598,8 @@ describe('RegistrationPage', () => {
},
});
- const registerPage = mount(reduxWrapper());
- expect(registerPage.find('button.username-suggestion').length).toEqual(3);
+ const registrationPage = mount(reduxWrapper());
+ expect(registrationPage.find('button.username-suggestion').length).toEqual(3);
});
it('should show username suggestions when full name is populated', () => {
@@ -541,10 +615,10 @@ describe('RegistrationPage', () => {
},
});
- const registerPage = mount(reduxWrapper());
- registerPage.find('input#name').simulate('change', { target: { value: 'test name', name: 'name' } });
+ const registrationPage = mount(reduxWrapper());
+ registrationPage.find('input#name').simulate('change', { target: { value: 'test name', name: 'name' } });
- expect(registerPage.find('button.username-suggestion').length).toEqual(3);
+ expect(registrationPage.find('button.username-suggestion').length).toEqual(3);
});
it('should clear username suggestions when close icon is clicked', () => {
@@ -561,9 +635,9 @@ describe('RegistrationPage', () => {
});
store.dispatch = jest.fn(store.dispatch);
- const registerPage = mount(reduxWrapper());
- registerPage.find('input#name').simulate('change', { target: { value: 'test name', name: 'name' } });
- registerPage.find('button.suggested-username-close-button').at(0).simulate('click');
+ const registrationPage = mount(reduxWrapper());
+ registrationPage.find('input#name').simulate('change', { target: { value: 'test name', name: 'name' } });
+ registrationPage.find('button.suggested-username-close-button').at(0).simulate('click');
expect(store.dispatch).toHaveBeenCalledWith(clearUsernameSuggestions());
});
@@ -657,6 +731,35 @@ describe('RegistrationPage', () => {
expect(window.location.href).toBe(dashboardUrl);
});
+ it('should redirect to progressive profiling page if optional fields are configured', () => {
+ mergeConfig({
+ ENABLE_PROGRESSIVE_PROFILING: true,
+ });
+
+ store = mockStore({
+ ...initialState,
+ register: {
+ ...initialState.register,
+ registrationResult: {
+ success: true,
+ },
+ },
+ commonComponents: {
+ optionalFields: {
+ country: { name: 'country', error_message: false },
+ },
+ },
+ });
+
+ const progressiveProfilingPage = mount(reduxWrapper(
+
+
+ ,
+ ));
+ progressiveProfilingPage.update();
+ expect(history.location.pathname).toEqual(WELCOME_PAGE);
+ });
+
// ******** test hinted third party auth ********
it('should render tpa button for tpa_hint id matching one of the primary providers', () => {
@@ -676,9 +779,9 @@ describe('RegistrationPage', () => {
window.location = { href: getConfig().BASE_URL.concat('/login'), search: `?next=/dashboard&tpa_hint=${ssoProvider.id}` };
ssoProvider.iconImage = null;
- const registerPage = mount(reduxWrapper());
- expect(registerPage.find(`button#${ssoProvider.id}`).find('span').text()).toEqual(ssoProvider.name);
- expect(registerPage.find(`button#${ssoProvider.id}`).hasClass(`btn-tpa btn-${ssoProvider.id}`)).toEqual(true);
+ const registrationPage = mount(reduxWrapper());
+ expect(registrationPage.find(`button#${ssoProvider.id}`).find('span').text()).toEqual(ssoProvider.name);
+ expect(registrationPage.find(`button#${ssoProvider.id}`).hasClass(`btn-tpa btn-${ssoProvider.id}`)).toEqual(true);
});
it('should render tpa button for tpa_hint id matching one of the secondary providers', () => {
@@ -721,8 +824,8 @@ describe('RegistrationPage', () => {
window.location = { href: getConfig().BASE_URL.concat('/login'), search: '?next=/dashboard&tpa_hint=invalid' };
ssoProvider.iconImage = null;
- const registerPage = mount(reduxWrapper());
- expect(registerPage.find(`button#${ssoProvider.id}`).find('span#provider-name').text()).toEqual(expectedMessage);
+ const registrationPage = mount(reduxWrapper());
+ expect(registrationPage.find(`button#${ssoProvider.id}`).find('span#provider-name').text()).toEqual(expectedMessage);
});
// ******** miscellaneous tests ********
@@ -742,8 +845,8 @@ describe('RegistrationPage', () => {
});
it('should render cookie banner', () => {
- const registerPage = mount(reduxWrapper());
- expect(registerPage.find()).toBeTruthy();
+ const registrationPage = mount(reduxWrapper());
+ expect(registrationPage.find()).toBeTruthy();
});
it('should send page event when register page is rendered', () => {
@@ -769,10 +872,12 @@ describe('RegistrationPage', () => {
},
},
});
+ store.dispatch = jest.fn(store.dispatch);
const registrationPage = mount(reduxWrapper()).find('RegistrationPage');
expect(registrationPage.find('input#email').props().value).toEqual('test@example.com');
expect(registrationPage.find('input#username').props().value).toEqual('test');
+ expect(store.dispatch).toHaveBeenCalledWith(setUserPipelineDataLoaded(true));
});
it('should update state from country code present in redux store', () => {
@@ -854,9 +959,9 @@ describe('RegistrationPage', () => {
},
},
});
- const registerPage = mount(reduxWrapper());
- expect(registerPage.find('#profession').exists()).toBeTruthy();
- expect(registerPage.find('#tos').exists()).toBeTruthy();
+ const registrationPage = mount(reduxWrapper());
+ expect(registrationPage.find('#profession').exists()).toBeTruthy();
+ expect(registrationPage.find('#tos').exists()).toBeTruthy();
});
it('should submit form with fields returned by backend in payload', () => {
@@ -879,48 +984,36 @@ describe('RegistrationPage', () => {
password: 'password1',
country: 'Pakistan',
honor_code: true,
+ profession: 'Engineer',
totalRegistrationTime: 0,
- marketing_emails_opt_in: true,
- extended_profile: [{ field_name: 'profession', field_value: 'Engineer' }],
};
store.dispatch = jest.fn(store.dispatch);
- const registerPage = mount(reduxWrapper());
+ const registrationPage = mount(reduxWrapper());
- populateRequiredFields(registerPage, payload);
- registerPage.find('input#profession').simulate('change', { target: { value: 'Engineer', name: 'profession' } });
- registerPage.find('button.btn-brand').simulate('click');
+ populateRequiredFields(registrationPage, payload);
+ registrationPage.find('input#profession').simulate('change', { target: { value: 'Engineer', name: 'profession' } });
+ registrationPage.find('button.btn-brand').simulate('click');
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload, country: 'PK' }));
});
- it('should show error message for fields returned by backend', () => {
+ it('should show error messages for required fields on empty form submission', () => {
+ const professionError = 'Enter your profession';
+ const countryError = 'Select your country or region of residence';
+ const confirmEmailError = 'Enter your email';
+
store = mockStore({
...initialState,
commonComponents: {
...initialState.commonComponents,
fieldDescriptions: {
profession: {
- name: 'profession', type: 'text', label: 'Profession', error_message: 'Enter profession',
+ name: 'profession', type: 'text', label: 'Profession', error_message: professionError,
},
- },
- },
- });
-
- const registrationPage = mount(reduxWrapper());
- registrationPage.find('button.btn-brand').simulate('click');
-
- expect(registrationPage.find('#profession-error').last().text()).toEqual('Enter profession');
- });
-
- it('should show error message for confirm email field returned by backend', () => {
- store = mockStore({
- ...initialState,
- commonComponents: {
- ...initialState.commonComponents,
- fieldDescriptions: {
confirm_email: {
- name: 'confirm_email', type: 'text', label: 'Confirm Email', error_message: 'Enter your confirm email',
+ name: 'confirm_email', type: 'text', label: 'Confirm Email', error_message: confirmEmailError,
},
+ country: { name: 'country' },
},
},
});
@@ -928,7 +1021,9 @@ describe('RegistrationPage', () => {
const registrationPage = mount(reduxWrapper());
registrationPage.find('button.btn-brand').simulate('click');
- expect(registrationPage.find('#confirm_email-error').last().text()).toEqual('Enter your confirm email');
+ expect(registrationPage.find('#profession-error').last().text()).toEqual(professionError);
+ expect(registrationPage.find('div[feedback-for="country"]').text()).toEqual(countryError);
+ expect(registrationPage.find('#confirm_email-error').last().text()).toEqual(confirmEmailError);
});
it('should show error if email and confirm email fields do not match', () => {
@@ -949,5 +1044,26 @@ describe('RegistrationPage', () => {
expect(registrationPage.find('div#confirm_email-error').text()).toEqual('The email addresses do not match.');
});
+
+ it('should run validations for configurable focused field on form submission', () => {
+ const professionError = 'Enter your profession';
+ store = mockStore({
+ ...initialState,
+ commonComponents: {
+ ...initialState.commonComponents,
+ fieldDescriptions: {
+ profession: {
+ name: 'profession', type: 'text', label: 'Profession', error_message: professionError,
+ },
+ },
+ },
+ });
+
+ const registrationPage = mount(reduxWrapper());
+ registrationPage.find('input#profession').simulate('focus', { target: { value: '', name: 'profession' } });
+ registrationPage.find('button.btn-brand').simulate('click');
+
+ expect(registrationPage.find('#profession-error').last().text()).toEqual(professionError);
+ });
});
});