TIDE/backend/tests/Unit/User/UseCases/SignupUserTest.php
Yisroel Baum 4829a02aac
test SignupUser displayname requirement
Adds displayname to existing assertions and new tests covering:
null/short/invalid-charset displayname, duplicate displayname,
findability by displayname. AuthenticateUser tests pick up the
seedUser displayname argument.
2026-05-06 22:03:40 +03:00

207 lines
6.5 KiB
PHP

<?php
namespace Tests\Unit\User\UseCases;
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 App\User\User;
use DomainException;
use Tests\Fakes\FakePasswordHasher;
use Tests\Fakes\FakeUserRepository;
use Tests\TestCase;
class SignupUserTest extends TestCase
{
private FakeUserRepository $userRepo;
private FakePasswordHasher $hasher;
private SignupUser $useCase;
protected function setUp(): void
{
$this->userRepo = new FakeUserRepository;
$this->hasher = new FakePasswordHasher;
$this->useCase = new SignupUser(
$this->userRepo,
$this->hasher,
);
}
public function test_null_email_throws_bad_request(): void
{
$this->expectException(BadRequestException::class);
$this->useCase->execute(new SignupUserRequest(
email: null,
displayName: 'alice',
password: 'longenoughpassword',
));
}
public function test_empty_email_throws_bad_request(): void
{
$this->expectException(BadRequestException::class);
$this->useCase->execute(new SignupUserRequest(
email: '',
displayName: 'alice',
password: 'longenoughpassword',
));
}
public function test_invalid_email_format_throws_bad_request(): void
{
$this->expectException(BadRequestException::class);
$this->useCase->execute(new SignupUserRequest(
email: 'not-an-email',
displayName: 'alice',
password: 'longenoughpassword',
));
}
public function test_null_display_name_throws_bad_request(): void
{
$this->expectException(BadRequestException::class);
$this->useCase->execute(new SignupUserRequest(
email: 'user@example.com',
displayName: null,
password: 'longenoughpassword',
));
}
public function test_short_display_name_throws_bad_request(): void
{
$this->expectException(BadRequestException::class);
$this->useCase->execute(new SignupUserRequest(
email: 'user@example.com',
displayName: 'ab',
password: 'longenoughpassword',
));
}
public function test_display_name_with_invalid_chars_throws(): void
{
$this->expectException(BadRequestException::class);
$this->useCase->execute(new SignupUserRequest(
email: 'user@example.com',
displayName: 'Has Spaces',
password: 'longenoughpassword',
));
}
public function test_null_password_throws_bad_request(): void
{
$this->expectException(BadRequestException::class);
$this->useCase->execute(new SignupUserRequest(
email: 'user@example.com',
displayName: 'alice',
password: null,
));
}
public function test_short_password_throws_bad_request(): void
{
$this->expectException(BadRequestException::class);
$this->useCase->execute(new SignupUserRequest(
email: 'user@example.com',
displayName: 'alice',
password: 'short',
));
}
public function test_duplicate_email_throws_domain_exception(): void
{
$this->userRepo->create(new CreateUserDto(
email: new EmailAddress('user@example.com'),
displayName: 'first',
passwordHash: $this->hasher->hash('original-password'),
isAdmin: false,
emailConfirmedAt: null,
));
$this->expectException(DomainException::class);
$this->useCase->execute(new SignupUserRequest(
email: 'user@example.com',
displayName: 'second',
password: 'second-attempt-password',
));
}
public function test_duplicate_display_name_throws_domain_exception(): void
{
$this->userRepo->create(new CreateUserDto(
email: new EmailAddress('first@example.com'),
displayName: 'taken',
passwordHash: $this->hasher->hash('original-password'),
isAdmin: false,
emailConfirmedAt: null,
));
$this->expectException(DomainException::class);
$this->useCase->execute(new SignupUserRequest(
email: 'second@example.com',
displayName: 'taken',
password: 'second-attempt-password',
));
}
public function test_valid_signup_returns_user_with_hashed_password(): void
{
$created = $this->useCase->execute(new SignupUserRequest(
email: 'new@example.com',
displayName: 'newuser',
password: 'longenoughpassword',
));
$this->assertInstanceOf(User::class, $created);
$this->assertSame('new@example.com', $created->getEmail()->value());
$this->assertSame('newuser', $created->getDisplayName());
$this->assertSame(
$this->hasher->hash('longenoughpassword'),
$created->getPasswordHash(),
);
$this->assertFalse($created->isAdmin());
$this->assertFalse($created->isEmailConfirmed());
}
public function test_created_user_is_findable_by_email(): void
{
$created = $this->useCase->execute(new SignupUserRequest(
email: 'lookup@example.com',
displayName: 'lookup',
password: 'longenoughpassword',
));
$found = $this->userRepo->findByEmail(
new EmailAddress('lookup@example.com')
);
$this->assertNotNull($found);
$this->assertSame($created->getId(), $found->getId());
}
public function test_created_user_is_findable_by_display_name(): void
{
$created = $this->useCase->execute(new SignupUserRequest(
email: 'lookup@example.com',
displayName: 'lookupbyname',
password: 'longenoughpassword',
));
$found = $this->userRepo->findByDisplayName('lookupbyname');
$this->assertNotNull($found);
$this->assertSame($created->getId(), $found->getId());
}
public function test_signup_normalizes_email_domain(): void
{
$created = $this->useCase->execute(new SignupUserRequest(
email: 'Mixed@CASE.com',
displayName: 'mixed',
password: 'longenoughpassword',
));
$this->assertSame('Mixed@case.com', $created->getEmail()->value());
}
}