Red phase: write AuthenticateUserTest with cases for valid credentials, empty email/password (null and empty string), unknown email, wrong password, and fresh instance guarantee. Fakes included.
126 lines
3.8 KiB
PHP
126 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Auth\UseCases;
|
|
|
|
use App\Auth\UseCases\AuthenticateUser\AuthenticateUser;
|
|
use App\Auth\UseCases\AuthenticateUser\AuthenticateUserRequest;
|
|
use App\Exceptions\BadRequestException;
|
|
use App\Exceptions\UnauthorizedException;
|
|
use App\Shared\ValueObject\EmailAddress;
|
|
use App\User\CreateUserDto;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Tests\Fakes\FakePasswordHasher;
|
|
use Tests\Fakes\FakeUserRepository;
|
|
|
|
class AuthenticateUserTest extends TestCase
|
|
{
|
|
private FakeUserRepository $userRepo;
|
|
private FakePasswordHasher $hasher;
|
|
private AuthenticateUser $useCase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->userRepo = new FakeUserRepository();
|
|
$this->hasher = new FakePasswordHasher();
|
|
$this->useCase = new AuthenticateUser(
|
|
$this->userRepo,
|
|
$this->hasher,
|
|
);
|
|
|
|
$this->userRepo->create(new CreateUserDto(
|
|
email: new EmailAddress('user@example.com'),
|
|
passwordHash: $this->hasher->hash('correct-password'),
|
|
));
|
|
}
|
|
|
|
public function testAuthenticatesWithValidCredentials(): void
|
|
{
|
|
$user = $this->useCase->execute(new AuthenticateUserRequest(
|
|
email: 'user@example.com',
|
|
password: 'correct-password',
|
|
));
|
|
|
|
$this->assertSame('user@example.com', $user->getEmail()->value());
|
|
}
|
|
|
|
public function testThrowsBadRequestWhenEmailIsEmpty(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('email is required');
|
|
|
|
$this->useCase->execute(new AuthenticateUserRequest(
|
|
email: '',
|
|
password: 'some-password',
|
|
));
|
|
}
|
|
|
|
public function testThrowsBadRequestWhenPasswordIsEmpty(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('password is required');
|
|
|
|
$this->useCase->execute(new AuthenticateUserRequest(
|
|
email: 'user@example.com',
|
|
password: '',
|
|
));
|
|
}
|
|
|
|
public function testThrowsBadRequestWhenEmailIsNull(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('email is required');
|
|
|
|
$this->useCase->execute(new AuthenticateUserRequest(
|
|
email: null,
|
|
password: 'some-password',
|
|
));
|
|
}
|
|
|
|
public function testThrowsBadRequestWhenPasswordIsNull(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('password is required');
|
|
|
|
$this->useCase->execute(new AuthenticateUserRequest(
|
|
email: 'user@example.com',
|
|
password: null,
|
|
));
|
|
}
|
|
|
|
public function testThrowsUnauthorizedForUnknownEmail(): void
|
|
{
|
|
$this->expectException(UnauthorizedException::class);
|
|
$this->expectExceptionMessage('invalid credentials');
|
|
|
|
$this->useCase->execute(new AuthenticateUserRequest(
|
|
email: 'unknown@example.com',
|
|
password: 'some-password',
|
|
));
|
|
}
|
|
|
|
public function testThrowsUnauthorizedForWrongPassword(): void
|
|
{
|
|
$this->expectException(UnauthorizedException::class);
|
|
$this->expectExceptionMessage('invalid credentials');
|
|
|
|
$this->useCase->execute(new AuthenticateUserRequest(
|
|
email: 'user@example.com',
|
|
password: 'wrong-password',
|
|
));
|
|
}
|
|
|
|
public function testReturnsNewInstanceOnEachCall(): void
|
|
{
|
|
$user1 = $this->useCase->execute(new AuthenticateUserRequest(
|
|
email: 'user@example.com',
|
|
password: 'correct-password',
|
|
));
|
|
|
|
$user2 = $this->useCase->execute(new AuthenticateUserRequest(
|
|
email: 'user@example.com',
|
|
password: 'correct-password',
|
|
));
|
|
|
|
$this->assertNotSame($user1, $user2);
|
|
}
|
|
}
|