{selectedPage === LOGIN_PAGE
?
diff --git a/src/progressive-profiling/ProgressiveProfiling.jsx b/src/progressive-profiling/ProgressiveProfiling.jsx
index ed9171a6..c64f0742 100644
--- a/src/progressive-profiling/ProgressiveProfiling.jsx
+++ b/src/progressive-profiling/ProgressiveProfiling.jsx
@@ -21,6 +21,7 @@ import {
import { Error } from '@edx/paragon/icons';
import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
+import { useLocation } from 'react-router-dom';
import { saveUserProfile } from './data/actions';
import { welcomePageContextSelector } from './data/selectors';
@@ -47,12 +48,12 @@ const ProgressiveProfiling = (props) => {
const { formatMessage } = useIntl();
const {
getFieldDataFromBackend,
- location,
submitState,
showError,
welcomePageContext,
welcomePageContextApiStatus,
} = props;
+ const location = useLocation();
const registrationEmbedded = isHostAvailableInQueryParams();
const queryParams = getAllPossibleQueryParams();
@@ -170,7 +171,7 @@ const ProgressiveProfiling = (props) => {
const handleSkip = (e) => {
e.preventDefault();
- window.history.replaceState(props.location.state, null, '');
+ window.history.replaceState(location.state, null, '');
setShowModal(true);
sendTrackEvent(
'edx.bi.welcome.page.skip.link.clicked',
@@ -282,17 +283,6 @@ const ProgressiveProfiling = (props) => {
};
ProgressiveProfiling.propTypes = {
- location: PropTypes.shape({
- state: PropTypes.shape({
- registrationResult: PropTypes.shape({
- redirectUrl: PropTypes.string,
- }),
- optionalFields: PropTypes.shape({
- extended_profile: PropTypes.arrayOf(PropTypes.string),
- fields: PropTypes.shape({}),
- }),
- }),
- }),
showError: PropTypes.bool,
shouldRedirect: PropTypes.bool,
submitState: PropTypes.string,
@@ -308,7 +298,6 @@ ProgressiveProfiling.propTypes = {
};
ProgressiveProfiling.defaultProps = {
- location: { state: {} },
shouldRedirect: false,
showError: false,
submitState: DEFAULT_STATE,
diff --git a/src/progressive-profiling/tests/ProgressiveProfiling.test.jsx b/src/progressive-profiling/tests/ProgressiveProfiling.test.jsx
index bee4775d..1014da35 100644
--- a/src/progressive-profiling/tests/ProgressiveProfiling.test.jsx
+++ b/src/progressive-profiling/tests/ProgressiveProfiling.test.jsx
@@ -6,9 +6,8 @@ import { identifyAuthenticatedUser, sendTrackEvent } from '@edx/frontend-platfor
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { configure, injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import { mount } from 'enzyme';
-import { createMemoryHistory } from 'history';
import { act } from 'react-dom/test-utils';
-import { MemoryRouter, Router } from 'react-router-dom';
+import { MemoryRouter, mockNavigate, useLocation } from 'react-router-dom';
import configureStore from 'redux-mock-store';
import {
@@ -44,8 +43,22 @@ jest.mock('../../recommendations/optimizelyExperiment.js', () => ({
trackRecommendationViewedOptimizely: jest.fn(),
RECOMMENDATIONS_EXP_VARIATION: 'welcome_page_recommendations_enabled',
}));
+jest.mock('react-router-dom', () => {
+ const mockNavigation = jest.fn();
-const history = createMemoryHistory();
+ // eslint-disable-next-line react/prop-types
+ const Navigate = ({ to }) => {
+ mockNavigation(to);
+ return
;
+ };
+
+ return {
+ ...jest.requireActual('react-router-dom'),
+ Navigate,
+ mockNavigate: mockNavigation,
+ useLocation: jest.fn(),
+ };
+});
describe('ProgressiveProfilingTests', () => {
mergeConfig({
@@ -63,7 +76,6 @@ describe('ProgressiveProfilingTests', () => {
};
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 = {
@@ -86,11 +98,7 @@ describe('ProgressiveProfilingTests', () => {
);
const getProgressiveProfilingPage = async () => {
- const progressiveProfilingPage = mount(reduxWrapper(
-
-
- ,
- ));
+ const progressiveProfilingPage = mount(reduxWrapper(
));
await act(async () => {
await Promise.resolve(progressiveProfilingPage);
await new Promise(resolve => { setImmediate(resolve); });
@@ -110,14 +118,12 @@ describe('ProgressiveProfilingTests', () => {
},
messages: { 'es-419': {}, de: {}, 'en-us': {} },
});
- props = {
- location: {
- state: {
- registrationResult,
- optionalFields,
- },
+ useLocation.mockReturnValue({
+ state: {
+ registrationResult,
+ optionalFields,
},
- };
+ });
});
it('should not display button "Learn more about how we use this information."', async () => {
@@ -225,7 +231,7 @@ describe('ProgressiveProfilingTests', () => {
const progressiveProfilingPage = await getProgressiveProfilingPage();
expect(progressiveProfilingPage.find('button.btn-brand').text()).toEqual('Next');
- expect(history.location.pathname).toEqual(RECOMMENDATIONS);
+ expect(mockNavigate).toHaveBeenCalledWith(RECOMMENDATIONS);
});
it('should fire segments recommendations viewed and variation group events', async () => {
@@ -258,17 +264,15 @@ describe('ProgressiveProfilingTests', () => {
it('should not redirect to recommendations page if user is on its way to enroll in a course', async () => {
const redirectUrl = `${getConfig().LMS_BASE_URL}${DEFAULT_REDIRECT_URL}?enrollment_action=1`;
- props = {
- location: {
- state: {
- registrationResult: {
- redirectUrl,
- success: true,
- },
- optionalFields,
+ useLocation.mockReturnValue({
+ state: {
+ registrationResult: {
+ redirectUrl,
+ success: true,
},
+ optionalFields,
},
- };
+ });
store = mockStore({
...initialState,
@@ -293,7 +297,9 @@ describe('ProgressiveProfilingTests', () => {
const host = 'http://example.com';
beforeEach(() => {
- props = {};
+ useLocation.mockReturnValue({
+ state: {},
+ });
store = mockStore({
...initialState,
commonComponents: {
@@ -372,7 +378,6 @@ describe('ProgressiveProfilingTests', () => {
href: getConfig().BASE_URL,
search: `?variant=${EMBEDDED}&host=${host}&next=${redirectUrl}`,
};
- props = {};
store = mockStore({
...initialState,
commonComponents: {
diff --git a/src/recommendations/RecommendationsPage.jsx b/src/recommendations/RecommendationsPage.jsx
index 65b92587..84079d93 100644
--- a/src/recommendations/RecommendationsPage.jsx
+++ b/src/recommendations/RecommendationsPage.jsx
@@ -8,6 +8,7 @@ import {
} from '@edx/paragon';
import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
+import { useLocation } from 'react-router-dom';
import { POPULAR, TRENDING } from './data/constants';
import useProducts from './data/hooks/useProducts';
@@ -16,8 +17,9 @@ import RecommendationsList from './RecommendationsList';
import { trackRecommendationsViewed } from './track';
import { DEFAULT_REDIRECT_URL } from '../data/constants';
-const RecommendationsPage = ({ location, countryCode }) => {
+const RecommendationsPage = ({ countryCode }) => {
const { formatMessage } = useIntl();
+ const location = useLocation();
const registrationResponse = location.state?.registrationResult;
const userId = location.state?.userId;
@@ -113,21 +115,9 @@ const RecommendationsPage = ({ location, countryCode }) => {
};
RecommendationsPage.propTypes = {
- location: PropTypes.shape({
- state: PropTypes.shape({
- registrationResult: PropTypes.shape({
- redirectUrl: PropTypes.string,
- }),
- userId: PropTypes.number,
- }),
- }),
countryCode: PropTypes.string.isRequired,
};
-RecommendationsPage.defaultProps = {
- location: { state: {} },
-};
-
const mapStateToProps = state => ({
countryCode: state.register.backendCountryCode,
});
diff --git a/src/recommendations/tests/RecommendationsPage.test.jsx b/src/recommendations/tests/RecommendationsPage.test.jsx
index 966809c7..7548587a 100644
--- a/src/recommendations/tests/RecommendationsPage.test.jsx
+++ b/src/recommendations/tests/RecommendationsPage.test.jsx
@@ -4,6 +4,7 @@ import { Provider } from 'react-redux';
import { getConfig, mergeConfig } from '@edx/frontend-platform';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import { mount } from 'enzyme';
+import { useLocation } from 'react-router-dom';
import configureStore from 'redux-mock-store';
import { DEFAULT_REDIRECT_URL } from '../../data/constants';
@@ -19,6 +20,10 @@ jest.mock('../data/service', () => ({
__esModule: true,
default: jest.fn(),
}));
+jest.mock('react-router-dom', () => ({
+ ...jest.requireActual('react-router-dom'),
+ useLocation: jest.fn(),
+}));
describe('RecommendationsPageTests', () => {
mergeConfig({
@@ -27,7 +32,6 @@ describe('RecommendationsPageTests', () => {
TRENDING_PRODUCTS: '[]',
});
- let defaultProps = {};
let store = {};
const dashboardUrl = getConfig().LMS_BASE_URL.concat(DEFAULT_REDIRECT_URL);
@@ -43,20 +47,24 @@ describe('RecommendationsPageTests', () => {
);
+ const mockUseLocation = () => (
+ useLocation.mockReturnValue({
+ state: {
+ registrationResult,
+ userId: 111,
+ },
+ })
+ );
+
beforeEach(() => {
store = mockStore({
register: {
backendCountryCode: 'PK',
},
});
- defaultProps = {
- location: {
- state: {
- registrationResult,
- userId: 111,
- },
- },
- };
+ useLocation.mockReturnValue({
+ state: {},
+ });
});
it('should redirect to dashboard if user is not coming from registration workflow', () => {
@@ -65,19 +73,22 @@ describe('RecommendationsPageTests', () => {
});
it('should redirect if either popular or trending recommendations are not configured', () => {
- mount(reduxWrapper(
));
+ mockUseLocation();
+ mount(reduxWrapper(
));
expect(window.location.href).toEqual(redirectUrl);
});
it('should redirect user if they click "Skip for now" button', () => {
- const recommendationsPage = mount(reduxWrapper(
));
+ mockUseLocation();
+ const recommendationsPage = mount(reduxWrapper(
));
recommendationsPage.find('.pgn__stateful-btn-state-default').first().simulate('click');
expect(window.location.href).toEqual(redirectUrl);
});
it('displays popular products as default recommendations', () => {
- const recommendationsPage = mount(reduxWrapper(
));
+ mockUseLocation();
+ const recommendationsPage = mount(reduxWrapper(
));
expect(recommendationsPage.find('.nav-link .active a').text()).toEqual('Most Popular');
});
});
diff --git a/src/register/tests/RegistrationPage.test.jsx b/src/register/tests/RegistrationPage.test.jsx
index e6a9ff5e..435f73eb 100644
--- a/src/register/tests/RegistrationPage.test.jsx
+++ b/src/register/tests/RegistrationPage.test.jsx
@@ -7,8 +7,7 @@ import {
configure, getLocale, injectIntl, IntlProvider,
} from '@edx/frontend-platform/i18n';
import { mount } from 'enzyme';
-import { createMemoryHistory } from 'history';
-import { Router } from 'react-router-dom';
+import { mockNavigate, BrowserRouter as Router } from 'react-router-dom';
import renderer from 'react-test-renderer';
import configureStore from 'redux-mock-store';
@@ -40,7 +39,22 @@ jest.mock('@edx/frontend-platform/i18n', () => ({
const IntlRegistrationPage = injectIntl(RegistrationPage);
const IntlRegistrationFailure = injectIntl(RegistrationFailureMessage);
const mockStore = configureStore();
-const history = createMemoryHistory();
+
+jest.mock('react-router-dom', () => {
+ const mockNavigation = jest.fn();
+
+ // eslint-disable-next-line react/prop-types
+ const Navigate = ({ to }) => {
+ mockNavigation(to);
+ return
;
+ };
+
+ return {
+ ...jest.requireActual('react-router-dom'),
+ Navigate,
+ mockNavigate: mockNavigation,
+ };
+});
describe('RegistrationPage', () => {
mergeConfig({
@@ -72,6 +86,12 @@ describe('RegistrationPage', () => {
);
+ const routerWrapper = children => (
+
+ {children}
+
+ );
+
const thirdPartyAuthContext = {
currentProvider: null,
finishAuthUrl: null,
@@ -174,7 +194,7 @@ describe('RegistrationPage', () => {
};
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
populateRequiredFields(registrationPage, payload);
registrationPage.find('button.btn-brand').simulate('click');
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload, country: 'PK' }));
@@ -204,7 +224,7 @@ describe('RegistrationPage', () => {
},
});
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
populateRequiredFields(registrationPage, formPayload, true);
registrationPage.find('button.btn-brand').simulate('click');
@@ -230,7 +250,7 @@ describe('RegistrationPage', () => {
};
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
populateRequiredFields(registrationPage, payload);
registrationPage.find('button.btn-brand').simulate('click');
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload, country: 'PK' }));
@@ -243,7 +263,7 @@ describe('RegistrationPage', () => {
it('should not dispatch registerNewUser on empty form Submission', () => {
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('button.btn-brand').simulate('click');
expect(store.dispatch).not.toHaveBeenCalledWith(registerNewUser({}));
});
@@ -263,7 +283,7 @@ describe('RegistrationPage', () => {
});
it('should show error messages for required fields on empty form submission', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('button.btn-brand').simulate('click');
expect(registrationPage.find('div[feedback-for="name"]').text()).toEqual(emptyFieldValidation.name);
@@ -277,7 +297,7 @@ describe('RegistrationPage', () => {
});
it('should update errors for frontend validations', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#name').simulate('blur', { target: { value: 'http://test.com', name: 'name' } });
expect(
@@ -294,7 +314,7 @@ describe('RegistrationPage', () => {
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',
+ + ' underscores (_), and hyphens (-). Usernames cannot contain spaces',
);
registrationPage.find('input#email').simulate('blur', { target: { value: 'ab', name: 'email' } });
@@ -304,7 +324,7 @@ describe('RegistrationPage', () => {
});
it('should validate fields on blur event', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#username').simulate('blur', { target: { value: '', name: 'username' } });
expect(registrationPage.find('div[feedback-for="username"]').text()).toEqual(emptyFieldValidation.username);
@@ -324,7 +344,7 @@ describe('RegistrationPage', () => {
it('should call validation api on blur event, if frontend validations have passed', () => {
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
// Enter a valid name so that frontend validations are passed
registrationPage.find('input#name').simulate('change', { target: { value: 'John Doe', name: 'name' } });
@@ -342,7 +362,7 @@ describe('RegistrationPage', () => {
});
it('should run validations for focused field on form submission', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input[name="country"]').simulate('focus');
registrationPage.find('button.btn-brand').simulate('click');
@@ -351,7 +371,7 @@ describe('RegistrationPage', () => {
it('should give email suggestions for common service provider domain typos', () => {
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#email').simulate('change', { target: { value: 'john@yopmail.com', name: 'email' } });
registrationPage.find('input#email').simulate('blur');
@@ -360,7 +380,7 @@ describe('RegistrationPage', () => {
});
it('should click on email suggestions for common service provider domain typos', () => {
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#email').simulate('change', { target: { value: 'john@yopmail.com', name: 'email' } });
registrationPage.find('input#email').simulate('blur');
@@ -370,7 +390,7 @@ describe('RegistrationPage', () => {
it('should give error for common top level domain mistakes', () => {
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage
.find('input#email')
@@ -392,7 +412,7 @@ describe('RegistrationPage', () => {
},
},
});
- const registrationPage = mount(reduxWrapper(
)).find('RegistrationPage');
+ const registrationPage = mount(routerWrapper(reduxWrapper(
))).find('RegistrationPage');
expect(registrationPage.prop('backendValidations')).toEqual({
email: `This email is already associated with an existing or previous ${ getConfig().SITE_NAME } account`,
username: 'It looks like this username is already taken',
@@ -400,20 +420,20 @@ describe('RegistrationPage', () => {
});
it('should remove space from the start of username', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#username').simulate('change', { target: { value: ' test-user', name: 'username' } });
expect(registrationPage.find('input#username').prop('value')).toEqual('test-user');
});
it('should remove extra character if username is more than 30 character long', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#username').simulate('change', { target: { value: 'why_this_is_not_valid_username_', name: 'username' } });
expect(registrationPage.find('input#username').prop('value')).toEqual('');
});
it('should give error with suggestion for common top level domain mistakes', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#email').simulate('change', { target: { value: 'ahtesham@hotmail', name: 'email' } });
registrationPage.find('input#email').simulate('blur');
@@ -423,7 +443,7 @@ describe('RegistrationPage', () => {
it('should call backend validation api for password validation', () => {
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#password').simulate('change', { target: { value: 'aziz194@', name: 'password' } });
registrationPage.find('input#password').simulate('blur');
@@ -434,7 +454,7 @@ describe('RegistrationPage', () => {
// ******** test field focus in functionality ********
it('should clear field related error messages on input field Focus', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('button.btn-brand').simulate('click');
expect(registrationPage.find('div[feedback-for="name"]').text()).toEqual(emptyFieldValidation.name);
@@ -461,7 +481,7 @@ describe('RegistrationPage', () => {
it('should clear username suggestions when username field is focused in', () => {
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#username').simulate('focus');
expect(store.dispatch).toHaveBeenCalledWith(clearUsernameSuggestions());
@@ -484,7 +504,7 @@ 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 registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
expect(registrationPage.find('#tpa-alert').find('p').text()).toEqual(expectedMessage);
});
@@ -545,7 +565,7 @@ describe('RegistrationPage', () => {
// ******** test form buttons and fields ********
it('should match default button state', () => {
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
expect(registrationPage.find('button[type="submit"] span').first().text()).toEqual('Create an account for free');
});
@@ -558,7 +578,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
const button = registrationPage.find('button[type="submit"] span').first();
expect(button.find('.sr-only').text()).toEqual('pending');
@@ -569,7 +589,7 @@ describe('RegistrationPage', () => {
MARKETING_EMAILS_OPT_IN: 'true',
});
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
expect(registrationPage.find('div.form-field--checkbox').length).toEqual(1);
mergeConfig({
@@ -589,7 +609,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
expect(registrationPage.find(`button#${ssoProvider.id}`).length).toEqual(1);
});
@@ -611,7 +631,7 @@ describe('RegistrationPage', () => {
delete window.location;
window.location = { href: getConfig().BASE_URL };
- const root = mount(reduxWrapper(
));
+ const root = mount(routerWrapper(reduxWrapper(
)));
expect(root.text().includes('Institution/campus credentials')).toBe(true);
mergeConfig({
@@ -639,7 +659,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
expect(registrationPage.find('input#password').length).toEqual(0);
});
@@ -654,7 +674,7 @@ describe('RegistrationPage', () => {
},
});
- renderer.create(reduxWrapper(
));
+ renderer.create(routerWrapper(reduxWrapper(
)));
expect(document.cookie).toMatch(`${getConfig().REGISTER_CONVERSION_COOKIE_NAME}=true`);
});
@@ -674,7 +694,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
expect(registrationPage.find('button.username-suggestions--chip').length).toEqual(3);
});
@@ -691,7 +711,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#name').simulate('change', { target: { value: 'test name', name: 'name' } });
expect(registrationPage.find('button.username-suggestions--chip').length).toEqual(3);
@@ -710,7 +730,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#name').simulate('change', { target: { value: 'test name', name: 'name' } });
registrationPage.find('.username-suggestions--chip').first().simulate('click');
expect(registrationPage.find('input#username').props().value).toEqual('test_1');
@@ -730,7 +750,7 @@ describe('RegistrationPage', () => {
});
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper(
));
+ const registrationPage = mount(routerWrapper(reduxWrapper(
)));
registrationPage.find('input#name').simulate('change', { target: { value: 'test name', name: 'name' } });
registrationPage.find('button.username-suggestions__close__button').at(0).simulate('click');
expect(store.dispatch).toHaveBeenCalledWith(clearUsernameSuggestions());
@@ -750,7 +770,7 @@ describe('RegistrationPage', () => {
});
delete window.location;
window.location = { href: getConfig().BASE_URL };
- renderer.create(reduxWrapper(
));
+ renderer.create(routerWrapper(reduxWrapper(
)));
expect(window.location.href).toBe(dashboardURL);
});
@@ -773,7 +793,7 @@ describe('RegistrationPage', () => {
delete window.location;
window.location = { href: getConfig().BASE_URL };
- const loginPage = mount(reduxWrapper(
));
+ const loginPage = mount(routerWrapper(reduxWrapper(
)));
loginPage.find('button#oa2-apple-id').simulate('click');
expect(window.location.href).toBe(getConfig().LMS_BASE_URL + registerUrl);
@@ -801,7 +821,7 @@ describe('RegistrationPage', () => {
delete window.location;
window.location = { href: getConfig().BASE_URL };
- renderer.create(reduxWrapper(
));
+ renderer.create(routerWrapper(reduxWrapper(
)));
expect(window.location.href).toBe(getConfig().LMS_BASE_URL + authCompleteUrl);
});
@@ -822,7 +842,7 @@ describe('RegistrationPage', () => {
});
delete window.location;
window.location = { href: getConfig().BASE_URL };
- renderer.create(reduxWrapper(
));
+ renderer.create(routerWrapper(reduxWrapper(
)));
expect(window.location.href).toBe(dashboardUrl);
});
@@ -851,12 +871,12 @@ describe('RegistrationPage', () => {
});
const progressiveProfilingPage = mount(reduxWrapper(
-
+
,
));
progressiveProfilingPage.update();
- expect(history.location.pathname).toEqual(AUTHN_PROGRESSIVE_PROFILING);
+ expect(mockNavigate).toHaveBeenCalledWith(AUTHN_PROGRESSIVE_PROFILING);
});
// ******** test hinted third party auth ********
@@ -877,7 +897,7 @@ describe('RegistrationPage', () => {
delete window.location;
window.location = { href: getConfig().BASE_URL.concat(LOGIN_PAGE), search: `?next=/dashboard&tpa_hint=${ssoProvider.id}` };
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(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);
});
@@ -935,7 +955,7 @@ describe('RegistrationPage', () => {
window.location = { href: getConfig().BASE_URL.concat(REGISTER_PAGE), search: `?next=/dashboard&tpa_hint=${ssoProvider.id}` };
ssoProvider.iconImage = null;
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
expect(registrationPage.find(`button#${ssoProvider.id}`).find('div').find('span').hasClass('pgn__icon')).toEqual(true);
});
@@ -956,7 +976,7 @@ describe('RegistrationPage', () => {
delete window.location;
window.location = { href: getConfig().BASE_URL.concat(REGISTER_PAGE), search: `?next=/dashboard&tpa_hint=${secondaryProviders.id}` };
- mount(reduxWrapper());
+ mount(routerWrapper(reduxWrapper()));
expect(window.location.href).toEqual(getConfig().LMS_BASE_URL + secondaryProviders.registerUrl);
});
@@ -977,7 +997,7 @@ describe('RegistrationPage', () => {
delete window.location;
window.location = { href: getConfig().BASE_URL.concat(LOGIN_PAGE), search: '?next=/dashboard&tpa_hint=invalid' };
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
expect(registrationPage.find(`button#${ssoProvider.id}`).find('span#provider-name').text()).toEqual(expectedMessage);
});
@@ -993,12 +1013,12 @@ describe('RegistrationPage', () => {
});
store.dispatch = jest.fn(store.dispatch);
- mount(reduxWrapper());
+ mount(routerWrapper(reduxWrapper()));
expect(store.dispatch).toHaveBeenCalledWith(backupRegistrationFormBegin({ ...registrationFormData }));
});
it('should send page event when register page is rendered', () => {
- mount(reduxWrapper());
+ mount(routerWrapper(reduxWrapper()));
expect(sendPageEvent).toHaveBeenCalledWith('login_and_registration', 'register');
});
@@ -1023,7 +1043,7 @@ describe('RegistrationPage', () => {
});
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper()).find('RegistrationPage');
+ const registrationPage = mount(routerWrapper(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));
@@ -1038,7 +1058,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
expect(registrationPage.find('input[name="country"]').props().value).toEqual('Pakistan');
});
@@ -1053,7 +1073,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper()).find('RegistrationPage');
+ const registrationPage = mount(routerWrapper(reduxWrapper())).find('RegistrationPage');
expect(registrationPage.find('div#validation-errors').first().text()).toContain(
'An error has occurred. Try refreshing the page, or check your internet connection.',
);
@@ -1079,7 +1099,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper()).find('RegistrationPage');
+ const registrationPage = mount(routerWrapper(reduxWrapper())).find('RegistrationPage');
expect(registrationPage.find('input#name').props().value).toEqual('John Doe');
expect(registrationPage.find('input#username').props().value).toEqual('john_doe');
@@ -1091,7 +1111,7 @@ describe('RegistrationPage', () => {
it('should set country in component state when form is translated used i18n', () => {
getLocale.mockImplementation(() => ('ar-ae'));
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
registrationPage.find('input[name="country"]').simulate('click');
registrationPage.find('button.dropdown-item').at(0).simulate('click', { target: { value: 'أفغانستان ', name: 'countryItem' } });
expect(registrationPage.find('div[feedback-for="country"]').exists()).toBeFalsy();
@@ -1111,7 +1131,9 @@ describe('RegistrationPage', () => {
store.dispatch = jest.fn(store.dispatch);
const clearBackendError = jest.fn();
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper(
+ ,
+ )));
registrationPage.find('input#email').simulate('change', { target: { value: 'a@gmail.com', name: 'email' } });
expect(registrationPage.find('div[feedback-for="email"]').exists()).toBeFalsy();
});
@@ -1137,7 +1159,7 @@ describe('RegistrationPage', () => {
},
},
});
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
expect(registrationPage.find('#profession').exists()).toBeTruthy();
expect(registrationPage.find('#tos').exists()).toBeTruthy();
});
@@ -1168,7 +1190,7 @@ describe('RegistrationPage', () => {
};
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
populateRequiredFields(registrationPage, payload);
registrationPage.find('input#profession').simulate('change', { target: { value: 'Engineer', name: 'profession' } });
@@ -1197,7 +1219,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
registrationPage.find('button.btn-brand').simulate('click');
expect(registrationPage.find('#profession-error').last().text()).toEqual(professionError);
@@ -1217,7 +1239,7 @@ describe('RegistrationPage', () => {
},
},
});
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
registrationPage.find('input#email').simulate('change', { target: { value: 'test1@gmail.com', name: 'email' } });
registrationPage.find('input#confirm_email').simulate('blur', { target: { value: 'test2@gmail.com', name: 'confirm_email' } });
expect(registrationPage.find('div#confirm_email-error').text()).toEqual('The email addresses do not match.');
@@ -1237,7 +1259,7 @@ describe('RegistrationPage', () => {
},
});
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
registrationPage.find('input#profession').simulate('focus', { target: { value: '', name: 'profession' } });
registrationPage.find('button.btn-brand').simulate('click');
@@ -1279,7 +1301,7 @@ describe('RegistrationPage', () => {
});
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
expect(registrationPage.find('input#tos').props().value).toEqual(true);
expect(registrationPage.find('input#honor-code').props().value).toEqual(true);
@@ -1313,7 +1335,7 @@ describe('RegistrationPage', () => {
});
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
expect(registrationPage.find('#tpa-spinner').exists()).toBeTruthy();
expect(registrationPage.find('#registration-form').exists()).toBeFalsy();
});
@@ -1343,7 +1365,7 @@ describe('RegistrationPage', () => {
});
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
expect(registrationPage.find('#tpa-spinner').exists()).toBeFalsy();
expect(registrationPage.find('#registration-form').exists()).toBeTruthy();
});
@@ -1373,7 +1395,7 @@ describe('RegistrationPage', () => {
store.dispatch = jest.fn(store.dispatch);
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
expect(registrationPage.find('div.alert-heading').length).toEqual(1);
expect(registrationPage.find('div.alert').first().text()).toContain('An error occured');
});
@@ -1381,7 +1403,7 @@ describe('RegistrationPage', () => {
it('should not run country field validation when onBlur is fired by drop-down arrow icon click', () => {
getLocale.mockImplementation(() => ('en-us'));
- const registrationPage = mount(reduxWrapper());
+ const registrationPage = mount(routerWrapper(reduxWrapper()));
registrationPage.find('input[name="country"]').simulate('blur', {
target: { value: '', name: 'country' },
relatedTarget: { type: 'button', className: 'btn-icon pgn__form-autosuggest__icon-button' },
diff --git a/src/reset-password/ResetPasswordPage.jsx b/src/reset-password/ResetPasswordPage.jsx
index 39afac4e..38da95a5 100644
--- a/src/reset-password/ResetPasswordPage.jsx
+++ b/src/reset-password/ResetPasswordPage.jsx
@@ -14,7 +14,7 @@ import {
import { ChevronLeft } from '@edx/paragon/icons';
import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
-import { Redirect } from 'react-router-dom';
+import { useNavigate, useParams } from 'react-router-dom';
import { resetPassword, validateToken } from './data/actions';
import {
@@ -39,7 +39,8 @@ const ResetPasswordPage = (props) => {
const [confirmPassword, setConfirmPassword] = useState('');
const [formErrors, setFormErrors] = useState({});
const [errorCode, setErrorCode] = useState(null);
- const [key, setKey] = useState('');
+ const { token } = useParams();
+ const navigate = useNavigate();
useEffect(() => {
if (props.status !== TOKEN_STATE.PENDING && props.status !== PASSWORD_RESET_ERROR) {
@@ -145,15 +146,14 @@ const ResetPasswordPage = (props) => {
);
if (props.status === TOKEN_STATE.PENDING) {
- const { token } = props.match.params;
if (token) {
props.validateToken(token);
return ;
}
} else if (props.status === PASSWORD_RESET_ERROR) {
- return ;
+ navigate(updatePathWithQueryParams(RESET_PAGE));
} else if (props.status === 'success') {
- return ;
+ navigate(updatePathWithQueryParams(LOGIN_PAGE));
} else {
return (
@@ -163,12 +163,9 @@ const ResetPasswordPage = (props) => {
{formatMessage(messages['reset.password.page.title'], { siteName: getConfig().SITE_NAME })}
- setKey(k)}>
+ navigate(updatePathWithQueryParams(key))}>
- { key && (
-
- )}
@@ -220,7 +217,6 @@ const ResetPasswordPage = (props) => {
ResetPasswordPage.defaultProps = {
status: null,
token: null,
- match: null,
errorMsg: null,
};
@@ -228,11 +224,6 @@ ResetPasswordPage.propTypes = {
resetPassword: PropTypes.func.isRequired,
validateToken: PropTypes.func.isRequired,
token: PropTypes.string,
- match: PropTypes.shape({
- params: PropTypes.shape({
- token: PropTypes.string,
- }),
- }),
status: PropTypes.string,
errorMsg: PropTypes.string,
};
diff --git a/src/reset-password/tests/ResetPasswordPage.test.jsx b/src/reset-password/tests/ResetPasswordPage.test.jsx
index facdb5a1..e565a5b4 100644
--- a/src/reset-password/tests/ResetPasswordPage.test.jsx
+++ b/src/reset-password/tests/ResetPasswordPage.test.jsx
@@ -3,23 +3,29 @@ import { Provider } from 'react-redux';
import { configure, injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import { mount } from 'enzyme';
-import { createMemoryHistory } from 'history';
import { act } from 'react-dom/test-utils';
-import { MemoryRouter, Router } from 'react-router-dom';
+import { MemoryRouter } from 'react-router-dom';
import configureStore from 'redux-mock-store';
-import { LOGIN_PAGE } from '../../data/constants';
+import { LOGIN_PAGE, RESET_PAGE } from '../../data/constants';
import { resetPassword, validateToken } from '../data/actions';
import {
PASSWORD_RESET, PASSWORD_RESET_ERROR, SUCCESS, TOKEN_STATE,
} from '../data/constants';
import ResetPasswordPage from '../ResetPasswordPage';
+const mockedNavigator = jest.fn();
+const token = '1c-bmjdkc-5e60e084cf8113048ca7';
+
jest.mock('@edx/frontend-platform/auth');
+jest.mock('react-router-dom', () => ({
+ ...(jest.requireActual('react-router-dom')),
+ useNavigate: () => mockedNavigator,
+ useParams: jest.fn().mockReturnValue({ token }),
+}));
const IntlResetPasswordPage = injectIntl(ResetPasswordPage);
const mockStore = configureStore();
-const history = createMemoryHistory();
describe('ResetPasswordPage', () => {
let props = {};
@@ -188,36 +194,24 @@ describe('ResetPasswordPage', () => {
props = {
status:
TOKEN_STATE.PENDING,
- match: {
- params: { token: '1c-bmjdkc-5e60e084cf8113048ca7' },
- },
};
mount(reduxWrapper());
- expect(store.dispatch).toHaveBeenCalledWith(validateToken(props.match.params.token));
+ expect(store.dispatch).toHaveBeenCalledWith(validateToken(token));
});
it('should redirect the user to Reset password email screen ', async () => {
props = {
status:
PASSWORD_RESET_ERROR,
};
- mount(reduxWrapper(
-
-
- ,
-
- ));
- expect(history.location.pathname).toEqual('/reset');
+ mount(reduxWrapper());
+ expect(mockedNavigator).toHaveBeenCalledWith(RESET_PAGE);
});
it('should redirect the user to root url of the application ', async () => {
props = {
status: SUCCESS,
};
- mount(reduxWrapper(
-
-
- ,
- ));
- expect(history.location.pathname).toEqual('/login');
+ mount(reduxWrapper());
+ expect(mockedNavigator).toHaveBeenCalledWith(LOGIN_PAGE);
});
it('show spinner during token validation', () => {
@@ -228,15 +222,11 @@ describe('ResetPasswordPage', () => {
// ******** redirection tests ********
it('by clicking on sign in tab should redirect onto login page', async () => {
- const resetPasswordPage = mount(reduxWrapper(
-
-
- ,
- ));
+ const resetPasswordPage = mount(reduxWrapper());
await act(async () => { await resetPasswordPage.find('nav').find('a').first().simulate('click'); });
resetPasswordPage.update();
- expect(history.location.pathname).toEqual(LOGIN_PAGE);
+ expect(mockedNavigator).toHaveBeenCalledWith(LOGIN_PAGE);
});
});