- Add phpunit/phpunit ^13.2, symfony/browser-kit and symfony/css-selector to require-dev, plus the autoload-dev mapping for App\Tests- Add phpunit.dist.xml (strict deprecation/notice/warning failures, APP_ENV=test forced) and .env.test / bin/phpunit / tests/bootstrap.php from the PHPUnit recipe - Add tests/Support/TotpTestHelper providing a deterministic TOTP fixture, frozen clock and ConfigBag/cache-pool helpers - Add 121 unit tests covering Clock, ConfigBag, Data/Payload, Enum/Scope, MonitorCacheKeys, PersistCache, Utilities, all five Traits and the three Service managers (BackupCode, Domain, Login) - Fix LoginManagerTest nonce lookups to use makeCacheKey() so the cache key matches the one the manager actually reads/writes - Gitignore bin/.phpunit.result.cache
70 lines
2.2 KiB
PHP
70 lines
2.2 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Unit;
|
|
|
|
use App\Utilities;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Psr\Clock\ClockInterface;
|
|
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
|
|
|
final class UtilitiesTest extends TestCase {
|
|
private function makeUtilities(?ArrayAdapter $pool = null, ?ClockInterface $clock = null): Utilities {
|
|
$pool ??= new ArrayAdapter();
|
|
$clock ??= $this->createStub(ClockInterface::class);
|
|
return new Utilities($clock, $pool);
|
|
}
|
|
|
|
public function testLoadTotpReturnsCachedValueWhenPresent(): void {
|
|
$pool = new ArrayAdapter();
|
|
$item = $pool->getItem('totp');
|
|
$item->set('otpauth://totp/cached?secret=ABCDEFGH');
|
|
$pool->save($item);
|
|
|
|
$utilities = $this->makeUtilities($pool);
|
|
|
|
$result = $utilities->loadTotp();
|
|
|
|
self::assertSame('otpauth://totp/cached?secret=ABCDEFGH', $result);
|
|
}
|
|
|
|
public function testLoadTotpGeneratesAndStoresWhenMissing(): void {
|
|
$pool = new ArrayAdapter();
|
|
$utilities = $this->makeUtilities($pool);
|
|
|
|
$result = $utilities->loadTotp();
|
|
|
|
self::assertNotEmpty($result);
|
|
self::assertStringStartsWith('otpauth://totp/', $result);
|
|
|
|
// stored in cache for next boot
|
|
$cached = $pool->getItem('totp');
|
|
self::assertTrue($cached->isHit());
|
|
self::assertSame($result, $cached->get());
|
|
}
|
|
|
|
public function testLoadTotpSetsFarFutureExpiry(): void {
|
|
$pool = new ArrayAdapter();
|
|
$utilities = $this->makeUtilities($pool);
|
|
|
|
$utilities->loadTotp();
|
|
|
|
$cached = $pool->getItem('totp');
|
|
$expiry = $cached->getMetadata()['expiry'];
|
|
// 2999-12-31 is well in the future, far beyond any reasonable test timestamp
|
|
self::assertGreaterThan((new \DateTimeImmutable('+10 years'))->getTimestamp(), (int) $expiry);
|
|
}
|
|
|
|
public function testLoadTotpIsIdempotentAfterGeneration(): void {
|
|
$pool = new ArrayAdapter();
|
|
$utilities = $this->makeUtilities($pool);
|
|
|
|
$first = $utilities->loadTotp();
|
|
|
|
// second call should find it in cache and return the same value
|
|
$second = $utilities->loadTotp();
|
|
|
|
self::assertSame($first, $second);
|
|
}
|
|
}
|