|
16 | 16 | use Auth\AuthService; |
17 | 17 | use Auth\CustomAuthProvider; |
18 | 18 | use Auth\Exceptions\AuthenticationException; |
| 19 | +use Auth\Exceptions\UnverifiedEmailMemberException; |
19 | 20 | use Auth\Repositories\IUserRepository; |
20 | 21 | use Mockery; |
21 | 22 | use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; |
@@ -91,6 +92,7 @@ public function testValidCredentials_returnsUser_withoutEstablishingSession(): v |
91 | 92 | $password = 'Str0ng!Pass'; |
92 | 93 |
|
93 | 94 | $resolved_user = Mockery::mock('Auth\User'); |
| 95 | + $resolved_user->shouldReceive('canLogin')->once()->andReturn(true); |
94 | 96 |
|
95 | 97 | $provider_mock = Mockery::mock(CustomAuthProvider::class); |
96 | 98 | $provider_mock->shouldReceive('retrieveByCredentials') |
@@ -179,4 +181,54 @@ public function testLoginUser_throwsException_whenIsNotActive(): void |
179 | 181 | $this->service->loginUser($user, true); |
180 | 182 | } |
181 | 183 |
|
| 184 | + /** |
| 185 | + * UnverifiedEmailMemberException from the provider must be caught and |
| 186 | + * re-thrown as AuthenticationException (contract: @throws AuthenticationException only). |
| 187 | + */ |
| 188 | + public function testUnverifiedUser_throwsAuthenticationException(): void |
| 189 | + { |
| 190 | + $username = 'unverified@example.com'; |
| 191 | + $password = 'any'; |
| 192 | + |
| 193 | + $provider_mock = Mockery::mock(CustomAuthProvider::class); |
| 194 | + $provider_mock->shouldReceive('retrieveByCredentials') |
| 195 | + ->once() |
| 196 | + ->with(['username' => $username, 'password' => $password]) |
| 197 | + ->andThrow(new UnverifiedEmailMemberException('Email not verified.')); |
| 198 | + |
| 199 | + $this->auth_mock->shouldReceive('getProvider')->once()->andReturn($provider_mock); |
| 200 | + $this->auth_mock->shouldNotReceive('login'); |
| 201 | + |
| 202 | + $this->expectException(AuthenticationException::class); |
| 203 | + $this->expectExceptionMessage('Email not verified.'); |
| 204 | + |
| 205 | + $this->service->validateCredentials($username, $password); |
| 206 | + } |
| 207 | + |
| 208 | + /** |
| 209 | + * Provider returns a valid User but canLogin() is false (locked/inactive): |
| 210 | + * must throw AuthenticationException — not silently return the user. |
| 211 | + */ |
| 212 | + public function testUserCannotLogin_throwsAuthenticationException(): void |
| 213 | + { |
| 214 | + $username = 'locked@example.com'; |
| 215 | + $password = 'any'; |
| 216 | + |
| 217 | + $locked_user = Mockery::mock('Auth\User'); |
| 218 | + $locked_user->shouldReceive('canLogin')->once()->andReturn(false); |
| 219 | + |
| 220 | + $provider_mock = Mockery::mock(CustomAuthProvider::class); |
| 221 | + $provider_mock->shouldReceive('retrieveByCredentials') |
| 222 | + ->once() |
| 223 | + ->with(['username' => $username, 'password' => $password]) |
| 224 | + ->andReturn($locked_user); |
| 225 | + |
| 226 | + $this->auth_mock->shouldReceive('getProvider')->once()->andReturn($provider_mock); |
| 227 | + $this->auth_mock->shouldNotReceive('login'); |
| 228 | + |
| 229 | + $this->expectException(AuthenticationException::class); |
| 230 | + |
| 231 | + $this->service->validateCredentials($username, $password); |
| 232 | + } |
| 233 | + |
182 | 234 | } |
0 commit comments