userRepo = new FakeUserRepository; $this->useCase = new PromoteUserToAdmin($this->userRepo); } private function seedUser(bool $isAdmin): int { $user = $this->userRepo->create(new CreateUserDto( email: new EmailAddress('user@example.com'), displayName: 'user', passwordHash: 'h', isAdmin: $isAdmin, emailConfirmedAt: null, )); return $user->getId(); } public function test_non_admin_requester_throws_forbidden(): void { $userId = $this->seedUser(false); $this->expectException(ForbiddenException::class); $this->useCase->execute(new PromoteUserToAdminRequest( targetUserId: $userId, requesterIsAdmin: false, )); } public function test_zero_target_id_throws_bad_request(): void { $this->expectException(BadRequestException::class); $this->useCase->execute(new PromoteUserToAdminRequest( targetUserId: 0, requesterIsAdmin: true, )); } public function test_unknown_user_throws_domain_exception(): void { $this->expectException(DomainException::class); $this->useCase->execute(new PromoteUserToAdminRequest( targetUserId: 999, requesterIsAdmin: true, )); } public function test_admin_promotes_target(): void { $userId = $this->seedUser(false); $this->useCase->execute(new PromoteUserToAdminRequest( targetUserId: $userId, requesterIsAdmin: true, )); $reloaded = $this->userRepo->find($userId); $this->assertTrue($reloaded->isAdmin()); } public function test_already_admin_is_idempotent(): void { $userId = $this->seedUser(true); $this->useCase->execute(new PromoteUserToAdminRequest( targetUserId: $userId, requesterIsAdmin: true, )); $reloaded = $this->userRepo->find($userId); $this->assertTrue($reloaded->isAdmin()); } }