diff --git a/client/modules/User/components/AccountForm.unit.test.jsx b/client/modules/User/components/AccountForm.unit.test.jsx
new file mode 100644
index 0000000000..653dce5243
--- /dev/null
+++ b/client/modules/User/components/AccountForm.unit.test.jsx
@@ -0,0 +1,122 @@
+import React from 'react';
+import thunk from 'redux-thunk';
+import configureStore from 'redux-mock-store';
+import {
+ reduxRender,
+ screen,
+ fireEvent,
+ act,
+ waitFor
+} from '../../../test-utils';
+import AccountForm from './AccountForm';
+import { initialTestState } from '../../../testData/testReduxStore';
+import * as actions from '../actions';
+
+const mockStore = configureStore([thunk]);
+const store = mockStore(initialTestState);
+
+jest.mock('../actions', () => ({
+ ...jest.requireActual('../actions'),
+ updateSettings: jest.fn().mockReturnValue(
+ (dispatch) =>
+ new Promise((resolve) => {
+ setTimeout(() => {
+ dispatch({ type: 'UPDATE_SETTINGS', payload: {} });
+ resolve();
+ }, 100);
+ })
+ )
+}));
+
+const subject = () => {
+ reduxRender(, {
+ store
+ });
+};
+
+describe('', () => {
+ it('renders form fields with initial values', () => {
+ subject();
+ const emailElement = screen.getByRole('textbox', {
+ name: /email/i
+ });
+ expect(emailElement).toBeInTheDocument();
+ expect(emailElement).toHaveValue('happydog@example.com');
+
+ const userNameElement = screen.getByRole('textbox', {
+ name: /username/i
+ });
+ expect(userNameElement).toBeInTheDocument();
+ expect(userNameElement).toHaveValue('happydog');
+
+ const currentPasswordElement = screen.getByLabelText(/current password/i);
+ expect(currentPasswordElement).toBeInTheDocument();
+ expect(currentPasswordElement).toHaveValue('');
+
+ const newPasswordElement = screen.getByLabelText(/new password/i);
+ expect(newPasswordElement).toBeInTheDocument();
+ expect(newPasswordElement).toHaveValue('');
+ });
+
+ it('handles form submission and calls updateSettings', async () => {
+ subject();
+
+ const saveAllSettingsButton = screen.getByRole('button', {
+ name: /save all settings/i
+ });
+
+ const currentPasswordElement = screen.getByLabelText(/current password/i);
+ const newPasswordElement = screen.getByLabelText(/new password/i);
+
+ fireEvent.change(currentPasswordElement, {
+ target: {
+ value: 'currentPassword'
+ }
+ });
+
+ fireEvent.change(newPasswordElement, {
+ target: {
+ value: 'newPassword'
+ }
+ });
+
+ await act(async () => {
+ fireEvent.click(saveAllSettingsButton);
+ });
+
+ await waitFor(() => {
+ expect(actions.updateSettings).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ it('Save all setting button should get disabled while submitting and enable when not submitting', async () => {
+ subject();
+
+ const saveAllSettingsButton = screen.getByRole('button', {
+ name: /save all settings/i
+ });
+
+ const currentPasswordElement = screen.getByLabelText(/current password/i);
+ const newPasswordElement = screen.getByLabelText(/new password/i);
+
+ fireEvent.change(currentPasswordElement, {
+ target: {
+ value: 'currentPassword'
+ }
+ });
+
+ fireEvent.change(newPasswordElement, {
+ target: {
+ value: 'newPassword'
+ }
+ });
+ expect(saveAllSettingsButton).not.toHaveAttribute('disabled');
+
+ await act(async () => {
+ fireEvent.click(saveAllSettingsButton);
+ await waitFor(() => {
+ expect(saveAllSettingsButton).toHaveAttribute('disabled');
+ });
+ });
+ });
+});
diff --git a/client/modules/User/components/LoginForm.unit.test.jsx b/client/modules/User/components/LoginForm.unit.test.jsx
new file mode 100644
index 0000000000..28fb9383c2
--- /dev/null
+++ b/client/modules/User/components/LoginForm.unit.test.jsx
@@ -0,0 +1,86 @@
+import React from 'react';
+import thunk from 'redux-thunk';
+import configureStore from 'redux-mock-store';
+import LoginForm from './LoginForm';
+import * as actions from '../actions';
+import { initialTestState } from '../../../testData/testReduxStore';
+import { reduxRender, screen, fireEvent, act } from '../../../test-utils';
+
+const mockStore = configureStore([thunk]);
+const store = mockStore(initialTestState);
+
+jest.mock('../actions', () => ({
+ ...jest.requireActual('../actions'),
+ validateAndLoginUser: jest.fn().mockReturnValue(
+ (dispatch) =>
+ new Promise((resolve) => {
+ setTimeout(() => {
+ dispatch({ type: 'AUTH_USER', payload: {} });
+ dispatch({ type: 'SET_PREFERENCES', payload: {} });
+ resolve();
+ }, 100);
+ })
+ )
+}));
+
+const subject = () => {
+ reduxRender(, {
+ store
+ });
+};
+
+describe('', () => {
+ test('Renders form with the correct fields.', () => {
+ subject();
+ const emailTextElement = screen.getByText(/email or username/i);
+ expect(emailTextElement).toBeInTheDocument();
+
+ const emailInputElement = screen.getByRole('textbox', {
+ name: /email or username/i
+ });
+ expect(emailInputElement).toBeInTheDocument();
+
+ const passwordTextElement = screen.getByText(/password/i);
+ expect(passwordTextElement).toBeInTheDocument();
+
+ const passwordInputElement = screen.getByLabelText(/password/i);
+ expect(passwordInputElement).toBeInTheDocument();
+
+ const loginButtonElement = screen.getByRole('button', {
+ name: /log in/i
+ });
+ expect(loginButtonElement).toBeInTheDocument();
+ });
+ test('Validate and login user is called with the correct values.', async () => {
+ subject();
+
+ const emailElement = screen.getByRole('textbox', {
+ name: /email or username/i
+ });
+ fireEvent.change(emailElement, {
+ target: {
+ value: 'correctuser@gmail.com'
+ }
+ });
+
+ const passwordElement = screen.getByLabelText(/password/i);
+
+ fireEvent.change(passwordElement, {
+ target: {
+ value: 'correctpassword'
+ }
+ });
+
+ const loginButton = screen.getByRole('button', {
+ name: /log in/i
+ });
+ await act(async () => {
+ fireEvent.click(loginButton);
+ });
+
+ expect(actions.validateAndLoginUser).toHaveBeenCalledWith({
+ email: 'correctuser@gmail.com',
+ password: 'correctpassword'
+ });
+ });
+});
diff --git a/client/modules/User/components/NewPasswordForm.unit.test.jsx b/client/modules/User/components/NewPasswordForm.unit.test.jsx
new file mode 100644
index 0000000000..dbddf3c8cb
--- /dev/null
+++ b/client/modules/User/components/NewPasswordForm.unit.test.jsx
@@ -0,0 +1,84 @@
+import React from 'react';
+import thunk from 'redux-thunk';
+import configureStore from 'redux-mock-store';
+import { fireEvent } from '@storybook/testing-library';
+import { reduxRender, screen, act, waitFor } from '../../../test-utils';
+import { initialTestState } from '../../../testData/testReduxStore';
+import NewPasswordForm from './NewPasswordForm';
+
+const mockStore = configureStore([thunk]);
+const store = mockStore(initialTestState);
+
+const mockResetPasswordToken = 'mockResetToken';
+const subject = () => {
+ reduxRender(, {
+ store
+ });
+};
+const mockDispatch = jest.fn();
+
+jest.mock('react-redux', () => ({
+ ...jest.requireActual('react-redux'),
+ useDispatch: () => mockDispatch
+}));
+
+jest.mock('../../../utils/reduxFormUtils', () => ({
+ validateNewPassword: jest.fn()
+}));
+
+jest.mock('../actions', () => ({
+ updatePassword: jest.fn().mockReturnValue(
+ new Promise((resolve) => {
+ resolve();
+ })
+ )
+}));
+
+describe('', () => {
+ beforeEach(() => {
+ mockDispatch.mockClear();
+ jest.clearAllMocks();
+ });
+ test('renders form fields correctly', () => {
+ subject();
+
+ const passwordInputElements = screen.getAllByLabelText(/Password/i);
+ expect(passwordInputElements).toHaveLength(2);
+
+ const passwordInputElement = passwordInputElements[0];
+ expect(passwordInputElement).toBeInTheDocument();
+
+ const confirmPasswordInputElement = passwordInputElements[1];
+ expect(confirmPasswordInputElement).toBeInTheDocument();
+
+ const submitElemement = screen.getByRole('button', {
+ name: /set new password/i
+ });
+ expect(submitElemement).toBeInTheDocument();
+ });
+
+ test('submits form with valid data', async () => {
+ subject();
+ const passwordInputElements = screen.getAllByLabelText(/Password/i);
+
+ const passwordInputElement = passwordInputElements[0];
+ fireEvent.change(passwordInputElement, {
+ target: { value: 'password123' }
+ });
+
+ const confirmPasswordInputElement = passwordInputElements[1];
+ fireEvent.change(confirmPasswordInputElement, {
+ target: { value: 'password123' }
+ });
+
+ const submitElemement = screen.getByRole('button', {
+ name: /set new password/i
+ });
+
+ await act(async () => {
+ fireEvent.click(submitElemement);
+ });
+
+ await waitFor(() => expect(mockDispatch).toHaveBeenCalled());
+ });
+});