Skip to content

Commit

Permalink
fix-#6: integration test completed for signin component (#413)
Browse files Browse the repository at this point in the history
  • Loading branch information
krishnaacharyaa authored Jul 10, 2024
2 parents c7df8ad + 0447008 commit ddb013b
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 21 deletions.
2 changes: 1 addition & 1 deletion backend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const app = express();
app.use(
cors({
// added origin
origin: FRONTEND_URL,
origin: [FRONTEND_URL, 'http://localhost:3000'],
credentials: true,
})
);
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/__tests__/integration-test/signin/client-utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { render } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import Signin from '@/pages/signin-page';
import {
PASSWORDINPUT_PLACEHOLDER,
SIGNINBUTTON_TEXT,
SIGNIN_EMAIL_PLACEHOLDER,
} from '@/constants/images';

export const formSetup = () => {
const form = render(
<BrowserRouter>
<Signin />
</BrowserRouter>
);

const usernameInput = form.getByPlaceholderText(SIGNIN_EMAIL_PLACEHOLDER);

const passwordInput = form.getByPlaceholderText(PASSWORDINPUT_PLACEHOLDER);

const signinbuttonText = form.getByText(SIGNINBUTTON_TEXT);

if (
!(usernameInput instanceof HTMLInputElement) ||
!(passwordInput instanceof HTMLInputElement) ||
!(signinbuttonText instanceof HTMLButtonElement)
) {
throw new Error('Issue during test setup, some input elemnts are not rendered');
}

return { form, usernameInput, passwordInput, signinbuttonText };
};
70 changes: 70 additions & 0 deletions frontend/src/__tests__/integration-test/signin/signin.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { waitFor } from '@testing-library/react';
import { vi } from 'vitest';
import userEvent from '@testing-library/user-event';
import { formSetup } from './client-utils';
import { toast } from 'react-toastify';

interface sucessdata {
status: number;
message: string;
}

interface errordata {
status: number;
message: string;
}

interface Messages {
success: {
render: (data: { data: sucessdata }) => void;
};
error: {
render: (error: { error: errordata }) => void;
};
}

const mockedUseNavigate = vi.fn();

// Mocking the useNavigate hook from React Router DOM
vi.mock('react-router-dom', async () => {
const mod = await vi.importActual<typeof import('react-router-dom')>('react-router-dom');
return {
...mod,
useNavigate: () => mockedUseNavigate,
};
});

// Mock react-toastify's toast.promise
vi.mock('react-toastify', () => ({
toast: {
promise: vi.fn((promise: Promise<sucessdata>, messages: Messages) => {
return promise.then(
(data: sucessdata) => {
messages.success.render({ data });
return data;
},
(error: errordata) => {
messages.error.render({ error });
throw error;
}
);
}),
},
}));

describe('Integration Tests : Signin Component', async () => {
test('Signin : Sucess - Sucessfully sign in', async () => {
const mockedToastPromise = toast.promise;
const userActions = userEvent.setup();
const { usernameInput, passwordInput, signinbuttonText } = await formSetup();

await userActions.type(usernameInput, '[email protected]');
await userActions.type(passwordInput, 'Test@1234');
await userActions.click(signinbuttonText);

await waitFor(() => {
expect(mockedToastPromise).toHaveBeenCalled();
expect(mockedUseNavigate).toHaveBeenCalled();
});
});
});
2 changes: 1 addition & 1 deletion frontend/src/__tests__/mocks/handeler-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { http, HttpResponse } from 'msw';

export const handlers = [
http.post('http://localhost:5000/api/auth/email-password/signup', () => {
http.post('http://localhost:8080/api/auth/email-password/signup', () => {
return new HttpResponse(null, {
status: 200,
});
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/__tests__/unit-test/signup/client-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Signup from '@/pages/signup-page';
import {
CONFIRMPASSWORD_PLACEHOLDER,
EMAILINPUT_PLACEHOLDER,
NAME,
PASSWORDINPUT_PLACEHOLDER,
SIGNUPBUTTON_TEXT,
USERNAME_PLACEHOLDER,
Expand All @@ -15,14 +16,15 @@ export const formSetup = () => {
<Signup />
</BrowserRouter>
);

const nameInput = form.getByPlaceholderText(NAME);
const usernameInput = form.getByPlaceholderText(USERNAME_PLACEHOLDER);
const emailInput = form.getByPlaceholderText(EMAILINPUT_PLACEHOLDER);
const passwordInput = form.getByPlaceholderText(PASSWORDINPUT_PLACEHOLDER);
const confirmpasswordInput = form.getByPlaceholderText(CONFIRMPASSWORD_PLACEHOLDER);
const signupbuttonText = form.getByText(SIGNUPBUTTON_TEXT);

if (
!(nameInput instanceof HTMLInputElement) ||
!(usernameInput instanceof HTMLInputElement) ||
!(emailInput instanceof HTMLInputElement) ||
!(passwordInput instanceof HTMLInputElement) ||
Expand All @@ -32,5 +34,13 @@ export const formSetup = () => {
throw new Error('Issue during test setup, some input elemnts are not rendered');
}

return { form, usernameInput, emailInput, passwordInput, confirmpasswordInput, signupbuttonText };
return {
form,
usernameInput,
emailInput,
passwordInput,
confirmpasswordInput,
signupbuttonText,
nameInput,
};
};
79 changes: 67 additions & 12 deletions frontend/src/__tests__/unit-test/signup/signup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,30 @@ import {
EMAIL_EMPTY_ERRORMESSAGE,
INVALID_CONFIRMPWD_ERRORMESSAGE,
INVALID_PWD_ERRORMESSAGE,
INVALID_USERNAME_ERRORMESSAGE,
NAME_EMPTY_ERRORMESSAGE,
PASSWORD_EMPTY_ERRORMESSAGE,
USERNAME_EMPTY_ERRORMESSAGE,
} from '@/constants/images';
import { toast } from 'react-toastify';

interface sucessdata {
status: number;
message: string;
}

interface errordata {
status: number;
message: string;
}

interface Messages {
success: {
render: (data: { data: sucessdata }) => void;
};
error: {
render: (error: { error: errordata }) => void;
};
}
const mockedUseNavigate = vi.fn();
// Mocking the useNavigate hook from React Router DOM
vi.mock('react-router-dom', async () => {
Expand All @@ -21,6 +41,24 @@ vi.mock('react-router-dom', async () => {
};
});

// Mock react-toastify's toast.promise
vi.mock('react-toastify', () => ({
toast: {
promise: vi.fn((promise: Promise<sucessdata>, messages: Messages) => {
return promise.then(
(data: sucessdata) => {
messages.success.render({ data });
return data;
},
(error: errordata) => {
messages.error.render({ error });
throw error;
}
);
}),
},
}));

describe('Unit Tests : Signup Component', async () => {
test('Signup : Failure - Invalid Email Address', async () => {
const userActions = userEvent.setup();
Expand All @@ -42,17 +80,19 @@ describe('Unit Tests : Signup Component', async () => {
passwordInput,
confirmpasswordInput,
signupbuttonText,
nameInput,
} = await formSetup();
await userActions.type(usernameInput, 'aryastark');
await userActions.type(nameInput, 'arya');
await userActions.type(emailInput, '[email protected]');
await userActions.type(passwordInput, '12345678');
await userActions.type(confirmpasswordInput, '1234');
await userActions.type(passwordInput, 'Test@1234');
await userActions.type(confirmpasswordInput, 'Tesr@1897');
await userActions.click(signupbuttonText);
await waitFor(() => {
expect(form.getByText(INVALID_CONFIRMPWD_ERRORMESSAGE)).toBeInTheDocument();
});
});

/*
test('Signup : Failure - Invalid Username', async () => {
const userActions = userEvent.setup();
const {
Expand All @@ -62,23 +102,27 @@ describe('Unit Tests : Signup Component', async () => {
passwordInput,
confirmpasswordInput,
signupbuttonText,
nameInput
} = await formSetup();
await userActions.type(usernameInput, 'ary');
await userActions.type(nameInput,'arya')
await userActions.type(emailInput, '[email protected]');
await userActions.type(passwordInput, '12345678');
await userActions.type(confirmpasswordInput, '12345678');
await userActions.type(passwordInput, 'Test@1234');
await userActions.type(confirmpasswordInput, 'Test@1234');
await userActions.click(signupbuttonText);
await waitFor(() => {
expect(form.getByText(INVALID_USERNAME_ERRORMESSAGE)).toBeInTheDocument();
});
});
*/

test('Signup : Failure - Form is submitted without any values', async () => {
const userActions = userEvent.setup();
const { form, signupbuttonText } = await formSetup();
await userActions.click(signupbuttonText);
await waitFor(() => {
expect(form.getByText(USERNAME_EMPTY_ERRORMESSAGE)).toBeInTheDocument();
expect(form.getByText(NAME_EMPTY_ERRORMESSAGE)).toBeInTheDocument();
expect(form.getByText(EMAIL_EMPTY_ERRORMESSAGE)).toBeInTheDocument();
expect(form.getByText(PASSWORD_EMPTY_ERRORMESSAGE)).toBeInTheDocument();
expect(form.getByText(CONFIRMPASSWORD_EMPTY_ERRORMESSAGE)).toBeInTheDocument();
Expand All @@ -94,32 +138,43 @@ describe('Unit Tests : Signup Component', async () => {
passwordInput,
confirmpasswordInput,
signupbuttonText,
nameInput,
} = await formSetup();
await userActions.type(usernameInput, 'abcd');
await userActions.type(nameInput, 'ab');
await userActions.type(emailInput, '[email protected]');
await userActions.type(passwordInput, '123');
await userActions.type(confirmpasswordInput, '1234');
await userActions.click(signupbuttonText);
await waitFor(() => {
expect(form.getByText(INVALID_USERNAME_ERRORMESSAGE)).toBeInTheDocument();
expect(form.getByText(NAME_EMPTY_ERRORMESSAGE)).toBeInTheDocument();
expect(form.getByText(INVALID_PWD_ERRORMESSAGE)).toBeInTheDocument();
expect(form.getByText(INVALID_CONFIRMPWD_ERRORMESSAGE)).toBeInTheDocument();
});
});

test('should call the signup api when all the input values are valid and should redirect to home page', async () => {
const userActions = userEvent.setup();
const mockedToastPromise = toast.promise;

const { usernameInput, emailInput, passwordInput, confirmpasswordInput, signupbuttonText } =
await formSetup();
const {
usernameInput,
emailInput,
passwordInput,
confirmpasswordInput,
signupbuttonText,
nameInput,
} = await formSetup();
await userActions.type(nameInput, 'arya');
await userActions.type(usernameInput, 'aryastark');
await userActions.type(emailInput, '[email protected]');
await userActions.type(passwordInput, '123456789');
await userActions.type(confirmpasswordInput, '123456789');
await userActions.type(passwordInput, 'Test@1234');
await userActions.type(confirmpasswordInput, 'Test@1234');
await userActions.click(signupbuttonText);

await waitFor(() => {
expect(mockedUseNavigate).toHaveBeenCalledTimes(1);
expect(mockedToastPromise).toHaveBeenCalled();
expect(mockedUseNavigate).toHaveBeenCalled();
});
});
});
13 changes: 9 additions & 4 deletions frontend/src/constants/images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@ export const imageUrls: string[] = [
'https://i.ibb.co/qxFMj1H/sunset-horizon-clean-sky-nature.webp',
];
export const USERNAME_EMPTY_ERRORMESSAGE = 'Username is required';
export const EMAIL_EMPTY_ERRORMESSAGE = 'Email is required';
export const PASSWORD_EMPTY_ERRORMESSAGE = 'Password is required';
export const NAME_EMPTY_ERRORMESSAGE = 'Name must be at least 3 character';
export const EMAIL_EMPTY_ERRORMESSAGE = 'Enter valid email';
export const PASSWORD_EMPTY_ERRORMESSAGE = 'Password must be at least 8 character';
export const CONFIRMPASSWORD_EMPTY_ERRORMESSAGE = 'Confirm Password is required';

export const NAME = 'Name';
export const USERNAME_PLACEHOLDER = 'Username';
export const EMAILINPUT_PLACEHOLDER = 'Email';
export const PASSWORDINPUT_PLACEHOLDER = 'Password';
export const CONFIRMPASSWORD_PLACEHOLDER = 'Confirm Password';
export const SIGNUPBUTTON_TEXT = 'Sign Up';

export const SIGNINBUTTON_TEXT = 'Log In';
export const SIGNIN_EMAIL_PLACEHOLDER = 'Username or Email';

export const INVALID_USERNAME_ERRORMESSAGE = 'Username must be at least 5 characters long';
export const INVALID_EMAIL_ERRORMESSAGE = 'Invalid email address';
export const INVALID_PWD_ERRORMESSAGE = 'Password must be at least 8 characters long';
export const INVALID_CONFIRMPWD_ERRORMESSAGE = 'Passwords do not match';
export const INVALID_PWD_ERRORMESSAGE = 'Password must be at least 8 character';
export const INVALID_CONFIRMPWD_ERRORMESSAGE = 'Confirm Password do not match';
2 changes: 1 addition & 1 deletion frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default defineConfig({
reporters: ['verbose'],
exclude: [
...configDefaults.exclude,
'./src/__tests__/integration/home.test.tsx',
'./src/__tests__/integration-test/home.test.tsx',
'./src/__tests__/App.test.tsx',
],

Expand Down

0 comments on commit ddb013b

Please sign in to comment.