1
+ import { render , screen , fireEvent , waitFor } from '@testing-library/react' ;
2
+ import '@testing-library/jest-dom' ;
3
+ import LoginPanel from './LoginPanel' ;
4
+ import AuthService from '@/service/authService' ;
5
+ import useAuth from '@/hooks/useAuth' ;
6
+ import { AxiosError , InternalAxiosRequestConfig } from 'axios' ;
7
+
8
+
9
+ jest . mock ( '@/service/authService' ) ;
10
+ jest . mock ( '@/hooks/useAuth' ) ;
11
+ jest . mock ( '../../config' , ( ) => ( {
12
+ API_DOMAIN : 'http://localhost:3000' ,
13
+ } ) ) ;
14
+
15
+ describe ( 'LoginPanel Component' , ( ) => {
16
+ beforeEach ( ( ) => {
17
+ ( useAuth as jest . Mock ) . mockReturnValue ( {
18
+ saveToken : jest . fn ( ) ,
19
+ } ) ;
20
+ } ) ;
21
+
22
+ // login routes
23
+ test ( 'renders LoginPanel with login button' , ( ) => {
24
+ render ( < LoginPanel /> ) ;
25
+ expect ( screen . getByTestId ( 'open-login-button' ) ) . toBeInTheDocument ( ) ;
26
+ } ) ;
27
+
28
+ test ( 'opens dialog when clicking LOGIN button' , ( ) => {
29
+ render ( < LoginPanel /> ) ;
30
+ fireEvent . click ( screen . getByTestId ( 'open-login-button' ) ) ;
31
+ expect ( screen . getByText ( / P l e a s e e n t e r y o u r c r e d e n t i a l s t o c o n t i n u e / i) ) . toBeInTheDocument ( ) ;
32
+ } ) ;
33
+
34
+ test ( 'renders login form with username and password fields' , ( ) => {
35
+ render ( < LoginPanel /> ) ;
36
+ fireEvent . click ( screen . getByTestId ( 'open-login-button' ) ) ;
37
+ expect ( screen . getByTestId ( 'username-input' ) ) . toBeInTheDocument ( ) ;
38
+ expect ( screen . getByTestId ( 'password-input' ) ) . toBeInTheDocument ( ) ;
39
+ } ) ;
40
+
41
+ test ( 'displays error message when no username or password is provided' , async ( ) => {
42
+ render ( < LoginPanel /> ) ;
43
+ fireEvent . click ( screen . getByTestId ( 'open-login-button' ) ) ;
44
+ fireEvent . click ( screen . getByTestId ( 'submit-button' ) ) ;
45
+
46
+ expect ( screen . getByTestId ( 'error-message' ) ) . toHaveTextContent ( 'Please enter a username and password' ) ;
47
+ } ) ;
48
+
49
+ test ( 'logs in user successfully' , async ( ) => {
50
+ ( AuthService . login as jest . Mock ) . mockResolvedValue ( { token : 'test-token' } ) ;
51
+ render ( < LoginPanel /> ) ;
52
+ fireEvent . click ( screen . getByTestId ( 'open-login-button' ) ) ;
53
+ fireEvent . change ( screen . getByTestId ( 'username-input' ) , { target : { value : 'testuser' } } ) ;
54
+ fireEvent . change ( screen . getByTestId ( 'password-input' ) , { target : { value : '6@:;£V64YmvC' } } ) ;
55
+ fireEvent . click ( screen . getByTestId ( 'submit-button' ) ) ;
56
+
57
+ await waitFor ( ( ) => {
58
+ expect ( AuthService . login ) . toHaveBeenCalledWith ( 'testuser' , '6@:;£V64YmvC' ) ;
59
+ expect ( useAuth ( ) . saveToken ) . toHaveBeenCalledWith ( 'test-token' ) ;
60
+ } ) ;
61
+ } ) ;
62
+
63
+ test ( 'displays error when login fails' , async ( ) => {
64
+ const errorResponse = {
65
+ data : { error : 'Invalid credentials' } ,
66
+ } ;
67
+
68
+ const axiosError = new AxiosError (
69
+ 'Request failed with status code 401' ,
70
+ 'ERR_BAD_REQUEST' ,
71
+ { } as InternalAxiosRequestConfig ,
72
+ null ,
73
+ {
74
+ ...errorResponse ,
75
+ status : 401 ,
76
+ statusText : 'Unauthorized' ,
77
+ headers : { } ,
78
+ config : { } as InternalAxiosRequestConfig ,
79
+ }
80
+ ) ;
81
+
82
+ ( AuthService . login as jest . Mock ) . mockRejectedValue ( axiosError ) ;
83
+
84
+ render ( < LoginPanel /> ) ;
85
+ fireEvent . click ( screen . getByTestId ( 'open-login-button' ) ) ;
86
+ fireEvent . change ( screen . getByTestId ( 'username-input' ) , { target : { value : 'wronguser' } } ) ;
87
+ fireEvent . change ( screen . getByTestId ( 'password-input' ) , { target : { value : 'wrongpass' } } ) ;
88
+ fireEvent . click ( screen . getByTestId ( 'submit-button' ) ) ;
89
+
90
+ await waitFor ( ( ) => {
91
+ expect ( screen . getByTestId ( 'error-message' ) ) . toHaveTextContent ( 'Invalid credentials' ) ;
92
+ } ) ;
93
+ } ) ;
94
+
95
+ // register routes
96
+ test ( 'toggles between login and register mode' , ( ) => {
97
+ render ( < LoginPanel /> ) ;
98
+ fireEvent . click ( screen . getByTestId ( 'open-login-button' ) ) ;
99
+
100
+ // initially in login mode
101
+ expect ( screen . getByTestId ( 'submit-button' ) ) . toHaveTextContent ( 'Login' ) ;
102
+
103
+ // toggle to register mode
104
+ fireEvent . click ( screen . getByTestId ( 'toggle-register-button' ) ) ;
105
+ expect ( screen . getByTestId ( 'submit-button' ) ) . toHaveTextContent ( 'Register' ) ;
106
+
107
+ // toggle back to login mode
108
+ fireEvent . click ( screen . getByTestId ( 'toggle-register-button' ) ) ;
109
+ expect ( screen . getByTestId ( 'submit-button' ) ) . toHaveTextContent ( 'Login' ) ;
110
+ } ) ;
111
+
112
+ test ( 'registers a new user successfully' , async ( ) => {
113
+ ( AuthService . register as jest . Mock ) . mockResolvedValue ( { token : 'register-token' } ) ;
114
+ render ( < LoginPanel /> ) ;
115
+ fireEvent . click ( screen . getByTestId ( 'open-login-button' ) ) ;
116
+
117
+ // toggle to Register mode
118
+ fireEvent . click ( screen . getByTestId ( 'toggle-register-button' ) ) ;
119
+
120
+ fireEvent . change ( screen . getByTestId ( 'username-input' ) , { target : { value : 'newuser' } } ) ;
121
+ fireEvent . change ( screen . getByTestId ( 'password-input' ) , { target : { value : 'P@ssword1' } } ) ;
122
+ fireEvent . click ( screen . getByTestId ( 'submit-button' ) ) ;
123
+
124
+ await waitFor ( ( ) => {
125
+ expect ( AuthService . register ) . toHaveBeenCalledWith ( 'newuser' , 'P@ssword1' ) ;
126
+ expect ( useAuth ( ) . saveToken ) . toHaveBeenCalledWith ( 'register-token' ) ;
127
+ } ) ;
128
+ } ) ;
129
+
130
+ test ( 'displays error when registration fails' , async ( ) => {
131
+ const errorResponse = {
132
+ data : { error : 'Username already exists' } ,
133
+ } ;
134
+
135
+ const axiosError = new AxiosError (
136
+ 'Request failed with status code 409' ,
137
+ 'ERR_CONFLICT' ,
138
+ { } as InternalAxiosRequestConfig ,
139
+ null ,
140
+ {
141
+ ...errorResponse ,
142
+ status : 409 ,
143
+ statusText : 'Conflict' ,
144
+ headers : { } ,
145
+ config : { } as InternalAxiosRequestConfig ,
146
+ }
147
+ ) ;
148
+
149
+ ( AuthService . register as jest . Mock ) . mockRejectedValue ( axiosError ) ;
150
+
151
+ render ( < LoginPanel /> ) ;
152
+ fireEvent . click ( screen . getByTestId ( 'open-login-button' ) ) ;
153
+
154
+ // toggle to Register mode
155
+ fireEvent . click ( screen . getByTestId ( 'toggle-register-button' ) ) ;
156
+
157
+ fireEvent . change ( screen . getByTestId ( 'username-input' ) , { target : { value : 'zcog' } } ) ;
158
+ fireEvent . change ( screen . getByTestId ( 'password-input' ) , { target : { value : 'P@ssword1' } } ) ;
159
+ fireEvent . click ( screen . getByTestId ( 'submit-button' ) ) ;
160
+
161
+ await waitFor ( ( ) => {
162
+ expect ( screen . getByTestId ( 'error-message' ) ) . toHaveTextContent ( 'Username already exists' ) ;
163
+ } ) ;
164
+ } ) ;
165
+ } ) ;
0 commit comments