Skip to content

Commit 80e940f

Browse files
ahtesham-quraishsyedsajjadkazmii
authored andcommitted
fix: embedded registration form (#1026)
Description: Adding embedded registration form VAN-1574
1 parent 37e811d commit 80e940f

File tree

8 files changed

+1116
-169
lines changed

8 files changed

+1116
-169
lines changed

src/MainApp.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { ForgotPasswordPage } from './forgot-password';
2424
import Logistration from './logistration/Logistration';
2525
import { ProgressiveProfiling } from './progressive-profiling';
2626
import { RecommendationsPage } from './recommendations';
27-
import { RegistrationPage } from './register';
27+
import { EmbeddableRegistrationPage } from './register';
2828
import { ResetPasswordPage } from './reset-password';
2929

3030
import './index.scss';
@@ -41,7 +41,7 @@ const MainApp = () => (
4141
<Route path="/" element={<Navigate replace to={updatePathWithQueryParams(REGISTER_PAGE)} />} />
4242
<Route
4343
path={REGISTER_EMBEDDED_PAGE}
44-
element={<EmbeddedRegistrationRoute><RegistrationPage /></EmbeddedRegistrationRoute>}
44+
element={<EmbeddedRegistrationRoute><EmbeddableRegistrationPage /></EmbeddedRegistrationRoute>}
4545
/>
4646
<Route
4747
path={LOGIN_PAGE}

src/common-components/RedirectLogistration.jsx

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
33
import { Navigate } from 'react-router-dom';
44

55
import {
6-
AUTHN_PROGRESSIVE_PROFILING, RECOMMENDATIONS, REDIRECT,
6+
AUTHN_PROGRESSIVE_PROFILING, RECOMMENDATIONS,
77
} from '../data/constants';
88
import { setCookie } from '../data/utils';
99

@@ -18,8 +18,6 @@ const RedirectLogistration = (props) => {
1818
redirectToRecommendationsPage,
1919
educationLevel,
2020
userId,
21-
registrationEmbedded,
22-
host,
2321
} = props;
2422
let finalRedirectUrl = '';
2523

@@ -39,13 +37,6 @@ const RedirectLogistration = (props) => {
3937
// TODO: Do we still need this cookie?
4038
setCookie('van-504-returning-user', true);
4139

42-
if (registrationEmbedded) {
43-
window.parent.postMessage({
44-
action: REDIRECT,
45-
redirectUrl: getConfig().POST_REGISTRATION_REDIRECT_URL,
46-
}, host);
47-
return null;
48-
}
4940
const registrationResult = { redirectUrl: finalRedirectUrl, success };
5041
return (
5142
<Navigate
@@ -92,8 +83,6 @@ RedirectLogistration.defaultProps = {
9283
optionalFields: {},
9384
redirectToRecommendationsPage: false,
9485
userId: null,
95-
registrationEmbedded: false,
96-
host: '',
9786
};
9887

9988
RedirectLogistration.propTypes = {
@@ -106,8 +95,6 @@ RedirectLogistration.propTypes = {
10695
optionalFields: PropTypes.shape({}),
10796
redirectToRecommendationsPage: PropTypes.bool,
10897
userId: PropTypes.number,
109-
registrationEmbedded: PropTypes.bool,
110-
host: PropTypes.string,
11198
};
11299

113100
export default RedirectLogistration;

src/register/RegistrationPage.jsx

Lines changed: 18 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { getConfig } from '@edx/frontend-platform';
77
import { sendPageEvent, sendTrackEvent } from '@edx/frontend-platform/analytics';
88
import { useIntl } from '@edx/frontend-platform/i18n';
99
import { Form, Spinner, StatefulButton } from '@edx/paragon';
10-
import classNames from 'classnames';
1110
import PropTypes from 'prop-types';
1211
import { Helmet } from 'react-helmet';
1312
import Skeleton from 'react-loading-skeleton';
@@ -37,7 +36,7 @@ import {
3736
COMPLETE_STATE, PENDING_STATE, REGISTER_PAGE,
3837
} from '../data/constants';
3938
import {
40-
getAllPossibleQueryParams, getTpaHint, getTpaProvider, isHostAvailableInQueryParams, setCookie,
39+
getAllPossibleQueryParams, getTpaHint, getTpaProvider, setCookie,
4140
} from '../data/utils';
4241

4342
/**
@@ -47,7 +46,6 @@ const RegistrationPage = (props) => {
4746
const { formatMessage } = useIntl();
4847
const dispatch = useDispatch();
4948

50-
const registrationEmbedded = isHostAvailableInQueryParams();
5149
const platformName = getConfig().SITE_NAME;
5250
const flags = {
5351
showConfigurableEdxFields: getConfig().SHOW_CONFIGURABLE_EDX_FIELDS,
@@ -99,13 +97,6 @@ const RegistrationPage = (props) => {
9997
const [errors, setErrors] = useState({ ...backedUpFormData.errors });
10098
const [errorCode, setErrorCode] = useState({ type: '', count: 0 });
10199
const [formStartTime, setFormStartTime] = useState(null);
102-
// temporary error state for embedded experience because we don't want to show errors on blur
103-
const [temporaryErrors, setTemporaryErrors] = useState({ ...backedUpFormData.errors });
104-
105-
const { cta, host } = queryParams;
106-
const buttonLabel = cta
107-
? formatMessage(messages['create.account.cta.button'], { label: cta })
108-
: formatMessage(messages['create.account.for.free.button']);
109100

110101
/**
111102
* Set the userPipelineDetails data in formFields for only first time
@@ -156,13 +147,9 @@ const RegistrationPage = (props) => {
156147

157148
useEffect(() => {
158149
if (backendValidations) {
159-
if (registrationEmbedded) {
160-
setTemporaryErrors(prevErrors => ({ ...prevErrors, ...backendValidations }));
161-
} else {
162-
setErrors(prevErrors => ({ ...prevErrors, ...backendValidations }));
163-
}
150+
setErrors(prevErrors => ({ ...prevErrors, ...backendValidations }));
164151
}
165-
}, [backendValidations, registrationEmbedded]);
152+
}, [backendValidations]);
166153

167154
useEffect(() => {
168155
if (registrationErrorCode) {
@@ -206,23 +193,10 @@ const RegistrationPage = (props) => {
206193
};
207194

208195
const handleErrorChange = (fieldName, error) => {
209-
if (registrationEmbedded) {
210-
setTemporaryErrors(prevErrors => ({
211-
...prevErrors,
212-
[fieldName]: error,
213-
}));
214-
if (error === '' && errors[fieldName] !== '') {
215-
setErrors(prevErrors => ({
216-
...prevErrors,
217-
[fieldName]: error,
218-
}));
219-
}
220-
} else {
221-
setErrors(prevErrors => ({
222-
...prevErrors,
223-
[fieldName]: error,
224-
}));
225-
}
196+
setErrors(prevErrors => ({
197+
...prevErrors,
198+
[fieldName]: error,
199+
}));
226200
};
227201

228202
const registerUser = () => {
@@ -237,7 +211,7 @@ const RegistrationPage = (props) => {
237211
// Validating form data before submitting
238212
const { isValid, fieldErrors } = isFormValid(
239213
payload,
240-
registrationEmbedded ? temporaryErrors : errors,
214+
errors,
241215
configurableFormFields,
242216
fieldDescriptions,
243217
formatMessage,
@@ -288,13 +262,11 @@ const RegistrationPage = (props) => {
288262
<title>{formatMessage(messages['register.page.title'], { siteName: getConfig().SITE_NAME })}</title>
289263
</Helmet>
290264
<RedirectLogistration
291-
host={host}
292265
authenticatedUser={registrationResult.authenticatedUser}
293266
success={registrationResult.success}
294267
redirectUrl={registrationResult.redirectUrl}
295268
finishAuthUrl={finishAuthUrl}
296269
optionalFields={optionalFields}
297-
registrationEmbedded={registrationEmbedded}
298270
redirectToProgressiveProfilingPage={
299271
getConfig().ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN && !!Object.keys(optionalFields.fields).length
300272
}
@@ -304,12 +276,7 @@ const RegistrationPage = (props) => {
304276
<Spinner animation="border" variant="primary" id="tpa-spinner" />
305277
</div>
306278
) : (
307-
<div
308-
className={classNames(
309-
'mw-xs mt-3',
310-
{ 'w-100 m-auto pt-4 main-content': registrationEmbedded },
311-
)}
312-
>
279+
<div className="mw-xs mt-3">
313280
<ThirdPartyAuthAlert
314281
currentProvider={currentProvider}
315282
platformName={platformName}
@@ -365,7 +332,7 @@ const RegistrationPage = (props) => {
365332
email={formFields.email}
366333
fieldErrors={errors}
367334
formFields={configurableFormFields}
368-
setFieldErrors={registrationEmbedded ? setTemporaryErrors : setErrors}
335+
setFieldErrors={setErrors}
369336
setFormFields={setConfigurableFormFields}
370337
autoSubmitRegisterForm={autoSubmitRegForm}
371338
fieldDescriptions={fieldDescriptions}
@@ -378,21 +345,19 @@ const RegistrationPage = (props) => {
378345
className="register-button mt-4 mb-4"
379346
state={submitState}
380347
labels={{
381-
default: buttonLabel,
348+
default: formatMessage(messages['create.account.for.free.button']),
382349
pending: '',
383350
}}
384351
onClick={handleSubmit}
385352
onMouseDown={(e) => e.preventDefault()}
386353
/>
387-
{!registrationEmbedded && (
388-
<ThirdPartyAuth
389-
currentProvider={currentProvider}
390-
providers={providers}
391-
secondaryProviders={secondaryProviders}
392-
handleInstitutionLogin={handleInstitutionLogin}
393-
thirdPartyAuthApiStatus={thirdPartyAuthApiStatus}
394-
/>
395-
)}
354+
<ThirdPartyAuth
355+
currentProvider={currentProvider}
356+
providers={providers}
357+
secondaryProviders={secondaryProviders}
358+
handleInstitutionLogin={handleInstitutionLogin}
359+
thirdPartyAuthApiStatus={thirdPartyAuthApiStatus}
360+
/>
396361
</Form>
397362
</div>
398363
)}

src/register/RegistrationPage.test.jsx

Lines changed: 0 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -503,14 +503,6 @@ describe('RegistrationPage', () => {
503503
expect(registrationPage.find('.institutions__heading').text()).toEqual('Register with institution/campus credentials');
504504
});
505505

506-
it('should show button label based on cta query params value', () => {
507-
const buttonLabel = 'Register';
508-
delete window.location;
509-
window.location = { href: getConfig().BASE_URL, search: `?cta=${buttonLabel}` };
510-
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
511-
expect(registrationPage.find('button[type="submit"] span').first().text()).toEqual(buttonLabel);
512-
});
513-
514506
it('should not display password field when current provider is present', () => {
515507
store = mockStore({
516508
...initialState,
@@ -892,96 +884,6 @@ describe('RegistrationPage', () => {
892884
expect(registrationPage.find('.email-suggestion-alert-warning').first().text()).toEqual('[email protected]');
893885
});
894886

895-
// ********* Embedded experience tests *********/
896-
897-
it('should call the postMessage API when embedded variant is rendered', () => {
898-
getLocale.mockImplementation(() => ('en-us'));
899-
mergeConfig({
900-
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: true,
901-
});
902-
903-
window.parent.postMessage = jest.fn();
904-
905-
delete window.location;
906-
window.location = { href: getConfig().BASE_URL.concat(AUTHN_PROGRESSIVE_PROFILING), search: '?host=http://localhost/host-website' };
907-
908-
store = mockStore({
909-
...initialState,
910-
register: {
911-
...initialState.register,
912-
registrationResult: {
913-
success: true,
914-
},
915-
},
916-
commonComponents: {
917-
...initialState.commonComponents,
918-
optionalFields: {
919-
extended_profile: {},
920-
fields: {
921-
level_of_education: { name: 'level_of_education', error_message: false },
922-
},
923-
},
924-
},
925-
});
926-
const progressiveProfilingPage = mount(reduxWrapper(
927-
<IntlRegistrationPage {...props} />,
928-
));
929-
progressiveProfilingPage.update();
930-
expect(window.parent.postMessage).toHaveBeenCalledTimes(2);
931-
});
932-
933-
it('should not display validations error on blur event when embedded variant is rendered', () => {
934-
delete window.location;
935-
window.location = { href: getConfig().BASE_URL.concat(REGISTER_PAGE), search: '?host=http://localhost/host-website' };
936-
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
937-
938-
registrationPage.find('input#username').simulate('blur', { target: { value: '', name: 'username' } });
939-
expect(registrationPage.find('div[feedback-for="username"]').exists()).toBeFalsy();
940-
941-
registrationPage.find('input[name="country"]').simulate('blur', { target: { value: '', name: 'country' } });
942-
expect(registrationPage.find('div[feedback-for="country"]').exists()).toBeFalsy();
943-
});
944-
945-
it('should set errors in temporary state when validations are returned by registration api', () => {
946-
delete window.location;
947-
window.location = { href: getConfig().BASE_URL.concat(REGISTER_PAGE), search: '?host=http://localhost/host-website' };
948-
949-
const usernameError = 'It looks like this username is already taken';
950-
const emailError = 'This email is already associated with an existing or previous account';
951-
store = mockStore({
952-
...initialState,
953-
register: {
954-
...initialState.register,
955-
registrationError: {
956-
username: [{ userMessage: usernameError }],
957-
email: [{ userMessage: emailError }],
958-
},
959-
},
960-
});
961-
const registrationPage = mount(routerWrapper(reduxWrapper(
962-
<IntlRegistrationPage {...props} />),
963-
)).find('RegistrationPage');
964-
965-
expect(registrationPage.find('div[feedback-for="username"]').exists()).toBeFalsy();
966-
expect(registrationPage.find('div[feedback-for="email"]').exists()).toBeFalsy();
967-
});
968-
969-
it('should clear error on focus for embedded experience also', () => {
970-
delete window.location;
971-
window.location = {
972-
href: getConfig().BASE_URL.concat(REGISTER_PAGE),
973-
search: '?host=http://localhost/host-website',
974-
};
975-
976-
const registrationPage = mount(routerWrapper(reduxWrapper(<IntlRegistrationPage {...props} />)));
977-
registrationPage.find('button.btn-brand').simulate('click');
978-
979-
expect(registrationPage.find('div[feedback-for="password"]').text()).toContain(emptyFieldValidation.password);
980-
981-
registrationPage.find('input#password').simulate('focus');
982-
expect(registrationPage.find('div[feedback-for="password"]').exists()).toBeFalsy();
983-
});
984-
985887
it('should show spinner instead of form while registering if autoSubmitRegForm is true', () => {
986888
jest.spyOn(global.Date, 'now').mockImplementation(() => 0);
987889
getLocale.mockImplementation(() => ('en-us'));

0 commit comments

Comments
 (0)