From 7f8d00c13e65c90f5565c006abb529326e73371e Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Wed, 28 Feb 2024 18:05:11 +0100 Subject: [PATCH 01/12] refactor login form --- .../src/app/auth/login/page.tsx | 38 +++++--- .../components/organisms/Auth/AuthStatus.tsx | 14 +++ .../components/organisms/Auth/LoginForm.tsx | 97 +++++++++++-------- 3 files changed, 92 insertions(+), 57 deletions(-) create mode 100644 apps/nextjs-website/src/components/organisms/Auth/AuthStatus.tsx diff --git a/apps/nextjs-website/src/app/auth/login/page.tsx b/apps/nextjs-website/src/app/auth/login/page.tsx index 38b177e77..120f1517e 100644 --- a/apps/nextjs-website/src/app/auth/login/page.tsx +++ b/apps/nextjs-website/src/app/auth/login/page.tsx @@ -10,6 +10,7 @@ import ConfirmSignUp from '@/components/organisms/Auth/ConfirmSignUp'; import { useRouter, useSearchParams } from 'next/navigation'; import PageBackgroundWrapper from '@/components/atoms/PageBackgroundWrapper/PageBackgroundWrapper'; import { SignInOpts } from '@aws-amplify/auth/lib/types'; +import AuthStatus from '@/components/organisms/Auth/AuthStatus'; const Login = () => { const router = useRouter(); @@ -17,26 +18,29 @@ const Login = () => { const [user, setUser] = useState(null); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); - + const [submitting, setSubmitting] = useState(false); const [noAccountError, setNoAccountError] = useState(false); const onLogin: LoginFunction = useCallback(async ({ username, password }) => { + setSubmitting(true); setNoAccountError(false); setUsername(username); setPassword(password); - const user = await Auth.signIn({ - username, - password, - } as SignInOpts).catch((error) => { - if (error.code === 'UserNotConfirmedException') { - setUsername(username); - setLogInStep(LoginSteps.CONFIRM_ACCOUNT); - } else { - setNoAccountError(true); - } - return false; - }); + const opts: SignInOpts = { username, password }; + const user = await Auth.signIn(opts) + .catch((error) => { + if (error.code === 'UserNotConfirmedException') { + setUsername(username); + setLogInStep(LoginSteps.CONFIRM_ACCOUNT); + } else { + setNoAccountError(true); + } + return false; + }) + .finally(() => { + setSubmitting(false); + }); setUsername(username); @@ -86,7 +90,13 @@ const Login = () => { spacing={6} > {logInStep === LoginSteps.LOG_IN && ( - + + + )} {logInStep === LoginSteps.MFA_CHALLENGE && ( [context.authStatus]); + + if (authStatus === 'authenticated') { + redirect('/'); + } + + return children; +} diff --git a/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx b/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx index 140a06e7e..a66f19393 100644 --- a/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx +++ b/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx @@ -1,6 +1,4 @@ -'use client'; import { LoginFunction } from '@/lib/types/loginFunction'; -import { useAuthenticator } from '@aws-amplify/ui-react'; import { Visibility, VisibilityOff } from '@mui/icons-material'; import { Box, @@ -22,13 +20,19 @@ import { import { IllusLogin } from '@pagopa/mui-italia'; import { useTranslations } from 'next-intl'; import Link from 'next/link'; -import { redirect } from 'next/navigation'; -import { MouseEvent, useCallback, useEffect, useState } from 'react'; +import { + ChangeEvent, + MouseEvent, + useCallback, + useEffect, + useState, +} from 'react'; import { validateEmail, validateField } from '@/helpers/auth.helpers'; interface LoginFormProps { onLogin: LoginFunction; - noAccount: boolean; + noAccount?: boolean; + submitting?: boolean; } interface LoginFieldsError { @@ -36,29 +40,27 @@ interface LoginFieldsError { password: string | null; } -const LoginForm = ({ onLogin, noAccount = false }: LoginFormProps) => { +const LoginForm = ({ + onLogin, + noAccount = false, + submitting = false, +}: LoginFormProps) => { const signUp = useTranslations('auth.signUp'); const login = useTranslations('auth.login'); const shared = useTranslations('shared'); - const errors = useTranslations('errors'); const { palette } = useTheme(); - const [username, setUsername] = useState(''); - const [password, setPassword] = useState(''); - const [showPassword, setShowPassword] = useState(false); - const [submitting, setSubmitting] = useState(false); - - const { authStatus } = useAuthenticator((context) => [context.authStatus]); + const [formData, setFormData] = useState({ + username: '', + password: '', + }); + const [showPassword, setShowPassword] = useState(false); const [fieldErrors, setFieldErrors] = useState({ email: null, password: null, }); - if (authStatus === 'authenticated') { - redirect('/'); - } - const handleClickShowPassword = useCallback( () => setShowPassword((show) => !show), [] @@ -71,17 +73,21 @@ const LoginForm = ({ onLogin, noAccount = false }: LoginFormProps) => { [] ); + const handleChangeInput = useCallback((e: ChangeEvent) => { + setFormData((prev) => ({ ...prev, [e.target.name]: e.target.value })); + }, []); + const validateForm = useCallback(() => { - const emailError = validateEmail(username); + const emailError = validateEmail(formData.username); + const passwordError = validateField(formData.password); - const passwordError = validateField(password); setFieldErrors({ email: emailError ? shared(emailError) : null, password: passwordError ? shared(passwordError) : null, }); return !emailError && !passwordError; - }, [username, shared, password]); + }, [shared, formData]); const setNotloggedOnError = useCallback(() => { if (noAccount) { @@ -99,14 +105,11 @@ const LoginForm = ({ onLogin, noAccount = false }: LoginFormProps) => { const onLoginHandler = useCallback(() => { const valid = validateForm(); - if (!valid) { - return; - } - setSubmitting(true); - onLogin({ username, password }).finally(() => { - setSubmitting(false); - }); - }, [validateForm, onLogin, username, password, errors]); + + if (!valid) return; + + onLogin(formData); + }, [validateForm, onLogin, formData]); return ( { setUsername(e.target.value)} - helperText={fieldErrors.email} + autoComplete={'username'} error={!!fieldErrors.email || noAccount} + helperText={fieldErrors.email} + inputProps={{ + 'aria-label': 'email', + name: 'username', + }} + label={shared('emailAddress')} required + size='small' sx={{ width: '100%', backgroundColor: palette.background.paper, }} - autoComplete={'username'} + value={formData.username} + variant='outlined' + onChange={handleChangeInput} /> setPassword(e.target.value)} - label={`${shared('password')}`} - variant='outlined' - size='small' + autoComplete={'current-password'} error={!!fieldErrors.password || noAccount} - required + id='password-input' + inputProps={{ + 'aria-label': 'password', + name: 'password', + }} InputProps={{ endAdornment: ( @@ -170,7 +176,12 @@ const LoginForm = ({ onLogin, noAccount = false }: LoginFormProps) => { ), }} - autoComplete={'current-password'} + label={`${shared('password')}`} + required + size='small' + type={showPassword ? 'text' : 'password'} + variant='outlined' + onChange={handleChangeInput} /> {(fieldErrors.password || noAccount) && ( From 3e15037534802f79f2791feb80b7a417d0cd3a9d Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Wed, 28 Feb 2024 18:05:58 +0100 Subject: [PATCH 02/12] handle reset errors on change input value --- .../src/components/organisms/Auth/LoginForm.tsx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx b/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx index a66f19393..0aaec12dd 100644 --- a/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx +++ b/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx @@ -73,9 +73,19 @@ const LoginForm = ({ [] ); - const handleChangeInput = useCallback((e: ChangeEvent) => { - setFormData((prev) => ({ ...prev, [e.target.name]: e.target.value })); - }, []); + const handleChangeInput = useCallback( + (e: ChangeEvent) => { + if (fieldErrors.email || fieldErrors.password) { + setFieldErrors({ + email: null, + password: null, + }); + } + + setFormData((prev) => ({ ...prev, [e.target.name]: e.target.value })); + }, + [fieldErrors] + ); const validateForm = useCallback(() => { const emailError = validateEmail(formData.username); From 89cbb36d25fb3a485aeacb0f482daccbffcbf3ee Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Wed, 28 Feb 2024 18:06:11 +0100 Subject: [PATCH 03/12] add LoginForm tests --- .../__tests__/components/LoginForm.test.tsx | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx diff --git a/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx b/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx new file mode 100644 index 000000000..de9f6d683 --- /dev/null +++ b/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx @@ -0,0 +1,104 @@ +import LoginForm from '@/components/organisms/Auth/LoginForm'; +import { fireEvent, render, act } from '@testing-library/react'; +import Wrapper from './Wrapper'; +import React from 'react'; + +describe('LoginForm', () => { + const promise = Promise.resolve(); + const mockOnLogin = jest.fn(() => promise); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render without crashing', () => { + render( + + + + ); + }); + + it('should handle username and password input', () => { + const { getByLabelText } = render( + + + + ); + + const usernameInput = getByLabelText(/^email$/i) as HTMLInputElement; + const passwordInput = getByLabelText(/^password$/i) as HTMLInputElement; + + fireEvent.change(usernameInput, { target: { value: 'test@example.com' } }); + fireEvent.change(passwordInput, { target: { value: 'password123' } }); + + expect(usernameInput.value).toBe('test@example.com'); + expect(passwordInput.value).toBe('password123'); + }); + + it('should call onLogin when form is submitted', async () => { + const { getByLabelText, getByRole } = render( + + + + ); + + const usernameInput = getByLabelText(/^email$/i) as HTMLInputElement; + const passwordInput = getByLabelText(/^password$/i) as HTMLInputElement; + const submitButton = getByRole('button', { name: /accedi/i }); + + fireEvent.change(usernameInput, { target: { value: 'test@example.com' } }); + fireEvent.change(passwordInput, { target: { value: 'password123' } }); + fireEvent.click(submitButton); + + expect(mockOnLogin).toHaveBeenCalledWith({ + username: 'test@example.com', + password: 'password123', + }); + + await act(() => promise); + }); + + it('should display error messages when inputs are invalid', async () => { + const { getByLabelText, findByText, getByRole, findAllByText } = render( + + + + ); + + const usernameInput = getByLabelText(/^email$/i) as HTMLInputElement; + const passwordInput = getByLabelText(/^password$/i) as HTMLInputElement; + const submitButton = getByRole('button', { name: /accedi/i }); + + fireEvent.change(usernameInput, { target: { value: '' } }); + fireEvent.change(passwordInput, { target: { value: '' } }); + fireEvent.click(submitButton); + + const errors = await findAllByText(/Questo campo non può essere vuoto/i); + + expect(errors).toHaveLength(2); + + fireEvent.change(usernameInput, { target: { value: 'invalid email' } }); + fireEvent.click(submitButton); + + const emailError = await findByText(/Inserisci un indirizzo email valido/i); + const passwordError = await findByText( + /Questo campo non può essere vuoto/i + ); + + expect(emailError).toBeDefined(); + expect(passwordError).toBeDefined(); + }); + + it('should display error messages when account not exists', async () => { + const { findAllByText } = render( + + + + ); + + const errors = await findAllByText(/Nome utente o password non corretti./i); + + expect(errors).toHaveLength(2); + }); +}); From 1c073aa0224a39feff8307225660c45719555633 Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Thu, 29 Feb 2024 15:30:45 +0100 Subject: [PATCH 04/12] add test --- .../__tests__/components/LoginForm.test.tsx | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx b/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx index de9f6d683..d5e0d44fe 100644 --- a/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx +++ b/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx @@ -60,12 +60,21 @@ describe('LoginForm', () => { }); it('should display error messages when inputs are invalid', async () => { - const { getByLabelText, findByText, getByRole, findAllByText } = render( + const { + getByLabelText, + findByText, + getByRole, + findAllByText, + queryByText, + queryAllByText, + } = render( ); + const errorsRegex = /Questo campo non può essere vuoto/i; + const emailErrorRegex = /Inserisci un indirizzo email valido/i; const usernameInput = getByLabelText(/^email$/i) as HTMLInputElement; const passwordInput = getByLabelText(/^password$/i) as HTMLInputElement; const submitButton = getByRole('button', { name: /accedi/i }); @@ -74,20 +83,28 @@ describe('LoginForm', () => { fireEvent.change(passwordInput, { target: { value: '' } }); fireEvent.click(submitButton); - const errors = await findAllByText(/Questo campo non può essere vuoto/i); + const errors = await findAllByText(errorsRegex); expect(errors).toHaveLength(2); fireEvent.change(usernameInput, { target: { value: 'invalid email' } }); fireEvent.click(submitButton); - const emailError = await findByText(/Inserisci un indirizzo email valido/i); - const passwordError = await findByText( - /Questo campo non può essere vuoto/i - ); + const emailError = await findByText(emailErrorRegex); + const passwordError = await findByText(errorsRegex); expect(emailError).toBeDefined(); expect(passwordError).toBeDefined(); + + fireEvent.change(usernameInput, { target: { value: 'test@example.com' } }); + fireEvent.change(passwordInput, { target: { value: 'password123' } }); + fireEvent.click(submitButton); + + const emailError1 = await queryByText(emailErrorRegex); + const errorsRegex1 = await queryAllByText(errorsRegex); + + expect(emailError1).toBeNull(); + expect(errorsRegex1).toHaveLength(0); }); it('should display error messages when account not exists', async () => { From 4244ef038013b041afe527eba86a86fd5744ef62 Mon Sep 17 00:00:00 2001 From: Jeremy Gordillo Date: Thu, 29 Feb 2024 15:36:27 +0100 Subject: [PATCH 05/12] Create sour-penguins-smile.md --- .changeset/sour-penguins-smile.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sour-penguins-smile.md diff --git a/.changeset/sour-penguins-smile.md b/.changeset/sour-penguins-smile.md new file mode 100644 index 000000000..c2aafaa6e --- /dev/null +++ b/.changeset/sour-penguins-smile.md @@ -0,0 +1,5 @@ +--- +"nextjs-website": patch +--- + +[DEV-1465] Reset login form errors on user changes From 488c68373398f295ff106dd5fe205238cfd806e9 Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Fri, 1 Mar 2024 09:03:00 +0100 Subject: [PATCH 06/12] Moved test file --- .../organisms/Auth/__tests__}/LoginForm.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename apps/nextjs-website/src/{__tests__/components => components/organisms/Auth/__tests__}/LoginForm.test.tsx (98%) diff --git a/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx b/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx similarity index 98% rename from apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx rename to apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx index d5e0d44fe..c7c352dd3 100644 --- a/apps/nextjs-website/src/__tests__/components/LoginForm.test.tsx +++ b/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx @@ -1,6 +1,6 @@ import LoginForm from '@/components/organisms/Auth/LoginForm'; import { fireEvent, render, act } from '@testing-library/react'; -import Wrapper from './Wrapper'; +import Wrapper from '../../../../__tests__/components/Wrapper'; import React from 'react'; describe('LoginForm', () => { From c3bf5940fc3fca8d90c15777ce625ef53c70e518 Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Mon, 4 Mar 2024 17:31:26 +0100 Subject: [PATCH 07/12] fix error prop value --- .../src/components/organisms/Auth/LoginForm.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx b/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx index 0aaec12dd..71ff4d138 100644 --- a/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx +++ b/apps/nextjs-website/src/components/organisms/Auth/LoginForm.tsx @@ -144,7 +144,7 @@ const LoginForm = ({ - {(fieldErrors.password || noAccount) && ( + {fieldErrors.password && ( {fieldErrors.password} From 9943c4456d3dd277a34ba14bdb88bc5ca3624483 Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Mon, 4 Mar 2024 17:49:56 +0100 Subject: [PATCH 08/12] improve test --- .../Auth/__tests__/LoginForm.test.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx b/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx index c7c352dd3..f3ea2c774 100644 --- a/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx +++ b/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx @@ -85,6 +85,12 @@ describe('LoginForm', () => { const errors = await findAllByText(errorsRegex); + expect(usernameInput.attributes.getNamedItem('aria-invalid')?.value).toBe( + 'true' + ); + expect(passwordInput.attributes.getNamedItem('aria-invalid')?.value).toBe( + 'true' + ); expect(errors).toHaveLength(2); fireEvent.change(usernameInput, { target: { value: 'invalid email' } }); @@ -95,6 +101,12 @@ describe('LoginForm', () => { expect(emailError).toBeDefined(); expect(passwordError).toBeDefined(); + expect(usernameInput.attributes.getNamedItem('aria-invalid')?.value).toBe( + 'true' + ); + expect(passwordInput.attributes.getNamedItem('aria-invalid')?.value).toBe( + 'true' + ); fireEvent.change(usernameInput, { target: { value: 'test@example.com' } }); fireEvent.change(passwordInput, { target: { value: 'password123' } }); @@ -105,6 +117,12 @@ describe('LoginForm', () => { expect(emailError1).toBeNull(); expect(errorsRegex1).toHaveLength(0); + expect(usernameInput.attributes.getNamedItem('aria-invalid')?.value).toBe( + 'false' + ); + expect(passwordInput.attributes.getNamedItem('aria-invalid')?.value).toBe( + 'false' + ); }); it('should display error messages when account not exists', async () => { From b2d8694870e40355e8f596a3a0309209ad9c9e8b Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Wed, 6 Mar 2024 18:09:11 +0100 Subject: [PATCH 09/12] pr changes --- .../src/app/auth/login/page.tsx | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/apps/nextjs-website/src/app/auth/login/page.tsx b/apps/nextjs-website/src/app/auth/login/page.tsx index 120f1517e..e1672ab6f 100644 --- a/apps/nextjs-website/src/app/auth/login/page.tsx +++ b/apps/nextjs-website/src/app/auth/login/page.tsx @@ -16,22 +16,19 @@ const Login = () => { const router = useRouter(); const [logInStep, setLogInStep] = useState(LoginSteps.LOG_IN); const [user, setUser] = useState(null); - const [username, setUsername] = useState(''); - const [password, setPassword] = useState(''); + const [loginData, setLoginData] = useState({ username: '', password: '' }); const [submitting, setSubmitting] = useState(false); const [noAccountError, setNoAccountError] = useState(false); const onLogin: LoginFunction = useCallback(async ({ username, password }) => { setSubmitting(true); setNoAccountError(false); - setUsername(username); - setPassword(password); + setLoginData({ username, password }); const opts: SignInOpts = { username, password }; const user = await Auth.signIn(opts) .catch((error) => { if (error.code === 'UserNotConfirmedException') { - setUsername(username); setLogInStep(LoginSteps.CONFIRM_ACCOUNT); } else { setNoAccountError(true); @@ -42,8 +39,6 @@ const Login = () => { setSubmitting(false); }); - setUsername(username); - if (user) { setUser(user); setLogInStep(LoginSteps.MFA_CHALLENGE); @@ -51,12 +46,12 @@ const Login = () => { }, []); const resendCode = useCallback(async () => { - const result = await onLogin({ username, password }) + const result = await onLogin(loginData) .then(() => true) .catch(() => false); return result; - }, [onLogin, password, username]); + }, [onLogin, loginData]); const searchParams = useSearchParams(); @@ -72,13 +67,13 @@ const Login = () => { const onBackStep = useCallback(() => { router.replace( - `/auth/login?email=${encodeURIComponent(username || '')}&step=${ + `/auth/login?email=${encodeURIComponent(loginData.username || '')}&step=${ LoginSteps.LOG_IN }` ); setLogInStep(LoginSteps.LOG_IN); return null; - }, [router, username]); + }, [router, loginData.username]); return ( @@ -100,13 +95,13 @@ const Login = () => { )} {logInStep === LoginSteps.MFA_CHALLENGE && ( )} {logInStep === LoginSteps.CONFIRM_ACCOUNT && ( - + )} From dc707c424a7f8865a94d2810dd4a660778ad79f7 Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Thu, 7 Mar 2024 16:01:31 +0100 Subject: [PATCH 10/12] minor fixes --- apps/nextjs-website/src/app/auth/login/page.tsx | 10 ++-------- .../src/components/organisms/Auth/ConfirmSignUp.tsx | 3 ++- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/apps/nextjs-website/src/app/auth/login/page.tsx b/apps/nextjs-website/src/app/auth/login/page.tsx index e1672ab6f..e8f85692d 100644 --- a/apps/nextjs-website/src/app/auth/login/page.tsx +++ b/apps/nextjs-website/src/app/auth/login/page.tsx @@ -65,15 +65,9 @@ const Login = () => { [router, searchParams, user] ); - const onBackStep = useCallback(() => { - router.replace( - `/auth/login?email=${encodeURIComponent(loginData.username || '')}&step=${ - LoginSteps.LOG_IN - }` - ); + const onBackStep = () => { setLogInStep(LoginSteps.LOG_IN); - return null; - }, [router, loginData.username]); + }; return ( diff --git a/apps/nextjs-website/src/components/organisms/Auth/ConfirmSignUp.tsx b/apps/nextjs-website/src/components/organisms/Auth/ConfirmSignUp.tsx index 73b71bc89..e1b4fa6b9 100644 --- a/apps/nextjs-website/src/components/organisms/Auth/ConfirmSignUp.tsx +++ b/apps/nextjs-website/src/components/organisms/Auth/ConfirmSignUp.tsx @@ -14,7 +14,8 @@ import { useTranslations } from 'next-intl'; interface ConfirmSignUpProps { email: string; - onBack: () => null; + // eslint-disable-next-line functional/no-return-void + onBack: () => void; } const ConfirmSignUp = ({ email, onBack }: ConfirmSignUpProps) => { From 6ceed1a4858cc0d3ce194e52a39ee89451d0c9b2 Mon Sep 17 00:00:00 2001 From: jeremygordillo Date: Thu, 7 Mar 2024 16:36:08 +0100 Subject: [PATCH 11/12] changes after review --- .../Auth/__tests__/LoginForm.test.tsx | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx b/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx index f3ea2c774..f0518eb27 100644 --- a/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx +++ b/apps/nextjs-website/src/components/organisms/Auth/__tests__/LoginForm.test.tsx @@ -1,11 +1,18 @@ import LoginForm from '@/components/organisms/Auth/LoginForm'; -import { fireEvent, render, act } from '@testing-library/react'; -import Wrapper from '../../../../__tests__/components/Wrapper'; +import { fireEvent, render } from '@testing-library/react'; import React from 'react'; +import Wrapper from '../../../../__tests__/components/Wrapper'; +import labels from '@/messages/it.json'; + +const errorsRegex = RegExp(labels.shared.requiredFieldError, 'i'); +const emailErrorRegex = RegExp(labels.shared.emailFieldError, 'i'); +const fieldsErrorsRegex = RegExp(labels.auth.login.noAccountError, 'i'); +const actionRegex = RegExp(labels.auth.login.action, 'i'); + describe('LoginForm', () => { - const promise = Promise.resolve(); - const mockOnLogin = jest.fn(() => promise); + // eslint-disable-next-line @typescript-eslint/no-empty-function + const mockOnLogin = jest.fn(async () => {}); beforeEach(() => { jest.clearAllMocks(); @@ -45,7 +52,7 @@ describe('LoginForm', () => { const usernameInput = getByLabelText(/^email$/i) as HTMLInputElement; const passwordInput = getByLabelText(/^password$/i) as HTMLInputElement; - const submitButton = getByRole('button', { name: /accedi/i }); + const submitButton = getByRole('button', { name: actionRegex }); fireEvent.change(usernameInput, { target: { value: 'test@example.com' } }); fireEvent.change(passwordInput, { target: { value: 'password123' } }); @@ -55,8 +62,6 @@ describe('LoginForm', () => { username: 'test@example.com', password: 'password123', }); - - await act(() => promise); }); it('should display error messages when inputs are invalid', async () => { @@ -73,11 +78,9 @@ describe('LoginForm', () => { ); - const errorsRegex = /Questo campo non può essere vuoto/i; - const emailErrorRegex = /Inserisci un indirizzo email valido/i; const usernameInput = getByLabelText(/^email$/i) as HTMLInputElement; const passwordInput = getByLabelText(/^password$/i) as HTMLInputElement; - const submitButton = getByRole('button', { name: /accedi/i }); + const submitButton = getByRole('button', { name: actionRegex }); fireEvent.change(usernameInput, { target: { value: '' } }); fireEvent.change(passwordInput, { target: { value: '' } }); @@ -132,7 +135,7 @@ describe('LoginForm', () => { ); - const errors = await findAllByText(/Nome utente o password non corretti./i); + const errors = await findAllByText(fieldsErrorsRegex); expect(errors).toHaveLength(2); }); From 810345cb50f94f2d1256d3a51fde728b36734fed Mon Sep 17 00:00:00 2001 From: Jeremy Gordillo Date: Mon, 11 Mar 2024 10:35:03 +0100 Subject: [PATCH 12/12] Update .changeset/sour-penguins-smile.md Co-authored-by: marcobottaro <39835990+marcobottaro@users.noreply.github.com> --- .changeset/sour-penguins-smile.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/sour-penguins-smile.md b/.changeset/sour-penguins-smile.md index c2aafaa6e..696d6663e 100644 --- a/.changeset/sour-penguins-smile.md +++ b/.changeset/sour-penguins-smile.md @@ -2,4 +2,4 @@ "nextjs-website": patch --- -[DEV-1465] Reset login form errors on user changes +Reset login form errors on user changes