import React from 'react'; import { Provider } from 'react-redux'; import { getConfig, mergeConfig } from '@edx/frontend-platform'; import * as analytics from '@edx/frontend-platform/analytics'; import * as auth from '@edx/frontend-platform/auth'; import { configure, injectIntl, IntlProvider } from '@edx/frontend-platform/i18n'; import * as logging from '@edx/frontend-platform/logging'; import { mount } from 'enzyme'; import { createMemoryHistory } from 'history'; import { act } from 'react-dom/test-utils'; import { MemoryRouter, Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; import { COMPLETE_STATE, DEFAULT_REDIRECT_URL, FAILURE_STATE, RECOMMENDATIONS, } from '../../data/constants'; import { saveUserProfile } from '../data/actions'; import ProgressiveProfiling from '../ProgressiveProfiling'; const IntlProgressiveProfilingPage = injectIntl(ProgressiveProfiling); const mockStore = configureStore(); jest.mock('@edx/frontend-platform/analytics'); jest.mock('@edx/frontend-platform/auth'); jest.mock('@edx/frontend-platform/logging'); analytics.sendTrackEvent = jest.fn(); analytics.sendPageEvent = jest.fn(); analytics.identifyAuthenticatedUser = jest.fn(); logging.getLoggingService = jest.fn(); auth.configure = jest.fn(); auth.ensureAuthenticatedUser = jest.fn().mockImplementation(() => Promise.resolve(true)); auth.hydrateAuthenticatedUser = jest.fn().mockImplementation(() => Promise.resolve(true)); const history = createMemoryHistory(); describe('ProgressiveProfilingTests', () => { mergeConfig({ AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: 'http://localhost:1999/welcome', }); 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); const initialState = { welcomePage: { formRenderState: COMPLETE_STATE, }, }; const reduxWrapper = children => ( {children} ); const getProgressiveProfilingPage = async () => { const progressiveProfilingPage = mount(reduxWrapper( , )); await act(async () => { await Promise.resolve(progressiveProfilingPage); await new Promise(resolve => setImmediate(resolve)); progressiveProfilingPage.update(); }); return progressiveProfilingPage; }; beforeEach(() => { store = mockStore(initialState); configure({ loggingService: { logError: jest.fn() }, config: { ENVIRONMENT: 'production', LANGUAGE_PREFERENCE_COOKIE_NAME: 'yum', }, messages: { 'es-419': {}, de: {}, 'en-us': {} }, }); props = { getFieldData: jest.fn(), location: { state: { registrationResult, optionalFields, }, }, }; }); it('not should display button "Learn more about how we use this information."', async () => { mergeConfig({ AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: '', }); const progressiveProfilingPage = await getProgressiveProfilingPage(); expect(progressiveProfilingPage.find('a.pgn__hyperlink').exists()).toBeFalsy(); }); it('should display button "Learn more about how we use this information."', async () => { mergeConfig({ AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: 'http://localhost:1999/support', }); const progressiveProfilingPage = await getProgressiveProfilingPage(); expect(progressiveProfilingPage.find('a.pgn__hyperlink').text()).toEqual('Learn more about how we use this information.'); }); it('should render fields returned by backend api', async () => { const progressiveProfilingPage = await getProgressiveProfilingPage(); expect(progressiveProfilingPage.find('#gender').exists()).toBeTruthy(); }); it('should make identify call to segment on progressive profiling page', async () => { await getProgressiveProfilingPage(); expect(analytics.identifyAuthenticatedUser).toHaveBeenCalled(); }); it('should submit user profile details on form submission', async () => { auth.getAuthenticatedUser = jest.fn(() => ({ userId: 3, username: 'abc123' })); const formPayload = { gender: 'm', extended_profile: [{ field_name: 'company', field_value: 'test 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: 'test company', name: 'company' } }); progressiveProfilingPage.find('button.btn-brand').simulate('click'); expect(store.dispatch).toHaveBeenCalledWith(saveUserProfile('abc123', formPayload)); }); it('should open modal on pressing skip for now button', async () => { const progressiveProfilingPage = await getProgressiveProfilingPage(); progressiveProfilingPage.find('button.btn-link').simulate('click'); expect(progressiveProfilingPage.find('.pgn__modal-content-container').exists()).toBeTruthy(); expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.bi.welcome.page.skip.link.clicked'); }); it('should send analytic event for support link click', async () => { const progressiveProfilingPage = await getProgressiveProfilingPage(); progressiveProfilingPage.find('.progressive-profiling-support a[target="_blank"]').simulate('click'); expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.bi.welcome.page.support.link.clicked'); }); it('should show error message when patch request fails', async () => { store = mockStore({ welcomePage: { ...initialState.welcomePage, showError: true, }, }); const progressiveProfilingPage = await getProgressiveProfilingPage(); expect(progressiveProfilingPage.find('#pp-page-errors').exists()).toBeTruthy(); }); it('should redirect to dashboard if no form fields are configured', async () => { store = mockStore({ welcomePage: { formRenderState: FAILURE_STATE, }, }); delete window.location; window.location = { href: getConfig().BASE_URL, assign: jest.fn().mockImplementation((value) => { window.location.href = value; }), }; await getProgressiveProfilingPage(); expect(window.location.href).toBe(DASHBOARD_URL); }); describe('Recommendations test', () => { mergeConfig({ ENABLE_PERSONALIZED_RECOMMENDATIONS: true, }); it.skip('should redirect to recommendations page if recommendations are enabled', async () => { store = mockStore({ welcomePage: { ...initialState.welcomePage, success: true, }, }); auth.getAuthenticatedUser = jest.fn(() => ({ userId: 3, username: 'abc123' })); const progressiveProfilingPage = await getProgressiveProfilingPage(); expect(progressiveProfilingPage.find('button.btn-brand').text()).toEqual('Next'); expect(history.location.pathname).toEqual(RECOMMENDATIONS); }); it('should not redirect to recommendations page if user is on its way to enroll in a course', async () => { delete window.location; window.location = { href: getConfig().BASE_URL, assign: jest.fn().mockImplementation((value) => { window.location.href = value; }), }; const redirectUrl = `${getConfig().LMS_BASE_URL}${DEFAULT_REDIRECT_URL}?enrollment_action=1`; props = { getFieldData: jest.fn(), location: { state: { registrationResult: { redirectUrl, success: true, }, optionalFields, }, }, }; store = mockStore({ welcomePage: { ...initialState.welcomePage, success: true, }, }); auth.getAuthenticatedUser = jest.fn(() => ({ userId: 3, username: 'abc123' })); const progressiveProfilingPage = await getProgressiveProfilingPage(); expect(progressiveProfilingPage.find('button.btn-brand').text()).toEqual('Submit'); expect(window.location.href).toEqual(redirectUrl); }); }); });