Files
Gnuboard7/tests/Unit/Extension/IdentityVerification/IdentityVerificationManagerTest.php
T
2026-05-11 11:29:41 +09:00

184 lines
5.5 KiB
PHP

<?php
namespace Tests\Unit\Extension\IdentityVerification;
use App\Contracts\Extension\IdentityVerificationInterface;
use App\Extension\HookManager;
use App\Extension\IdentityVerification\DTO\VerificationChallenge;
use App\Extension\IdentityVerification\DTO\VerificationResult;
use App\Extension\IdentityVerification\IdentityVerificationManager;
use App\Models\User;
use Carbon\Carbon;
use InvalidArgumentException;
use Tests\TestCase;
/**
* IdentityVerificationManager 테스트.
*
* 프로바이더 등록/해제/resolveForPurpose/필터 훅 통과 후 병합 동작을 검증.
*/
class IdentityVerificationManagerTest extends TestCase
{
private IdentityVerificationManager $manager;
protected function setUp(): void
{
parent::setUp();
HookManager::resetAll();
$this->manager = new IdentityVerificationManager();
}
protected function tearDown(): void
{
HookManager::resetAll();
parent::tearDown();
}
public function test_register_and_get_provider(): void
{
$provider = $this->makeProvider('dummy', true, true);
$this->manager->register($provider);
$this->assertTrue($this->manager->has('dummy'));
$this->assertSame($provider, $this->manager->get('dummy'));
}
public function test_unregister_removes_provider(): void
{
$provider = $this->makeProvider('dummy', true, true);
$this->manager->register($provider);
$this->manager->unregister('dummy');
$this->assertFalse($this->manager->has('dummy'));
}
public function test_get_unknown_throws(): void
{
$this->expectException(InvalidArgumentException::class);
$this->manager->get('nonexistent');
}
public function test_all_runs_through_filter_hook(): void
{
$mail = $this->makeProvider('g7:core.mail', true, true);
$this->manager->register($mail);
$injected = $this->makeProvider('plugin:fake', true, true);
HookManager::addFilter('core.identity.registered_providers', function (array $providers) use ($injected) {
$providers[$injected->getId()] = $injected;
return $providers;
});
$all = $this->manager->all();
$this->assertArrayHasKey('g7:core.mail', $all);
$this->assertArrayHasKey('plugin:fake', $all);
}
public function test_resolve_for_purpose_returns_provider_supporting_purpose(): void
{
$mail = $this->makeProvider('g7:core.mail', true, true);
$this->manager->register($mail);
$resolved = $this->manager->resolveForPurpose('signup');
$this->assertSame('g7:core.mail', $resolved->getId());
}
public function test_resolve_for_purpose_falls_back_when_default_unsupported(): void
{
$unsupported = $this->makeProvider('g7:core.mail', true, false);
$supporter = $this->makeProvider('plugin:kcp', true, true);
$this->manager->register($unsupported);
$this->manager->register($supporter);
$resolved = $this->manager->resolveForPurpose('signup');
$this->assertSame('plugin:kcp', $resolved->getId());
}
/**
* IdentityVerificationInterface 더블을 생성합니다.
*/
private function makeProvider(string $id, bool $available, bool $supportsAll): IdentityVerificationInterface
{
return new class($id, $available, $supportsAll) implements IdentityVerificationInterface
{
public function __construct(
private string $id,
private bool $available,
private bool $supportsAll,
) {}
public function getId(): string
{
return $this->id;
}
public function getLabel(): string
{
return $this->id;
}
public function getChannels(): array
{
return ['email'];
}
public function getRenderHint(): string
{
return 'text_code';
}
public function supportsPurpose(string $purpose): bool
{
return $this->supportsAll;
}
public function isAvailable(): bool
{
return $this->available;
}
public function requestChallenge(User|array $target, array $context = []): VerificationChallenge
{
return new VerificationChallenge(
id: 'dummy-id',
providerId: $this->id,
purpose: $context['purpose'] ?? 'sensitive_action',
channel: 'email',
targetHash: str_repeat('0', 64),
expiresAt: Carbon::now()->addMinutes(15),
renderHint: 'text_code',
);
}
public function verify(string $challengeId, array $input, array $context = []): VerificationResult
{
return VerificationResult::success(
challengeId: $challengeId,
providerId: $this->id,
verifiedAt: Carbon::now(),
);
}
public function cancel(string $challengeId): bool
{
return true;
}
public function getSettingsSchema(): array
{
return [];
}
public function withConfig(array $config): static
{
return $this;
}
};
}
}