135 lines
4.3 KiB
PHP
135 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\User\UseCases;
|
|
|
|
use App\Email\EmailConfirmationToken\UseCases\CreateEmailConfirmationToken;
|
|
use App\Exceptions\BadRequestException;
|
|
use App\Shared\ValueObject\EmailAddress;
|
|
use App\User\CreateUserDto;
|
|
use App\User\UseCases\SignupUser\SignupUser;
|
|
use App\User\UseCases\SignupUser\SignupUserRequest;
|
|
use DateTimeImmutable;
|
|
use DateTimeZone;
|
|
use DomainException;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Tests\Fakes\FakeClock;
|
|
use Tests\Fakes\FakeEmailConfirmationTokenRepository;
|
|
use Tests\Fakes\FakeEmailer;
|
|
use Tests\Fakes\FakeEmailFactory;
|
|
use Tests\Fakes\FakeTokenGenerator;
|
|
use Tests\Fakes\FakeUserRepository;
|
|
|
|
class SignupUserTest extends TestCase
|
|
{
|
|
private FakeUserRepository $userRepository;
|
|
|
|
private FakeEmailConfirmationTokenRepository $tokenRepository;
|
|
|
|
private FakeEmailer $emailer;
|
|
|
|
private FakeEmailFactory $emailFactory;
|
|
|
|
private SignupUser $signupUser;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->userRepository = new FakeUserRepository;
|
|
$this->tokenRepository = new FakeEmailConfirmationTokenRepository;
|
|
$this->emailer = new FakeEmailer;
|
|
$this->emailFactory = new FakeEmailFactory;
|
|
$createToken = new CreateEmailConfirmationToken(
|
|
$this->tokenRepository,
|
|
new FakeClock(new DateTimeImmutable(
|
|
'2026-08-03T12:00:00',
|
|
new DateTimeZone('UTC'),
|
|
)),
|
|
new FakeTokenGenerator(['first-token', 'second-token']),
|
|
);
|
|
$this->signupUser = new SignupUser(
|
|
$this->userRepository,
|
|
$createToken,
|
|
$this->emailer,
|
|
$this->emailFactory,
|
|
);
|
|
}
|
|
|
|
public function test_it_creates_a_pending_user_token_and_email(): void
|
|
{
|
|
$this->signupUser->execute(new SignupUserRequest(
|
|
email: ' Founder@EXAMPLE.COM ',
|
|
));
|
|
|
|
$user = $this->userRepository->findByEmail(
|
|
new EmailAddress('Founder@example.com'),
|
|
);
|
|
$this->assertNotNull($user);
|
|
$this->assertNull($user->getPasswordHash());
|
|
$token = $this->tokenRepository->findByUser($user);
|
|
$this->assertNotNull($token);
|
|
$this->assertSame('first-token', $token->getToken());
|
|
$this->assertSame(
|
|
'2026-08-03T12:10:00+00:00',
|
|
$token->getAvailableTo()->format('c'),
|
|
);
|
|
$this->assertSame(1, $this->emailer->getSendCount());
|
|
$this->assertSame(
|
|
'Founder@example.com',
|
|
$this->emailer->getLastRecipient()?->value(),
|
|
);
|
|
$this->assertSame(
|
|
'Confirm your Attainly email',
|
|
$this->emailer->getLastSubject(),
|
|
);
|
|
$this->assertSame('first-token', $this->emailFactory->getLastToken());
|
|
}
|
|
|
|
public function test_it_replaces_the_token_for_a_pending_user(): void
|
|
{
|
|
$request = new SignupUserRequest(email: 'user@example.com');
|
|
$this->signupUser->execute($request);
|
|
$this->signupUser->execute($request);
|
|
|
|
$user = $this->userRepository->findByEmail(
|
|
new EmailAddress('user@example.com'),
|
|
);
|
|
$this->assertNotNull($user);
|
|
$this->assertSame(
|
|
'second-token',
|
|
$this->tokenRepository->findByUser($user)?->getToken(),
|
|
);
|
|
$this->assertSame(2, $this->emailer->getSendCount());
|
|
}
|
|
|
|
public function test_it_rejects_an_existing_confirmed_account(): void
|
|
{
|
|
$this->userRepository->create(new CreateUserDto(
|
|
email: new EmailAddress('user@example.com'),
|
|
passwordHash: 'hashed-password',
|
|
));
|
|
|
|
$this->expectException(DomainException::class);
|
|
$this->expectExceptionMessage('user@example.com already has an account');
|
|
|
|
$this->signupUser->execute(new SignupUserRequest(
|
|
email: 'user@example.com',
|
|
));
|
|
}
|
|
|
|
public function test_it_rejects_a_missing_email(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('email is required');
|
|
|
|
$this->signupUser->execute(new SignupUserRequest(email: null));
|
|
}
|
|
|
|
public function test_it_rejects_an_invalid_email(): void
|
|
{
|
|
$this->expectException(BadRequestException::class);
|
|
$this->expectExceptionMessage('email must be valid');
|
|
|
|
$this->signupUser->execute(new SignupUserRequest(
|
|
email: 'not-an-email',
|
|
));
|
|
}
|
|
}
|