11import React from 'react' ;
2- import { render , screen , fireEvent , waitFor } from '@testing-library/react' ;
3- import { vi , expect } from 'vitest' ;
4- import SignInForm from 'pages/Auth/SignIn/components/SignInForm' ;
5-
6- // Mock the useTranslation hook
7- vi . mock ( 'react-i18next' , ( ) => ( {
8- useTranslation : ( ) => ( {
9- t : ( key : string ) => key
10- } )
11- } ) ) ;
2+ import { render , screen , fireEvent } from '@testing-library/react' ;
3+ import { vi } from 'vitest' ;
4+ import SignInForm from '../SignInForm' ;
5+ import { AuthError } from '../../../../services/auth/types' ;
6+ import { useAuthOperations } from '../../../../hooks/useAuthOperations' ;
127
138// Mock the useAuthOperations hook
14- const mockSignIn = vi . fn ( ) ;
15- vi . mock ( 'common/hooks/useAuthOperations' , ( ) => ( {
9+ vi . mock ( '../../../../hooks/useAuthOperations' , ( ) => ( {
1610 useAuthOperations : ( ) => ( {
17- signIn : mockSignIn ,
11+ signIn : vi . fn ( ) ,
1812 error : null ,
19- isLoading : false
20- } )
13+ isLoading : false ,
14+ clearError : vi . fn ( ) ,
15+ } ) ,
2116} ) ) ;
2217
2318// Mock the useProgress hook
24- vi . mock ( 'common /hooks/useProgress' , ( ) => ( {
19+ vi . mock ( '../../../.. /hooks/useProgress' , ( ) => ( {
2520 useProgress : ( ) => ( {
26- start : vi . fn ( ) ,
27- done : vi . fn ( ) ,
28- active : false ,
29- progress : 0 ,
30- animation : 'ease' ,
31- className : '' ,
32- startPosition : 0.3 ,
33- initialPosition : 0.1
34- } )
21+ progressBar : {
22+ show : vi . fn ( ) ,
23+ hide : vi . fn ( ) ,
24+ } ,
25+ } ) ,
26+ } ) ) ;
27+
28+ // Mock the @ionic /react components
29+ vi . mock ( '@ionic/react' , ( ) => {
30+ const IonButton = ( { onClick, children, type } : { onClick ?: ( ) => void ; children : React . ReactNode ; type ?: string } ) => (
31+ < button onClick = { onClick } type = { type } >
32+ { children }
33+ </ button >
34+ ) ;
35+
36+ const IonItem = ( { children } : { children : React . ReactNode } ) => < div > { children } </ div > ;
37+ const IonLabel = ( { children } : { children : React . ReactNode } ) => < label > { children } </ label > ;
38+ const IonInput = ( {
39+ value,
40+ onIonChange,
41+ type,
42+ placeholder,
43+ "data-testid" : dataTestId ,
44+ } : {
45+ value ?: string ;
46+ onIonChange ?: ( e : { detail : { value : string } } ) => void ;
47+ type ?: string ;
48+ placeholder ?: string ;
49+ "data-testid" ?: string ;
50+ } ) => (
51+ < input
52+ value = { value }
53+ onChange = { ( e ) => onIonChange ?.( { detail : { value : e . target . value } } ) }
54+ type = { type }
55+ placeholder = { placeholder }
56+ data-testid = { dataTestId }
57+ />
58+ ) ;
59+
60+ const IonText = ( { children, color } : { children : React . ReactNode ; color ?: string } ) => (
61+ < div style = { { color } } > { children } </ div >
62+ ) ;
63+
64+ const IonRow = ( { children } : { children : React . ReactNode } ) => < div > { children } </ div > ;
65+ const IonCol = ( { children } : { children : React . ReactNode } ) => < div > { children } </ div > ;
66+ const IonList = ( { children } : { children : React . ReactNode } ) => < div > { children } </ div > ;
67+ const IonGrid = ( { children } : { children : React . ReactNode } ) => < div > { children } </ div > ;
68+ const IonCheckbox = ( {
69+ checked,
70+ onIonChange,
71+ "data-testid" : dataTestId ,
72+ } : {
73+ checked ?: boolean ;
74+ onIonChange ?: ( e : { detail : { checked : boolean } } ) => void ;
75+ "data-testid" ?: string ;
76+ } ) => (
77+ < input
78+ type = "checkbox"
79+ checked = { checked }
80+ onChange = { ( e ) => onIonChange ?.( { detail : { checked : e . target . checked } } ) }
81+ data-testid = { dataTestId }
82+ />
83+ ) ;
84+
85+ const IonInputPasswordToggle = ( {
86+ value,
87+ onIonChange,
88+ placeholder,
89+ "data-testid" : dataTestId ,
90+ } : {
91+ value ?: string ;
92+ onIonChange ?: ( e : { detail : { value : string } } ) => void ;
93+ placeholder ?: string ;
94+ "data-testid" ?: string ;
95+ } ) => (
96+ < input
97+ value = { value }
98+ onChange = { ( e ) => onIonChange ?.( { detail : { value : e . target . value } } ) }
99+ type = "password"
100+ placeholder = { placeholder }
101+ data-testid = { dataTestId }
102+ />
103+ ) ;
104+
105+ return {
106+ IonButton,
107+ IonItem,
108+ IonLabel,
109+ IonInput,
110+ IonText,
111+ IonRow,
112+ IonCol,
113+ IonList,
114+ IonGrid,
115+ IonCheckbox,
116+ IonInputPasswordToggle,
117+ } ;
118+ } ) ;
119+
120+ // Mock the AuthErrorDisplay component
121+ vi . mock ( '../AuthErrorDisplay' , ( ) => ( {
122+ default : ( { error } : { error : AuthError | null } ) => (
123+ error ? < div data-testid = "auth-error" > { error . message } </ div > : null
124+ ) ,
125+ } ) ) ;
126+
127+ // Mock the AuthLoadingIndicator component
128+ vi . mock ( '../AuthLoadingIndicator' , ( ) => ( {
129+ default : ( { isLoading } : { isLoading : boolean } ) => (
130+ isLoading ? < div data-testid = "loading-indicator" > Loading...</ div > : null
131+ ) ,
132+ } ) ) ;
133+
134+ // Mock the useTranslation hook
135+ vi . mock ( 'react-i18next' , ( ) => ( {
136+ useTranslation : ( ) => ( {
137+ t : ( key : string ) => key ,
138+ } ) ,
35139} ) ) ;
36140
37141describe ( 'SignInForm' , ( ) => {
38- beforeEach ( ( ) => {
39- mockSignIn . mockReset ( ) ;
142+ it ( 'should render successfully' , ( ) => {
143+ render ( < SignInForm /> ) ;
144+ expect ( screen . getByText ( 'auth.signIn.title' ) ) . toBeTruthy ( ) ;
40145 } ) ;
41146
42- it ( 'renders the form ' , ( ) => {
147+ it ( 'should handle email change ' , ( ) => {
43148 render ( < SignInForm /> ) ;
44-
45- const emailInput = screen . getByLabelText ( / a u t h .e m a i l / i) ;
46- const passwordInput = screen . getByLabelText ( / a u t h .p a s s w o r d / i) ;
47- const submitButton = screen . getByRole ( 'button' , { name : / a u t h .s i g n I n / i } ) ;
48-
49- expect ( emailInput ) . toBeDefined ( ) ;
50- expect ( passwordInput ) . toBeDefined ( ) ;
51- expect ( submitButton ) . toBeDefined ( ) ;
149+ const emailInput = screen . getByTestId ( 'email-input' ) ;
150+ fireEvent . change ( emailInput , { target :
{ value :
'[email protected] ' } } ) ; 151+ expect ( emailInput ) . toHaveValue ( '[email protected] ' ) ; 52152 } ) ;
53153
54- it ( 'validates email and password inputs' , async ( ) => {
154+ it ( 'should handle password change' , ( ) => {
55155 render ( < SignInForm /> ) ;
56-
57- const emailInput = screen . getByLabelText ( / a u t h .e m a i l / i) ;
58- const passwordInput = screen . getByLabelText ( / a u t h .p a s s w o r d / i) ;
59- const submitButton = screen . getByRole ( 'button' , { name : / a u t h .s i g n I n / i } ) ;
60-
61- // Submit with empty fields
62- fireEvent . click ( submitButton ) ;
63-
64- await waitFor ( ( ) => {
65- // Should show validation errors
66- expect ( screen . getByText ( / a u t h .v a l i d a t i o n .e m a i l R e q u i r e d / i) ) . toBeDefined ( ) ;
67- expect ( screen . getByText ( / a u t h .v a l i d a t i o n .p a s s w o r d R e q u i r e d / i) ) . toBeDefined ( ) ;
68- } ) ;
69-
70- // Enter invalid email format
71- fireEvent . change ( emailInput , { target : { value : 'invalid-email' } } ) ;
72- fireEvent . click ( submitButton ) ;
73-
74- await waitFor ( ( ) => {
75- expect ( screen . getByText ( / a u t h .v a l i d a t i o n .e m a i l F o r m a t / i) ) . toBeDefined ( ) ;
76- } ) ;
77-
78- // Enter valid email but short password
79- fireEvent . change ( emailInput , { target :
{ value :
'[email protected] ' } } ) ; 80- fireEvent . change ( passwordInput , { target : { value : '123' } } ) ;
81- fireEvent . click ( submitButton ) ;
82-
83- await waitFor ( ( ) => {
84- expect ( screen . getByText ( / a u t h .v a l i d a t i o n .p a s s w o r d L e n g t h / i) ) . toBeDefined ( ) ;
85- } ) ;
156+ const passwordInput = screen . getByTestId ( 'password-input' ) ;
157+ fireEvent . change ( passwordInput , { target : { value : 'password123' } } ) ;
158+ expect ( passwordInput ) . toHaveValue ( 'password123' ) ;
86159 } ) ;
87160
88- it ( 'submits the form with valid data' , async ( ) => {
161+ it ( 'should handle remember me change' , ( ) => {
162+ render ( < SignInForm /> ) ;
163+ const rememberMeCheckbox = screen . getByTestId ( 'remember-me' ) ;
164+ fireEvent . click ( rememberMeCheckbox ) ;
165+ expect ( rememberMeCheckbox ) . toBeChecked ( ) ;
166+ } ) ;
167+
168+ it ( 'should submit the form' , ( ) => {
169+ // Mock the useAuthOperations hook
170+ const mockSignIn = vi . fn ( ) ;
171+ vi . mocked ( useAuthOperations ) . mockReturnValue ( {
172+ signIn : mockSignIn ,
173+ error : null ,
174+ isLoading : false ,
175+ clearError : vi . fn ( ) ,
176+ } ) ;
177+
89178 render ( < SignInForm /> ) ;
90179
91- const emailInput = screen . getByLabelText ( / a u t h .e m a i l / i) ;
92- const passwordInput = screen . getByLabelText ( / a u t h .p a s s w o r d / i) ;
93- const submitButton = screen . getByRole ( 'button' , { name : / a u t h .s i g n I n / i } ) ;
94-
95- // Enter valid credentials
180+ const emailInput = screen . getByTestId ( 'email-input' ) ;
96181 fireEvent . change ( emailInput , { target :
{ value :
'[email protected] ' } } ) ; 97- fireEvent . change ( passwordInput , { target : { value : 'Password123' } } ) ;
98- fireEvent . click ( submitButton ) ;
99182
100- await waitFor ( ( ) => {
101- expect ( mockSignIn ) . toHaveBeenCalledWith ( '[email protected] ' , 'Password123' ) ; 102- } ) ;
103- } ) ;
104-
105- it ( 'applies custom className' , ( ) => {
106- const customClass = 'custom-form-class' ;
107- render ( < SignInForm className = { customClass } /> ) ;
183+ const passwordInput = screen . getByTestId ( 'password-input' ) ;
184+ fireEvent . change ( passwordInput , { target : { value : 'password123' } } ) ;
108185
109- const form = screen . getByTestId ( 'sign-in-form' ) ;
110- expect ( form . className ) . toContain ( customClass ) ;
111- } ) ;
112-
113- it ( 'accepts custom testid' , ( ) => {
114- const customTestId = 'custom-sign-in-form' ;
115- render ( < SignInForm testid = { customTestId } /> ) ;
186+ const submitButton = screen . getByText ( 'auth.signIn.button' ) ;
187+ fireEvent . click ( submitButton ) ;
116188
117- const form = screen . getByTestId ( customTestId ) ;
118- expect ( form ) . toBeDefined ( ) ;
189+ expect ( mockSignIn ) . toHaveBeenCalledWith ( '[email protected] ' , 'password123' ) ; 119190 } ) ;
120191} ) ;
0 commit comments