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, password: 'longenoughpassword', )); } public function test_empty_email_throws_bad_request(): void { $this->expectException(BadRequestException::class); $this->useCase->execute(new SignupUserRequest( email: '', 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', password: 'longenoughpassword', )); } public function test_null_password_throws_bad_request(): void { $this->expectException(BadRequestException::class); $this->useCase->execute(new SignupUserRequest( email: 'user@example.com', password: null, )); } public function test_short_password_throws_bad_request(): void { $this->expectException(BadRequestException::class); $this->useCase->execute(new SignupUserRequest( email: 'user@example.com', password: 'short', )); } public function test_duplicate_email_throws_domain_exception(): void { $this->userRepo->create(new CreateUserDto( email: new EmailAddress('user@example.com'), passwordHash: $this->hasher->hash('original-password'), isAdmin: false, )); $this->expectException(DomainException::class); $this->useCase->execute(new SignupUserRequest( email: 'user@example.com', 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', password: 'longenoughpassword', )); $this->assertInstanceOf(User::class, $created); $this->assertSame('new@example.com', $created->getEmail()->value()); $this->assertSame( $this->hasher->hash('longenoughpassword'), $created->getPasswordHash(), ); $this->assertFalse($created->isAdmin()); } public function test_created_user_is_findable_by_email(): void { $created = $this->useCase->execute(new SignupUserRequest( email: 'lookup@example.com', password: 'longenoughpassword', )); $found = $this->userRepo->findByEmail( new EmailAddress('lookup@example.com') ); $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', password: 'longenoughpassword', )); $this->assertSame('Mixed@case.com', $created->getEmail()->value()); } }