Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: my settings page tests #5499

Merged
merged 7 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions frontend/src/container/MySettings/Password/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,23 @@ function PasswordContainer(): JSX.Element {
return (
<Card>
<Space direction="vertical" size="small">
<Typography.Title level={4} style={{ marginTop: 0 }}>
<Typography.Title
level={4}
style={{ marginTop: 0 }}
data-testid="change-password-header"
>
{t('change_password', {
ns: 'settings',
})}
</Typography.Title>
<Space direction="vertical">
<Typography>
<Typography data-testid="current-password-label">
{t('current_password', {
ns: 'settings',
})}
</Typography>
<Password
data-testid="current-password-textbox"
disabled={isLoading}
placeholder={defaultPlaceHolder}
onChange={(event): void => {
Expand All @@ -111,12 +116,13 @@ function PasswordContainer(): JSX.Element {
/>
</Space>
<Space direction="vertical">
<Typography>
<Typography data-testid="new-password-label">
{t('new_password', {
ns: 'settings',
})}
</Typography>
<Password
data-testid="new-password-textbox"
disabled={isLoading}
placeholder={defaultPlaceHolder}
onChange={(event): void => {
Expand All @@ -129,6 +135,7 @@ function PasswordContainer(): JSX.Element {
<Space>
{isPasswordPolicyError && (
<Typography.Paragraph
data-testid="validation-message"
style={{
color: '#D89614',
marginTop: '0.50rem',
Expand All @@ -143,8 +150,13 @@ function PasswordContainer(): JSX.Element {
loading={isLoading}
onClick={onChangePasswordClickHandler}
type="primary"
data-testid="update-password-button"
>
<Save size={12} style={{ marginRight: '8px' }} />{' '}
<Save
size={12}
style={{ marginRight: '8px' }}
data-testid="update-password-icon"
/>{' '}
{t('change_password', {
ns: 'settings',
})}
Expand Down
30 changes: 25 additions & 5 deletions frontend/src/container/MySettings/UserInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,11 @@ function UserInfo(): JSX.Element {

<Flex gap={16}>
<Space>
<Typography className="userInfo-label">Name</Typography>
<Typography className="userInfo-label" data-testid="name-label">
Name
</Typography>
<NameInput
data-testid="name-textbox"
placeholder="Your Name"
onChange={(event): void => {
setChangedName(event.target.value);
Expand All @@ -102,20 +105,37 @@ function UserInfo(): JSX.Element {
loading={loading}
disabled={loading}
onClick={onClickUpdateHandler}
data-testid="update-name-button"
type="primary"
>
<PencilIcon size={12} /> Update
</Button>
</Flex>

<Space>
<Typography className="userInfo-label"> Email </Typography>
<Input className="userInfo-value" value={user.email} disabled />
<Typography className="userInfo-label" data-testid="email-label">
{' '}
Email{' '}
</Typography>
<Input
className="userInfo-value"
data-testid="email-textbox"
value={user.email}
disabled
/>
</Space>

<Space>
<Typography className="userInfo-label"> Role </Typography>
<Input className="userInfo-value" value={role || ''} disabled />
<Typography className="userInfo-label" data-testid="role-label">
{' '}
Role{' '}
</Typography>
<Input
className="userInfo-value"
value={role || ''}
disabled
data-testid="role-textbox"
/>
</Space>
</Space>
</Card>
Expand Down
219 changes: 219 additions & 0 deletions frontend/src/container/MySettings/__tests__/MySettings.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import MySettingsContainer from 'container/MySettings';
import { act, fireEvent, render, screen, waitFor } from 'tests/test-utils';

const toggleThemeFunction = jest.fn();

jest.mock('hooks/useDarkMode', () => ({
__esModule: true,
useIsDarkMode: jest.fn(() => ({
toggleTheme: toggleThemeFunction,
})),
default: jest.fn(() => ({
toggleTheme: toggleThemeFunction,
})),
}));

const errorNotification = jest.fn();
const successNotification = jest.fn();
jest.mock('hooks/useNotifications', () => ({
__esModule: true,
useNotifications: jest.fn(() => ({
notifications: {
error: errorNotification,
success: successNotification,
},
})),
}));

enum ThemeOptions {
Dark = 'Dark',
Light = 'Light',
}

describe('MySettings Flows', () => {
beforeEach(() => {
jest.clearAllMocks();

render(<MySettingsContainer />);
});

describe('Dark/Light Theme Switch', () => {
it('Should display Dark and Light theme buttons properly', async () => {
expect(screen.getByText('Dark')).toBeInTheDocument();

const darkThemeIcon = screen.getByTestId('dark-theme-icon');
expect(darkThemeIcon).toBeInTheDocument();
expect(darkThemeIcon.tagName).toBe('svg');

expect(screen.getByText('Light')).toBeInTheDocument();
const lightThemeIcon = screen.getByTestId('light-theme-icon');
expect(lightThemeIcon).toBeInTheDocument();
expect(lightThemeIcon.tagName).toBe('svg');
});

it('Should activate Dark and Light buttons on click', async () => {
const initialSelectedOption = screen.getByRole('radio', {
name: ThemeOptions.Dark,
});
expect(initialSelectedOption).toBeChecked();

const newThemeOption = screen.getByRole('radio', {
name: ThemeOptions.Light,
});
fireEvent.click(newThemeOption);

expect(newThemeOption).toBeChecked();
});

it('Should switch the them on clicking Light theme', async () => {
const lightThemeOption = screen.getByRole('radio', {
name: /light/i,
});
fireEvent.click(lightThemeOption);

await waitFor(() => {
expect(toggleThemeFunction).toBeCalled();
ahmadshaheer marked this conversation as resolved.
Show resolved Hide resolved
});
});
});

describe('User Details Form', () => {
it('Should properly display the User Details Form', () => {
const userDetailsHeader = screen.getByRole('heading', {
name: /user details/i,
});
const nameLabel = screen.getByTestId('name-label');
const nameTextbox = screen.getByTestId('name-textbox');
const updateNameButton = screen.getByTestId('update-name-button');
const emailLabel = screen.getByTestId('email-label');
const emailTextbox = screen.getByTestId('email-textbox');
const roleLabel = screen.getByTestId('role-label');
const roleTextbox = screen.getByTestId('role-textbox');

expect(userDetailsHeader).toBeInTheDocument();
expect(nameLabel).toBeInTheDocument();
expect(nameTextbox).toBeInTheDocument();
expect(updateNameButton).toBeInTheDocument();
expect(emailLabel).toBeInTheDocument();
expect(emailTextbox).toBeInTheDocument();
expect(roleLabel).toBeInTheDocument();
expect(roleTextbox).toBeInTheDocument();
});

it('Should update the name on clicking Update button', async () => {
const nameTextbox = screen.getByTestId('name-textbox');
const updateNameButton = screen.getByTestId('update-name-button');

act(() => {
fireEvent.change(nameTextbox, { target: { value: 'New Name' } });
});

fireEvent.click(updateNameButton);

await waitFor(() =>
expect(successNotification).toHaveBeenCalledWith({
message: 'success',
}),
);
});
});

describe('Reset password', () => {
let currentPasswordTextbox: Node | Window;
let newPasswordTextbox: Node | Window;
let submitButtonElement: HTMLElement;

beforeEach(() => {
currentPasswordTextbox = screen.getByTestId('current-password-textbox');
newPasswordTextbox = screen.getByTestId('new-password-textbox');
submitButtonElement = screen.getByTestId('update-password-button');
});

it('Should properly display the Password Reset Form', () => {
const passwordResetHeader = screen.getByTestId('change-password-header');
expect(passwordResetHeader).toBeInTheDocument();

const currentPasswordLabel = screen.getByTestId('current-password-label');
expect(currentPasswordLabel).toBeInTheDocument();

expect(currentPasswordTextbox).toBeInTheDocument();

const newPasswordLabel = screen.getByTestId('new-password-label');
expect(newPasswordLabel).toBeInTheDocument();

expect(newPasswordTextbox).toBeInTheDocument();
expect(submitButtonElement).toBeInTheDocument();

const savePasswordIcon = screen.getByTestId('update-password-icon');
expect(savePasswordIcon).toBeInTheDocument();
expect(savePasswordIcon.tagName).toBe('svg');
});

it('Should display validation error if password is less than 8 characters', async () => {
const currentPasswordTextbox = screen.getByTestId(
'current-password-textbox',
);
act(() => {
fireEvent.change(currentPasswordTextbox, { target: { value: '123' } });
});
const validationMessage = await screen.findByTestId('validation-message');

await waitFor(() => {
expect(validationMessage).toHaveTextContent(
'Password must a have minimum of 8 characters',
);
});
});

test("Should display 'inavlid credentials' error if different current and new passwords are provided", async () => {
act(() => {
fireEvent.change(currentPasswordTextbox, {
target: { value: '123456879' },
});

fireEvent.change(newPasswordTextbox, { target: { value: '123456789' } });
});

fireEvent.click(submitButtonElement);

await waitFor(() => expect(errorNotification).toHaveBeenCalled());
});

it('Should check if the "Change Password" button is disabled in case current / new password is less than 8 characters', () => {
act(() => {
fireEvent.change(currentPasswordTextbox, {
target: { value: '123' },
});
fireEvent.change(newPasswordTextbox, { target: { value: '123' } });
});

expect(submitButtonElement).toBeDisabled();
});

test("Should check if 'Change Password' button is enabled when password is at least 8 characters ", async () => {
expect(submitButtonElement).toBeDisabled();

act(() => {
fireEvent.change(currentPasswordTextbox, {
target: { value: '123456789' },
});
fireEvent.change(newPasswordTextbox, { target: { value: '1234567890' } });
});

expect(submitButtonElement).toBeEnabled();
});

test("Should check if 'Change Password' button is disabled when current and new passwords are the same ", async () => {
expect(submitButtonElement).toBeDisabled();

act(() => {
fireEvent.change(currentPasswordTextbox, {
target: { value: '123456789' },
});
fireEvent.change(newPasswordTextbox, { target: { value: '123456789' } });
});

expect(submitButtonElement).toBeDisabled();
});
});
});
12 changes: 9 additions & 3 deletions frontend/src/container/MySettings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ function MySettings(): JSX.Element {
{
label: (
<div className="theme-option">
<Moon size={12} /> Dark{' '}
<Moon data-testid="dark-theme-icon" size={12} /> Dark{' '}
</div>
),
value: 'dark',
},
{
label: (
<div className="theme-option">
<Sun size={12} /> Light{' '}
<Sun size={12} data-testid="light-theme-icon" /> Light{' '}
</div>
),
value: 'light',
Expand Down Expand Up @@ -63,6 +63,7 @@ function MySettings(): JSX.Element {
value={theme}
optionType="button"
buttonStyle="solid"
data-testid="theme-selector"
/>
</div>

Expand All @@ -74,7 +75,12 @@ function MySettings(): JSX.Element {
<Password />
</div>

<Button className="flexBtn" onClick={(): void => Logout()} type="primary">
<Button
className="flexBtn"
onClick={(): void => Logout()}
type="primary"
data-testid="logout-button"
>
<LogOut size={12} /> Logout
</Button>
</Space>
Expand Down
Loading
Loading