diff --git a/src/MainApp.jsx b/src/MainApp.jsx index 15ca8105..43171c62 100755 --- a/src/MainApp.jsx +++ b/src/MainApp.jsx @@ -32,7 +32,7 @@ const MainApp = () => ( diff --git a/src/common-components/RedirectLogistration.jsx b/src/common-components/RedirectLogistration.jsx index 824d8872..4c357cc6 100644 --- a/src/common-components/RedirectLogistration.jsx +++ b/src/common-components/RedirectLogistration.jsx @@ -10,7 +10,7 @@ import { setCookie } from '../data/utils'; function RedirectLogistration(props) { const { - finishAuthUrl, redirectUrl, redirectToWelcomePage, success, + finishAuthUrl, redirectUrl, redirectToWelcomePage, success, optionalFields, } = props; let finalRedirectUrl = ''; @@ -30,7 +30,16 @@ function RedirectLogistration(props) { // use this component to redirect WelcomePage after successful registration // return ; const registrationResult = { redirectUrl: finalRedirectUrl, success }; - return ; + return ( + + ); } window.location.href = finalRedirectUrl; @@ -43,6 +52,7 @@ RedirectLogistration.defaultProps = { success: false, redirectUrl: '', redirectToWelcomePage: false, + optionalFields: {}, }; RedirectLogistration.propTypes = { @@ -50,6 +60,7 @@ RedirectLogistration.propTypes = { success: PropTypes.bool, redirectUrl: PropTypes.string, redirectToWelcomePage: PropTypes.bool, + optionalFields: PropTypes.shape({}), }; export default RedirectLogistration; diff --git a/src/common-components/data/actions.js b/src/common-components/data/actions.js index 6eb655b5..c69d2559 100644 --- a/src/common-components/data/actions.js +++ b/src/common-components/data/actions.js @@ -12,9 +12,9 @@ export const getThirdPartyAuthContextBegin = () => ({ type: THIRD_PARTY_AUTH_CONTEXT.BEGIN, }); -export const getThirdPartyAuthContextSuccess = (fieldDescriptions, thirdPartyAuthContext) => ({ +export const getThirdPartyAuthContextSuccess = (fieldDescriptions, optionalFields, thirdPartyAuthContext) => ({ type: THIRD_PARTY_AUTH_CONTEXT.SUCCESS, - payload: { fieldDescriptions, thirdPartyAuthContext }, + payload: { fieldDescriptions, optionalFields, thirdPartyAuthContext }, }); export const getThirdPartyAuthContextFailure = () => ({ diff --git a/src/common-components/data/reducers.js b/src/common-components/data/reducers.js index 9cac42b2..eac34323 100644 --- a/src/common-components/data/reducers.js +++ b/src/common-components/data/reducers.js @@ -5,6 +5,7 @@ import { PENDING_STATE, COMPLETE_STATE } from '../../data/constants'; export const defaultState = { extendedProfile: [], fieldDescriptions: {}, + optionalFields: {}, thirdPartyAuthApiStatus: null, }; @@ -20,6 +21,7 @@ const reducer = (state = defaultState, action) => { ...state, extendedProfile: action.payload.fieldDescriptions.extendedProfile, fieldDescriptions: action.payload.fieldDescriptions.fields, + optionalFields: action.payload.optionalFields, thirdPartyAuthContext: action.payload.thirdPartyAuthContext, thirdPartyAuthApiStatus: COMPLETE_STATE, }; diff --git a/src/common-components/data/sagas.js b/src/common-components/data/sagas.js index 4c56845a..9b824c91 100644 --- a/src/common-components/data/sagas.js +++ b/src/common-components/data/sagas.js @@ -18,10 +18,12 @@ import { export function* fetchThirdPartyAuthContext(action) { try { yield put(getThirdPartyAuthContextBegin()); - const { fieldDescriptions, thirdPartyAuthContext } = yield call(getThirdPartyAuthContext, action.payload.urlParams); + const { fieldDescriptions, optionalFields, thirdPartyAuthContext } = yield call( + getThirdPartyAuthContext, action.payload.urlParams, + ); yield put(getThirdPartyAuthContextSuccess( - fieldDescriptions, thirdPartyAuthContext, + fieldDescriptions, optionalFields, thirdPartyAuthContext, )); } catch (e) { yield put(getThirdPartyAuthContextFailure()); diff --git a/src/common-components/data/selectors.js b/src/common-components/data/selectors.js index 393385e3..bfbef09f 100644 --- a/src/common-components/data/selectors.js +++ b/src/common-components/data/selectors.js @@ -18,3 +18,8 @@ export const extendedProfileSelector = createSelector( commonComponentsSelector, commonComponents => commonComponents.extendedProfile, ); + +export const optionalFieldsSelector = createSelector( + commonComponentsSelector, + commonComponents => commonComponents.optionalFields, +); diff --git a/src/common-components/data/service.js b/src/common-components/data/service.js index e083c871..4f41cc7f 100644 --- a/src/common-components/data/service.js +++ b/src/common-components/data/service.js @@ -19,6 +19,7 @@ export async function getThirdPartyAuthContext(urlParams) { }); return { fieldDescriptions: data.registration_fields || {}, + optionalFields: data.optional_fields || {}, // For backward compatibility with the API, once https://github.com/openedx/edx-platform/pull/30198 is merged // and deployed update it to use data.context_data thirdPartyAuthContext: camelCaseObject( diff --git a/src/common-components/data/tests/sagas.test.js b/src/common-components/data/tests/sagas.test.js index 1b40ce90..c63b1eb3 100644 --- a/src/common-components/data/tests/sagas.test.js +++ b/src/common-components/data/tests/sagas.test.js @@ -26,7 +26,11 @@ describe('fetchThirdPartyAuthContext', () => { it('should call service and dispatch success action', async () => { const getThirdPartyAuthContext = jest.spyOn(api, 'getThirdPartyAuthContext') - .mockImplementation(() => Promise.resolve({ thirdPartyAuthContext: data, fieldDescriptions: {} })); + .mockImplementation(() => Promise.resolve({ + thirdPartyAuthContext: data, + fieldDescriptions: {}, + optionalFields: {}, + })); const dispatched = []; await runSaga( @@ -38,7 +42,7 @@ describe('fetchThirdPartyAuthContext', () => { expect(getThirdPartyAuthContext).toHaveBeenCalledTimes(1); expect(dispatched).toEqual([ actions.getThirdPartyAuthContextBegin(), - actions.getThirdPartyAuthContextSuccess({}, data), + actions.getThirdPartyAuthContextSuccess({}, {}, data), ]); getThirdPartyAuthContext.mockClear(); }); diff --git a/src/register/RegistrationPage.jsx b/src/register/RegistrationPage.jsx index ee5fd44c..338e2a10 100644 --- a/src/register/RegistrationPage.jsx +++ b/src/register/RegistrationPage.jsx @@ -40,6 +40,7 @@ import { getThirdPartyAuthContext } from '../common-components/data/actions'; import { extendedProfileSelector, fieldDescriptionSelector, + optionalFieldsSelector, thirdPartyAuthContextSelector, } from '../common-components/data/selectors'; import EnterpriseSSO from '../common-components/EnterpriseSSO'; @@ -64,6 +65,7 @@ class RegistrationPage extends React.Component { // permanent part of Authn and remove extra code this.showDynamicRegistrationFields = getConfig().ENABLE_DYNAMIC_REGISTRATION_FIELDS; this.tpaHint = getTpaHint(); + this.isRegistered = true; this.state = { country: '', email: '', @@ -107,6 +109,7 @@ class RegistrationPage extends React.Component { if (this.tpaHint) { payload.tpa_hint = this.tpaHint; } + payload.is_registered = this.isRegistered; this.props.resetRegistrationForm(); this.props.getThirdPartyAuthContext(payload); this.getExperiments(); @@ -655,7 +658,14 @@ class RegistrationPage extends React.Component { success={this.props.registrationResult.success} redirectUrl={this.props.registrationResult.redirectUrl} finishAuthUrl={finishAuthUrl} - redirectToWelcomePage={getConfig().ENABLE_PROGRESSIVE_PROFILING} + optionalFields={this.props.optionalFields} + redirectToWelcomePage={ + // eslint-disable-next-line no-nested-ternary + getConfig().ENABLE_PROGRESSIVE_PROFILING + ? (getConfig().ENABLE_DYNAMIC_REGISTRATION_FIELDS + ? Object.keys(this.props.optionalFields).length !== 0 : true + ) : false + } />
{this.state.errorCode ? ( @@ -832,6 +842,7 @@ class RegistrationPage extends React.Component { RegistrationPage.defaultProps = { extendedProfile: [], fieldDescriptions: {}, + optionalFields: {}, registrationResult: null, registerNewUser: null, registrationErrorCode: null, @@ -853,6 +864,7 @@ RegistrationPage.defaultProps = { RegistrationPage.propTypes = { extendedProfile: PropTypes.arrayOf(PropTypes.string), fieldDescriptions: PropTypes.shape({}), + optionalFields: PropTypes.shape({}), intl: intlShape.isRequired, getThirdPartyAuthContext: PropTypes.func.isRequired, registerNewUser: PropTypes.func, @@ -907,6 +919,7 @@ const mapStateToProps = state => { statusCode: state.register.statusCode, usernameSuggestions: usernameSuggestionsSelector(state), fieldDescriptions: fieldDescriptionSelector(state), + optionalFields: optionalFieldsSelector(state), extendedProfile: extendedProfileSelector(state), }; }; diff --git a/src/register/tests/RegistrationPage.test.jsx b/src/register/tests/RegistrationPage.test.jsx index b223f02e..98ba5941 100644 --- a/src/register/tests/RegistrationPage.test.jsx +++ b/src/register/tests/RegistrationPage.test.jsx @@ -9,6 +9,7 @@ import CookiePolicyBanner from '@edx/frontend-component-cookie-policy-banner'; import { getConfig, mergeConfig } from '@edx/frontend-platform'; import * as analytics from '@edx/frontend-platform/analytics'; import { IntlProvider, injectIntl, configure } from '@edx/frontend-platform/i18n'; +import { MemoryRouter } from 'react-router-dom'; import { clearUsernameSuggestions, @@ -22,7 +23,7 @@ import { import RegistrationFailureMessage from '../RegistrationFailure'; import RegistrationPage from '../RegistrationPage'; -import { COMPLETE_STATE, PENDING_STATE } from '../../data/constants'; +import { COMPLETE_STATE, PENDING_STATE, WELCOME_PAGE } from '../../data/constants'; jest.mock('@edx/frontend-platform/analytics'); @@ -857,5 +858,63 @@ describe('RegistrationPage', () => { expect(registrationPage.find('#profession-error').last().text()).toEqual('Enter profession'); }); + + it('should redirect to dashboard if features flags are configured but no optional fields are configured', () => { + mergeConfig({ + ENABLE_PROGRESSIVE_PROFILING: true, + ENABLE_DYNAMIC_REGISTRATION_FIELDS: true, + }); + const dasboardUrl = 'http://test.com/testing-dashboard/'; + store = mockStore({ + ...initialState, + register: { + ...initialState.register, + registrationResult: { + success: true, + redirectUrl: dasboardUrl, + }, + commonComponents: { + optionalFields: {}, + }, + }, + }); + delete window.location; + window.location = { href: getConfig().BASE_URL }; + renderer.create(reduxWrapper()); + expect(window.location.href).toBe(dasboardUrl); + }); + + it('should redirect to welcome page when optional fields are configured with feature flags', () => { + mergeConfig({ + ENABLE_PROGRESSIVE_PROFILING: true, + ENABLE_DYNAMIC_REGISTRATION_FIELDS: true, + }); + store = mockStore({ + ...initialState, + commonComponents: { + optionalFields: { + country: { name: 'country', error_message: false }, + }, + }, + register: { + ...initialState.register, + registrationResult: { + success: true, + }, + + }, + }); + + delete window.location; + window.location = { href: getConfig().BASE_URL + WELCOME_PAGE }; + renderer.create(reduxWrapper( + + + + + , + )); + expect(window.location.href).toBe(getConfig().BASE_URL + WELCOME_PAGE); + }); }); }); diff --git a/src/welcome/ProgressiveProfiling.jsx b/src/welcome/ProgressiveProfiling.jsx index e641a4c4..ea5bcc7f 100644 --- a/src/welcome/ProgressiveProfiling.jsx +++ b/src/welcome/ProgressiveProfiling.jsx @@ -20,17 +20,16 @@ import { Form, StatefulButton, Hyperlink, - Spinner, } from '@edx/paragon'; import { Error } from '@edx/paragon/icons'; -import { getFieldData, saveUserProfile } from './data/actions'; +import { saveUserProfile } from './data/actions'; import { welcomePageSelector } from './data/selectors'; import messages from './messages'; import { RedirectLogistration } from '../common-components'; import { - DEFAULT_REDIRECT_URL, DEFAULT_STATE, FAILURE_STATE, COMPLETE_STATE, + DEFAULT_REDIRECT_URL, DEFAULT_STATE, FAILURE_STATE, } from '../data/constants'; import FormFieldRenderer from '../field-renderer'; import WelcomePageModal from './WelcomePageModal'; @@ -38,9 +37,10 @@ import BaseComponent from '../base-component'; const ProgressiveProfiling = (props) => { const { - extendedProfile, fieldDescriptions, formRenderState, intl, submitState, showError, + formRenderState, intl, submitState, showError, } = props; - + const optionalFields = props.location.state.optionalFields.fields; + const extendedProfile = props.location.state.optionalFields.extended_profile; const [ready, setReady] = useState(false); const [registrationResult, setRegistrationResult] = useState({ redirectUrl: '' }); const [values, setValues] = useState({}); @@ -52,7 +52,6 @@ const ProgressiveProfiling = (props) => { configureAuth(AxiosJwtAuthService, { loggingService: getLoggingService(), config: getConfig() }); ensureAuthenticatedUser(DASHBOARD_URL).then(() => { hydrateAuthenticatedUser().then(() => { - props.getFieldData(); setReady(true); }); }); @@ -108,8 +107,8 @@ const ProgressiveProfiling = (props) => { } }; - const formFields = Object.keys(fieldDescriptions).map((fieldName) => { - const fieldData = fieldDescriptions[fieldName]; + const formFields = Object.keys(optionalFields).map((fieldName) => { + const fieldData = optionalFields[fieldName]; return ( { ); }); - if (formRenderState === COMPLETE_STATE) { - return ( - <> - - - {intl.formatMessage(messages['progressive.profiling.page.title'], - { siteName: getConfig().SITE_NAME })} - - - - {props.shouldRedirect ? ( - - ) : null} -
-
-

{intl.formatMessage(messages['progressive.profiling.page.heading'])}

-
-
- {showError ? ( - - {intl.formatMessage(messages['welcome.page.error.heading'])} -

{intl.formatMessage(messages['welcome.page.error.message'])}

-
- ) : null} -
- {formFields} - - (sendTrackEvent('edx.bi.welcome.page.support.link.clicked'))} - > - {intl.formatMessage(messages['optional.fields.information.link'])} - - -
- e.preventDefault()} - /> - e.preventDefault()} - /> -
-
+ return ( + <> + + + {intl.formatMessage(messages['progressive.profiling.page.title'], + { siteName: getConfig().SITE_NAME })} + + + + {props.shouldRedirect ? ( + + ) : null} +
+
+

{intl.formatMessage(messages['progressive.profiling.page.heading'])}

- - - ); - } - return ; +
+ {showError ? ( + + {intl.formatMessage(messages['welcome.page.error.heading'])} +

{intl.formatMessage(messages['welcome.page.error.message'])}

+
+ ) : null} +
+ {formFields} + + (sendTrackEvent('edx.bi.welcome.page.support.link.clicked'))} + > + {intl.formatMessage(messages['optional.fields.information.link'])} + + +
+ e.preventDefault()} + /> + e.preventDefault()} + /> +
+
+
+
+ + ); }; ProgressiveProfiling.propTypes = { + // eslint-disable-next-line react/no-unused-prop-types extendedProfile: PropTypes.arrayOf(PropTypes.string), - fieldDescriptions: PropTypes.shape({}), + optionalFields: PropTypes.shape({}), formRenderState: PropTypes.string.isRequired, intl: intlShape.isRequired, location: PropTypes.shape({ state: PropTypes.object, }), - getFieldData: PropTypes.func.isRequired, saveUserProfile: PropTypes.func.isRequired, showError: PropTypes.bool, shouldRedirect: PropTypes.bool, @@ -212,7 +208,7 @@ ProgressiveProfiling.propTypes = { ProgressiveProfiling.defaultProps = { extendedProfile: [], - fieldDescriptions: {}, + optionalFields: {}, location: { state: {} }, shouldRedirect: false, showError: false, @@ -220,8 +216,6 @@ ProgressiveProfiling.defaultProps = { }; const mapStateToProps = state => ({ - extendedProfile: welcomePageSelector(state).extendedProfile, - fieldDescriptions: welcomePageSelector(state).fieldDescriptions, formRenderState: welcomePageSelector(state).formRenderState, shouldRedirect: welcomePageSelector(state).success, submitState: welcomePageSelector(state).submitState, @@ -232,6 +226,5 @@ export default connect( mapStateToProps, { saveUserProfile, - getFieldData, }, )(injectIntl(ProgressiveProfiling)); diff --git a/src/welcome/data/actions.js b/src/welcome/data/actions.js index 917cdf3a..6527c9d0 100644 --- a/src/welcome/data/actions.js +++ b/src/welcome/data/actions.js @@ -20,21 +20,3 @@ export const saveUserProfileSuccess = () => ({ export const saveUserProfileFailure = () => ({ type: SAVE_USER_PROFILE.FAILURE, }); - -// get field data from platform -export const getFieldData = () => ({ - type: GET_FIELDS_DATA.BASE, -}); - -export const getFieldDataBegin = () => ({ - type: GET_FIELDS_DATA.BEGIN, -}); - -export const getFieldDataSuccess = (data, extendedProfile) => ({ - type: GET_FIELDS_DATA.SUCCESS, - payload: { data, extendedProfile }, -}); - -export const getFieldDataFailure = () => ({ - type: GET_FIELDS_DATA.FAILURE, -}); diff --git a/src/welcome/data/reducers.js b/src/welcome/data/reducers.js index b5762cd1..493a9672 100644 --- a/src/welcome/data/reducers.js +++ b/src/welcome/data/reducers.js @@ -1,6 +1,6 @@ -import { GET_FIELDS_DATA, SAVE_USER_PROFILE } from './actions'; +import { SAVE_USER_PROFILE } from './actions'; import { - DEFAULT_STATE, PENDING_STATE, COMPLETE_STATE, FAILURE_STATE, + DEFAULT_STATE, PENDING_STATE, } from '../../data/constants'; export const defaultState = { @@ -14,23 +14,6 @@ export const defaultState = { const reducer = (state = defaultState, action) => { switch (action.type) { - case GET_FIELDS_DATA.BEGIN: - return { - ...state, - formRenderState: PENDING_STATE, - }; - case GET_FIELDS_DATA.SUCCESS: - return { - ...state, - extendedProfile: action.payload.extendedProfile, - fieldDescriptions: action.payload.data, - formRenderState: COMPLETE_STATE, - }; - case GET_FIELDS_DATA.FAILURE: - return { - ...state, - formRenderState: FAILURE_STATE, - }; case SAVE_USER_PROFILE.BEGIN: return { ...state, diff --git a/src/welcome/data/sagas.js b/src/welcome/data/sagas.js index 4e100873..224c50ed 100644 --- a/src/welcome/data/sagas.js +++ b/src/welcome/data/sagas.js @@ -1,17 +1,13 @@ import { call, put, takeEvery } from 'redux-saga/effects'; import { - GET_FIELDS_DATA, - getFieldDataBegin, - getFieldDataFailure, - getFieldDataSuccess, SAVE_USER_PROFILE, saveUserProfileBegin, saveUserProfileFailure, saveUserProfileSuccess, } from './actions'; -import { patchAccount, getOptionalFieldData } from './service'; +import { patchAccount } from './service'; export function* saveUserProfileInformation(action) { try { @@ -24,17 +20,6 @@ export function* saveUserProfileInformation(action) { } } -export function* getFieldData() { - try { - yield put(getFieldDataBegin()); - const data = yield call(getOptionalFieldData); - yield put(getFieldDataSuccess(data.fields, data.extended_profile)); - } catch (e) { - yield put(getFieldDataFailure()); - } -} - export default function* saga() { yield takeEvery(SAVE_USER_PROFILE.BASE, saveUserProfileInformation); - yield takeEvery(GET_FIELDS_DATA.BASE, getFieldData); } diff --git a/src/welcome/data/service.js b/src/welcome/data/service.js index a7b5246d..6145f779 100644 --- a/src/welcome/data/service.js +++ b/src/welcome/data/service.js @@ -1,6 +1,7 @@ import { getConfig } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; +// eslint-disable-next-line import/prefer-default-export export async function patchAccount(username, commitValues) { const requestConfig = { headers: { 'Content-Type': 'application/merge-patch+json' }, @@ -16,20 +17,3 @@ export async function patchAccount(username, commitValues) { throw (error); }); } - -export async function getOptionalFieldData() { - const requestConfig = { - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - }; - - const { data } = await getAuthenticatedHttpClient() - .get( - `${getConfig().LMS_BASE_URL}/api/optional_fields`, - requestConfig, - ) - .catch((e) => { - throw (e); - }); - - return data; -} diff --git a/src/welcome/tests/ProgressiveProfiling.test.jsx b/src/welcome/tests/ProgressiveProfiling.test.jsx index 66a64143..08875b01 100644 --- a/src/welcome/tests/ProgressiveProfiling.test.jsx +++ b/src/welcome/tests/ProgressiveProfiling.test.jsx @@ -11,10 +11,10 @@ import * as auth from '@edx/frontend-platform/auth'; import * as logging from '@edx/frontend-platform/logging'; import { injectIntl, IntlProvider, configure } from '@edx/frontend-platform/i18n'; -import { getFieldData, saveUserProfile } from '../data/actions'; +import { saveUserProfile } from '../data/actions'; import ProgressiveProfiling from '../ProgressiveProfiling'; import { - COMPLETE_STATE, DEFAULT_REDIRECT_URL, FAILURE_STATE, PENDING_STATE, + COMPLETE_STATE, DEFAULT_REDIRECT_URL, FAILURE_STATE, } from '../../data/constants'; const IntlProgressiveProfilingPage = injectIntl(ProgressiveProfiling); @@ -36,8 +36,18 @@ describe('ProgressiveProfilingTests', () => { mergeConfig({ WELCOME_PAGE_SUPPORT_LINK: 'http://localhost:1999/welcome', }); - - const registrationResult = { redirectUrl: 'http://localhost:18000/dashboard', success: true }; + const registrationResult = { redirectUrl: getConfig().LMS_BASE_URL + DEFAULT_REDIRECT_URL, success: true }; + const fields = { + company: { name: 'company', type: 'text', label: 'Company' }, + gender: { + name: 'gender', + type: 'select', + label: 'Gender', + options: [['m', 'Male'], ['f', 'Female'], ['o', 'Other/Prefer Not to Say']], + }, + }; + const extendedProfile = ['company']; + const optionalFields = { fields, extended_profile: extendedProfile }; let props = {}; let store = {}; const DASHBOARD_URL = getConfig().LMS_BASE_URL.concat(DEFAULT_REDIRECT_URL); @@ -79,43 +89,13 @@ describe('ProgressiveProfilingTests', () => { location: { state: { registrationResult, + optionalFields, }, }, }; }); - it('should fire action to get form fields', async () => { - store.dispatch = jest.fn(store.dispatch); - const progressiveProfilingPage = await getProgressiveProfilingPage(); - - progressiveProfilingPage.find('button.btn-link').simulate('click'); - expect(store.dispatch).toHaveBeenCalledWith(getFieldData()); - }); - - it('should show spinner until fields are fetched', async () => { - store = mockStore({ - welcomePage: { - formRenderState: PENDING_STATE, - }, - }); - const progressiveProfilingPage = await getProgressiveProfilingPage(); - expect(progressiveProfilingPage.find('#loader').exists()).toBeTruthy(); - }); - it('should render fields returned by backend api', async () => { - store = mockStore({ - welcomePage: { - ...initialState.welcomePage, - fieldDescriptions: { - gender: { - name: 'gender', - type: 'select', - label: 'Gender', - options: [['m', 'Male'], ['f', 'Female'], ['o', 'Other/Prefer Not to Say']], - }, - }, - }, - }); const progressiveProfilingPage = await getProgressiveProfilingPage(); expect(progressiveProfilingPage.find('#gender').exists()).toBeTruthy(); }); @@ -126,27 +106,7 @@ describe('ProgressiveProfilingTests', () => { gender: 'm', extended_profile: [{ field_name: 'company', field_value: 'edx' }], }; - store = mockStore({ - welcomePage: { - ...initialState.welcomePage, - extendedProfile: ['company'], - fieldDescriptions: { - gender: { - name: 'gender', - type: 'select', - label: 'Gender', - options: [['m', 'Male'], ['f', 'Female'], ['o', 'Other/Prefer Not to Say']], - }, - company: { - name: 'company', - type: 'text', - label: 'Company', - }, - }, - }, - }); store.dispatch = jest.fn(store.dispatch); - const progressiveProfilingPage = await getProgressiveProfilingPage(); progressiveProfilingPage.find('select#gender').simulate('change', { target: { value: 'm', name: 'gender' } }); progressiveProfilingPage.find('input#company').simulate('change', { target: { value: 'edx', name: 'company' } });