diff --git a/src/_style.scss b/src/_style.scss
index 625e09a9..860eebf5 100644
--- a/src/_style.scss
+++ b/src/_style.scss
@@ -20,7 +20,7 @@ $accent-a-light: #c9f2f5;
min-width: 464px !important;
}
-.register-button-width {
+.stateful-button-width {
width: 12rem;
}
diff --git a/src/forgot-password/messages.js b/src/forgot-password/messages.js
index 99502195..9dedb74b 100644
--- a/src/forgot-password/messages.js
+++ b/src/forgot-password/messages.js
@@ -105,8 +105,8 @@ const messages = defineMessages({
},
'invalid.token.error.message': {
id: 'invalid.token.error.message',
- defaultMessage: 'This link has expired. Enter your email below to receive a new link.',
- description: 'Alert message when reset password link has expired',
+ defaultMessage: 'This password reset link is invalid. It may have been used already. Enter your email below to receive a new link.',
+ description: 'Alert message when reset password link has expired or is invalid',
},
'token.validation.rate.limit.error.heading': {
id: 'token.validation.rate.limit.error.heading',
diff --git a/src/forgot-password/tests/ForgotPasswordPage.test.jsx b/src/forgot-password/tests/ForgotPasswordPage.test.jsx
index 1445bf4e..23605491 100644
--- a/src/forgot-password/tests/ForgotPasswordPage.test.jsx
+++ b/src/forgot-password/tests/ForgotPasswordPage.test.jsx
@@ -1,16 +1,19 @@
import React from 'react';
+
+import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
-import { mount } from 'enzyme';
import configureStore from 'redux-mock-store';
+
+import * as analytics from '@edx/frontend-platform/analytics';
+import CookiePolicyBanner from '@edx/frontend-component-cookie-policy-banner';
import { mergeConfig } from '@edx/frontend-platform';
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
-import CookiePolicyBanner from '@edx/frontend-component-cookie-policy-banner';
-import * as analytics from '@edx/frontend-platform/analytics';
import ForgotPasswordPage from '../ForgotPasswordPage';
import { INTERNAL_SERVER_ERROR } from '../../data/constants';
+import { PASSWORD_RESET } from '../../reset-password/data/constants';
jest.mock('@edx/frontend-platform/analytics');
@@ -20,7 +23,7 @@ const IntlForgotPasswordPage = injectIntl(ForgotPasswordPage);
const mockStore = configureStore();
const initialState = {
forgotPassword: {
- status: null,
+ status: '',
},
};
@@ -138,7 +141,7 @@ describe('ForgotPasswordPage', () => {
expect(forgotPage.find()).toBeTruthy();
});
- it('should display success message after email is sent', async () => {
+ it('should display success message after email is sent', () => {
store = mockStore({
...initialState,
forgotPassword: {
@@ -152,4 +155,19 @@ describe('ForgotPasswordPage', () => {
const wrapper = mount(reduxWrapper());
expect(wrapper.find('.alert-success').text()).toEqual(successMessage);
});
+
+ it('should display invalid password reset link error', () => {
+ store = mockStore({
+ ...initialState,
+ forgotPassword: {
+ status: PASSWORD_RESET.INVALID_TOKEN,
+ },
+ });
+ const successMessage = 'Invalid password reset link'
+ + 'This password reset link is invalid. It may have been used already. '
+ + 'Enter your email below to receive a new link.';
+
+ const wrapper = mount(reduxWrapper());
+ expect(wrapper.find('.alert-danger').text()).toEqual(successMessage);
+ });
});
diff --git a/src/login/tests/LoginPage.test.jsx b/src/login/tests/LoginPage.test.jsx
index bc51162e..53d5a2f5 100644
--- a/src/login/tests/LoginPage.test.jsx
+++ b/src/login/tests/LoginPage.test.jsx
@@ -450,7 +450,7 @@ describe('LoginPage', () => {
},
});
- renderer.create(reduxWrapper());
+ renderer.create(reduxWrapper());
expect(document.cookie).toMatch(`${getConfig().USER_SURVEY_COOKIE_NAME}=login`);
});
diff --git a/src/register/RegistrationPage.jsx b/src/register/RegistrationPage.jsx
index 9427f012..556bb9a0 100644
--- a/src/register/RegistrationPage.jsx
+++ b/src/register/RegistrationPage.jsx
@@ -548,7 +548,7 @@ class RegistrationPage extends React.Component {
{
}}
onClick={e => handleSubmit(e)}
diff --git a/src/reset-password/tests/ResetPasswordPage.test.jsx b/src/reset-password/tests/ResetPasswordPage.test.jsx
index 83ba02eb..77a6e518 100644
--- a/src/reset-password/tests/ResetPasswordPage.test.jsx
+++ b/src/reset-password/tests/ResetPasswordPage.test.jsx
@@ -1,5 +1,6 @@
import React from 'react';
+import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';
import configureStore from 'redux-mock-store';
import { Provider } from 'react-redux';
@@ -30,15 +31,6 @@ describe('ResetPasswordPage', () => {
);
- const submitForm = (password) => {
- const resetPasswordPage = mount(reduxWrapper());
- resetPasswordPage.find('input#newPassword').simulate('change', { target: { value: password, name: 'newPassword' } });
- resetPasswordPage.find('input#confirmPassword').simulate('change', { target: { value: password, name: 'confirmPassword' } });
- resetPasswordPage.find('button.btn-brand').simulate('click');
-
- return resetPasswordPage;
- };
-
beforeEach(() => {
store = mockStore();
props = {
@@ -75,7 +67,13 @@ describe('ResetPasswordPage', () => {
}));
store.dispatch = jest.fn(store.dispatch);
- const resetPasswordPage = submitForm(password);
+ const resetPasswordPage = mount(reduxWrapper());
+ resetPasswordPage.find('input#newPassword').simulate('change', { target: { value: password, name: 'newPassword' } });
+ resetPasswordPage.find('input#confirmPassword').simulate('change', { target: { value: password, name: 'confirmPassword' } });
+
+ await act(async () => {
+ await resetPasswordPage.find('button.btn-brand').simulate('click');
+ });
expect(store.dispatch).toHaveBeenCalledWith(resetPassword(
{ new_password1: password, new_password2: password }, props.token, {},