Add a trivial prefix-based PasswordHasher fake and inject it into the three test files that exercise CreateUser or AuthenticateUser. Drops the full phpunit suite from ~7.4s to ~30ms (about 224x) without losing coverage: the round-trip through hash/verify still validates that CreateUser stores something other than the plaintext and that AuthenticateUser only succeeds on a matching hash. CreateUserTest is also refactored to use a setUp method, matching the pattern already used in AuthenticateUserTest and AuthControllerTest.
126 lines
3.6 KiB
PHP
126 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\User\UseCases;
|
|
|
|
use App\Exceptions\BadRequestException;
|
|
use App\User\User;
|
|
use App\User\UseCases\CreateUser;
|
|
use App\User\UseCases\CreateUserRequest;
|
|
use Tests\Fakes\FakePasswordHasher;
|
|
use Tests\Fakes\FakeUserRepository;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class CreateUserTest extends TestCase
|
|
{
|
|
private FakeUserRepository $userRepo;
|
|
private FakePasswordHasher $passwordHasher;
|
|
private CreateUser $useCase;
|
|
|
|
public function setUp(): void
|
|
{
|
|
$this->userRepo = new FakeUserRepository();
|
|
$this->passwordHasher = new FakePasswordHasher();
|
|
$this->useCase = new CreateUser(
|
|
$this->userRepo,
|
|
$this->passwordHasher,
|
|
);
|
|
}
|
|
|
|
public function test_create_user(): void
|
|
{
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: 'test@test.com',
|
|
password: 'password1',
|
|
));
|
|
$user = $this->userRepo->find(0);
|
|
$this->assertInstanceOf(User::class, $user);
|
|
$this->assertEquals('test@test.com', $user->getEmail());
|
|
}
|
|
|
|
public function test_throws_if_email_is_null(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('email is required');
|
|
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: null,
|
|
));
|
|
}
|
|
|
|
public function test_is_admin_defaults_to_false(): void
|
|
{
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: 'test@test.com',
|
|
password: 'password1',
|
|
));
|
|
$user = $this->userRepo->find(0);
|
|
$this->assertFalse($user->isAdmin());
|
|
}
|
|
|
|
public function test_is_admin_can_be_set_true(): void
|
|
{
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: 'test@test.com',
|
|
password: 'password1',
|
|
isAdmin: true,
|
|
));
|
|
$user = $this->userRepo->find(0);
|
|
$this->assertTrue($user->isAdmin());
|
|
}
|
|
|
|
public function test_throws_when_email_already_taken(): void
|
|
{
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: 'test@test.com',
|
|
password: 'password1',
|
|
));
|
|
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('email already taken');
|
|
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: 'test@test.com',
|
|
password: 'password1',
|
|
));
|
|
}
|
|
|
|
public function test_throws_if_password_is_null(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('password is required');
|
|
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: 'test@test.com',
|
|
password: null,
|
|
));
|
|
}
|
|
|
|
public function test_throws_if_password_too_short(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage(
|
|
'password must be at least 8 characters'
|
|
);
|
|
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: 'test@test.com',
|
|
password: 'short',
|
|
));
|
|
}
|
|
|
|
public function test_stores_hashed_password(): void
|
|
{
|
|
$this->useCase->execute(new CreateUserRequest(
|
|
email: 'test@test.com',
|
|
password: 'password1',
|
|
));
|
|
$user = $this->userRepo->find(0);
|
|
$this->assertNotEquals('password1', $user->getPasswordHash());
|
|
$this->assertTrue(
|
|
$this->passwordHasher->verify(
|
|
'password1',
|
|
$user->getPasswordHash()
|
|
)
|
|
);
|
|
}
|
|
}
|