From 3b4916853c4fb91c96e7b60d896f2dcf801589c2 Mon Sep 17 00:00:00 2001 From: Tharun Rajendran Date: Wed, 30 Jun 2021 20:41:27 +0530 Subject: [PATCH] chore: Signup Page Component tests (#36279) * added tests for SignupPage component * added tests for VerifyEmailPage component * addressed review changes * removed id for button and followed consistent id naming pattern --- .../components/Signup/SignupPage.test.tsx | 119 ++++++++++++++++++ .../app/core/components/Signup/SignupPage.tsx | 13 +- .../core/components/Signup/VerifyEmail.tsx | 16 ++- .../Signup/VerifyEmailPage.test.tsx | 74 +++++++++++ 4 files changed, 214 insertions(+), 8 deletions(-) create mode 100644 public/app/core/components/Signup/SignupPage.test.tsx create mode 100644 public/app/core/components/Signup/VerifyEmailPage.test.tsx diff --git a/public/app/core/components/Signup/SignupPage.test.tsx b/public/app/core/components/Signup/SignupPage.test.tsx new file mode 100644 index 00000000000..3e16b268418 --- /dev/null +++ b/public/app/core/components/Signup/SignupPage.test.tsx @@ -0,0 +1,119 @@ +import React from 'react'; +import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { getRouteComponentProps } from 'app/core/navigation/__mocks__/routeProps'; + +import { SignupPage } from './SignupPage'; + +const postMock = jest.fn(); +jest.mock('@grafana/runtime', () => ({ + getBackendSrv: () => ({ + post: postMock, + }), +})); + +jest.mock('app/core/config', () => { + return { + loginError: false, + buildInfo: { + version: 'v1.0', + commit: '1', + env: 'production', + edition: 'Open Source', + isEnterprise: false, + }, + licenseInfo: { + stateInfo: '', + licenseUrl: '', + }, + appSubUrl: '', + getConfig: () => ({ + autoAssignOrg: false, + verifyEmailEnabled: true, + appSubUrl: '', + }), + }; +}); + +const props = { + email: '', + code: '', + ...getRouteComponentProps(), +}; + +describe('Signup Page', () => { + it('renders correctly', () => { + render(); + expect(screen.getByRole('heading', { name: 'Welcome to Grafana' })).toBeInTheDocument(); + + expect(screen.getByRole('textbox', { name: 'Your name' })).toBeInTheDocument(); + expect(screen.getByRole('textbox', { name: 'Email' })).toBeInTheDocument(); + expect(screen.getByRole('textbox', { name: 'Org. name' })).toBeInTheDocument(); + expect(screen.getByRole('textbox', { name: /Email verification code/i })).toBeInTheDocument(); + + expect(screen.getByLabelText('Password')).toBeInTheDocument(); + expect(screen.getByLabelText('Confirm password')).toBeInTheDocument(); + + expect(screen.getByRole('button', { name: 'Submit' })).toBeInTheDocument(); + + expect(screen.getByRole('link', { name: 'Back to login' })).toBeInTheDocument(); + expect(screen.getByRole('link', { name: 'Back to login' })).toHaveAttribute('href', '/login'); + }); + it('should pass validation checks for email field', async () => { + render(); + + fireEvent.click(screen.getByRole('button', { name: 'Submit' })); + expect(await screen.findByText('Email is required')).toBeInTheDocument(); + + await act(async () => { + await userEvent.type(screen.getByRole('textbox', { name: 'Email' }), 'test'); + expect(screen.queryByText('Email is invalid')).toBeInTheDocument(); + + await userEvent.type(screen.getByRole('textbox', { name: 'Email' }), 'test@gmail.com'); + expect(screen.queryByText('Email is invalid')).not.toBeInTheDocument(); + }); + }); + it('should pass validation checks for password and confirm password field', async () => { + render(); + + fireEvent.click(screen.getByRole('button', { name: 'Submit' })); + expect(await screen.findByText('Password is required')).toBeInTheDocument(); + expect(await screen.findByText('Confirmed password is required')).toBeInTheDocument(); + + await act(async () => { + await userEvent.type(screen.getByLabelText('Password'), 'admin'); + await userEvent.type(screen.getByLabelText('Confirm password'), 'a'); + expect(screen.queryByText('Passwords must match!')).toBeInTheDocument(); + + await userEvent.type(screen.getByLabelText('Confirm password'), 'dmin'); + expect(screen.queryByText('Passwords must match!')).not.toBeInTheDocument(); + }); + }); + it('should navigate to default url if signup is successful', async () => { + Object.defineProperty(window, 'location', { + value: { + assign: jest.fn(), + }, + }); + postMock.mockResolvedValueOnce({ message: 'Logged in' }); + render(); + + await userEvent.type(screen.getByRole('textbox', { name: 'Your name' }), 'test-user'); + await userEvent.type(screen.getByRole('textbox', { name: 'Email' }), 'test@gmail.com'); + await userEvent.type(screen.getByLabelText('Password'), 'admin'); + await userEvent.type(screen.getByLabelText('Confirm password'), 'admin'); + fireEvent.click(screen.getByRole('button', { name: 'Submit' })); + + await waitFor(() => + expect(postMock).toHaveBeenCalledWith('/api/user/signup/step2', { + code: '', + email: 'test@gmail.com', + name: 'test-user', + orgName: '', + password: 'admin', + username: 'test@gmail.com', + }) + ); + expect(window.location.assign).toHaveBeenCalledWith('/'); + }); +}); diff --git a/public/app/core/components/Signup/SignupPage.tsx b/public/app/core/components/Signup/SignupPage.tsx index 31e52133c0d..6eac404d1c6 100644 --- a/public/app/core/components/Signup/SignupPage.tsx +++ b/public/app/core/components/Signup/SignupPage.tsx @@ -46,9 +46,9 @@ export const SignupPage: FC = (props) => { }); if (response.code === 'redirect-to-select-org') { - window.location.href = getConfig().appSubUrl + '/profile/select-org?signup=1'; + window.location.assign(getConfig().appSubUrl + '/profile/select-org?signup=1'); } - window.location.href = getConfig().appSubUrl + '/'; + window.location.assign(getConfig().appSubUrl + '/'); }; const defaultValues = { @@ -63,10 +63,11 @@ export const SignupPage: FC = (props) => { {({ errors, register, getValues }: FormAPI) => ( <> - + = (props) => { {!getConfig().autoAssignOrg && ( - + )} {getConfig().verifyEmailEnabled && ( - + )} = (props) => { v === getValues().password || 'Passwords must match!', diff --git a/public/app/core/components/Signup/VerifyEmail.tsx b/public/app/core/components/Signup/VerifyEmail.tsx index 053936f51b7..788f4462ac8 100644 --- a/public/app/core/components/Signup/VerifyEmail.tsx +++ b/public/app/core/components/Signup/VerifyEmail.tsx @@ -44,10 +44,20 @@ export const VerifyEmail: FC = () => { - + diff --git a/public/app/core/components/Signup/VerifyEmailPage.test.tsx b/public/app/core/components/Signup/VerifyEmailPage.test.tsx new file mode 100644 index 00000000000..5e8783f1488 --- /dev/null +++ b/public/app/core/components/Signup/VerifyEmailPage.test.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { VerifyEmailPage } from './VerifyEmailPage'; + +const postMock = jest.fn(); +jest.mock('@grafana/runtime', () => ({ + getBackendSrv: () => ({ + post: postMock, + }), +})); + +jest.mock('app/core/config', () => { + return { + buildInfo: { + version: 'v1.0', + commit: '1', + env: 'production', + edition: 'Open Source', + isEnterprise: false, + }, + licenseInfo: { + stateInfo: '', + licenseUrl: '', + }, + getConfig: () => ({ + verifyEmailEnabled: true, + appSubUrl: '', + }), + }; +}); + +describe('VerifyEmail Page', () => { + it('renders correctly', () => { + render(); + expect(screen.getByText('Verify Email')).toBeInTheDocument(); + expect(screen.getByRole('textbox', { name: /Email/i })).toBeInTheDocument(); + + expect(screen.getByRole('button', { name: 'Send verification email' })).toBeInTheDocument(); + + expect(screen.getByRole('link', { name: 'Back to login' })).toBeInTheDocument(); + expect(screen.getByRole('link', { name: 'Back to login' })).toHaveAttribute('href', '/login'); + }); + it('should pass validation checks for email field', async () => { + render(); + + fireEvent.click(screen.getByRole('button', { name: 'Send verification email' })); + expect(await screen.findByText('Email is required')).toBeInTheDocument(); + + await act(async () => { + await userEvent.type(screen.getByRole('textbox', { name: /Email/i }), 'test'); + expect(screen.queryByText('Email is invalid')).toBeInTheDocument(); + + await userEvent.type(screen.getByRole('textbox', { name: /Email/i }), 'test@gmail.com'); + expect(screen.queryByText('Email is invalid')).not.toBeInTheDocument(); + }); + }); + it('should show complete signup if email-verification is successful', async () => { + postMock.mockResolvedValueOnce({ message: 'SignUpCreated' }); + render(); + + await userEvent.type(screen.getByRole('textbox', { name: /Email/i }), 'test@gmail.com'); + fireEvent.click(screen.getByRole('button', { name: 'Send verification email' })); + + await waitFor(() => + expect(postMock).toHaveBeenCalledWith('/api/user/signup', { + email: 'test@gmail.com', + }) + ); + expect(screen.getByRole('link', { name: 'Complete Signup' })).toBeInTheDocument(); + expect(screen.getByRole('link', { name: 'Complete Signup' })).toHaveAttribute('href', '/signup'); + }); +});