From 018155d61fd6d0a1d8bcca08667adcbe5861234b Mon Sep 17 00:00:00 2001 From: Harshil Gupta <144909381+hars-21@users.noreply.github.com> Date: Sun, 12 Jan 2025 04:02:47 +0530 Subject: [PATCH] Improve code coverage in `src/components/UserPortal/Register/Register.tsx` (#3248) * Improve code coverage in register.tsx * Achieved 100% Code coverage --- .../UserPortal/Register/Register.spec.tsx | 98 +++++++++++++------ .../UserPortal/Register/Register.tsx | 7 -- 2 files changed, 66 insertions(+), 39 deletions(-) diff --git a/src/components/UserPortal/Register/Register.spec.tsx b/src/components/UserPortal/Register/Register.spec.tsx index 7ca65f8f0d..d0d43ba3b8 100644 --- a/src/components/UserPortal/Register/Register.spec.tsx +++ b/src/components/UserPortal/Register/Register.spec.tsx @@ -29,6 +29,7 @@ import { vi } from 'vitest'; * GraphQL mock data is used for testing user registration functionality. */ +// GraphQL Mock Data const MOCKS = [ { request: { @@ -54,6 +55,7 @@ const MOCKS = [ }, ]; +// Form Data const formData = { firstName: 'John', lastName: 'Doe', @@ -62,16 +64,26 @@ const formData = { confirmPassword: 'johnDoe', }; -const link = new StaticMockLink(MOCKS, true); +// Additional GraphQL Mock Data for Error Handling +const ERROR_MOCKS = [ + { + request: { + query: SIGNUP_MUTATION, + variables: { + firstName: 'Error', + lastName: 'Test', + email: 'error@test.com', + password: 'password', + }, + }, + error: new Error('GraphQL error occurred'), + }, +]; -async function wait(ms = 100): Promise { - await act(() => { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - }); -} +// Static Mock Link +const link = new StaticMockLink(MOCKS, true); +// Mock toast vi.mock('react-toastify', () => ({ toast: { success: vi.fn(), @@ -80,12 +92,18 @@ vi.mock('react-toastify', () => ({ }, })); +// Mock setCurrentMode function const setCurrentMode: React.Dispatch> = vi.fn(); +// Test setup props const props = { setCurrentMode, }; +async function waitForAsync(): Promise { + await act(() => new Promise((resolve) => setTimeout(resolve, 100))); +} + describe('Testing Register Component [User Portal]', () => { it('Component should be rendered properly', async () => { render( @@ -100,7 +118,7 @@ describe('Testing Register Component [User Portal]', () => { , ); - await wait(); + await waitForAsync(); }); it('Expect the mode to be changed to Login', async () => { @@ -116,7 +134,7 @@ describe('Testing Register Component [User Portal]', () => { , ); - await wait(); + await waitForAsync(); userEvent.click(screen.getByTestId('setLoginBtn')); @@ -136,7 +154,7 @@ describe('Testing Register Component [User Portal]', () => { , ); - await wait(); + await waitForAsync(); userEvent.click(screen.getByTestId('registerBtn')); @@ -156,7 +174,7 @@ describe('Testing Register Component [User Portal]', () => { , ); - await wait(); + await waitForAsync(); userEvent.type(screen.getByTestId('emailInput'), formData.email); userEvent.click(screen.getByTestId('registerBtn')); @@ -177,12 +195,10 @@ describe('Testing Register Component [User Portal]', () => { , ); - await wait(); + await waitForAsync(); userEvent.type(screen.getByTestId('passwordInput'), formData.password); - userEvent.type(screen.getByTestId('emailInput'), formData.email); - userEvent.click(screen.getByTestId('registerBtn')); expect(toast.error).toHaveBeenCalledWith('Please enter valid details.'); @@ -201,20 +217,17 @@ describe('Testing Register Component [User Portal]', () => { , ); - await wait(); + await waitForAsync(); userEvent.type(screen.getByTestId('passwordInput'), formData.password); - userEvent.type(screen.getByTestId('emailInput'), formData.email); - userEvent.type(screen.getByTestId('firstNameInput'), formData.firstName); - userEvent.click(screen.getByTestId('registerBtn')); expect(toast.error).toHaveBeenCalledWith('Please enter valid details.'); }); - test("Expect toast.error to be called if confirmPassword doesn't match with password", async () => { + it("Expect toast.error to be called if confirmPassword doesn't match with password", async () => { render( @@ -227,16 +240,12 @@ describe('Testing Register Component [User Portal]', () => { , ); - await wait(); + await waitForAsync(); userEvent.type(screen.getByTestId('passwordInput'), formData.password); - userEvent.type(screen.getByTestId('emailInput'), formData.email); - userEvent.type(screen.getByTestId('firstNameInput'), formData.firstName); - userEvent.type(screen.getByTestId('lastNameInput'), formData.lastName); - userEvent.click(screen.getByTestId('registerBtn')); expect(toast.error).toHaveBeenCalledWith( @@ -257,27 +266,52 @@ describe('Testing Register Component [User Portal]', () => { , ); - await wait(); + await waitForAsync(); userEvent.type(screen.getByTestId('passwordInput'), formData.password); - userEvent.type( screen.getByTestId('confirmPasswordInput'), formData.confirmPassword, ); - userEvent.type(screen.getByTestId('emailInput'), formData.email); - userEvent.type(screen.getByTestId('firstNameInput'), formData.firstName); - userEvent.type(screen.getByTestId('lastNameInput'), formData.lastName); - userEvent.click(screen.getByTestId('registerBtn')); - await wait(); + await waitForAsync(); expect(toast.success).toHaveBeenCalledWith( 'Successfully registered. Please wait for admin to approve your request.', ); }); + + // Error Test Case + it('Expect toast.error to be called if GraphQL mutation fails', async () => { + render( + + + + + + + + + , + ); + + await waitForAsync(); + + // Fill out the form with error-triggering values + userEvent.type(screen.getByTestId('passwordInput'), 'password'); + userEvent.type(screen.getByTestId('confirmPasswordInput'), 'password'); + userEvent.type(screen.getByTestId('emailInput'), 'error@test.com'); + userEvent.type(screen.getByTestId('firstNameInput'), 'Error'); + userEvent.type(screen.getByTestId('lastNameInput'), 'Test'); + userEvent.click(screen.getByTestId('registerBtn')); + + await waitForAsync(); + + // Assert that toast.error is called with the error message + expect(toast.error).toHaveBeenCalledWith('GraphQL error occurred'); + }); }); diff --git a/src/components/UserPortal/Register/Register.tsx b/src/components/UserPortal/Register/Register.tsx index 11a810c955..dffb83b002 100644 --- a/src/components/UserPortal/Register/Register.tsx +++ b/src/components/UserPortal/Register/Register.tsx @@ -76,7 +76,6 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { toast.success(t('afterRegister') as string); // Success message // Reset form fields - /* istanbul ignore next */ setRegisterVariables({ firstName: '', lastName: '', @@ -86,7 +85,6 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { }); } catch (error: unknown) { // Handle any errors during registration - /* istanbul ignore next */ errorHandler(t, error); } } @@ -96,7 +94,6 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { * Updates the state with the first name input value. * @param e - Change event from the input element */ - /* istanbul ignore next */ const handleFirstName = (e: ChangeEvent): void => { const firstName = e.target.value; setRegisterVariables({ ...registerVariables, firstName }); @@ -106,7 +103,6 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { * Updates the state with the last name input value. * @param e - Change event from the input element */ - /* istanbul ignore next */ const handleLastName = (e: ChangeEvent): void => { const lastName = e.target.value; setRegisterVariables({ ...registerVariables, lastName }); @@ -116,7 +112,6 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { * Updates the state with the email input value. * @param e - Change event from the input element */ - /* istanbul ignore next */ const handleEmailChange = (e: ChangeEvent): void => { const email = e.target.value; setRegisterVariables({ ...registerVariables, email }); @@ -126,7 +121,6 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { * Updates the state with the password input value. * @param e - Change event from the input element */ - /* istanbul ignore next */ const handlePasswordChange = (e: ChangeEvent): void => { const password = e.target.value; @@ -137,7 +131,6 @@ export default function register(props: InterfaceRegisterProps): JSX.Element { * Updates the state with the confirm password input value. * @param e - Change event from the input element */ - /* istanbul ignore next */ const handleConfirmPasswordChange = ( e: ChangeEvent, ): void => {