userRepository = new FakeUserRepository; $this->passwordHasher = new FakePasswordHasher; $this->useCase = new AuthenticateUser( $this->userRepository, $this->passwordHasher, ); } public function test_null_email_throws_bad_request(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('email is required'); $this->useCase->execute(new AuthenticateUserRequest( email: null, password: 'correct-password', )); } public function test_null_password_throws_bad_request(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('password is required'); $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: null, )); } public function test_unknown_email_throws_unauthorized(): void { $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('invalid credentials'); $this->useCase->execute(new AuthenticateUserRequest( email: 'unknown@example.com', password: 'correct-password', )); } public function test_pending_user_throws_unauthorized(): void { $this->userRepository->create(new CreateUserDto( email: new EmailAddress('user@example.com'), passwordHash: null, )); $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('invalid credentials'); $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: 'correct-password', )); } public function test_wrong_password_throws_unauthorized(): void { $this->createUser('correct-password'); $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('invalid credentials'); $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: 'wrong-password', )); } public function test_valid_credentials_return_user(): void { $user = $this->createUser('correct-password'); $authenticatedUser = $this->useCase->execute( new AuthenticateUserRequest( email: 'user@example.com', password: 'correct-password', ), ); $this->assertSame($user->getId(), $authenticatedUser->getId()); $this->assertSame( $user->getEmail()->value(), $authenticatedUser->getEmail()->value(), ); } private function createUser(string $password): User { return $this->userRepository->create(new CreateUserDto( email: new EmailAddress('user@example.com'), passwordHash: $this->passwordHasher->hash($password), )); } }