feat: Divi release status, store, resolver and gate
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use RuntimeException;
|
||||
|
||||
final class ReleaseGateTest extends TestCase
|
||||
{
|
||||
private function untested(): void
|
||||
{
|
||||
ReleaseGate::useResolver(static fn (): ReleaseStatus => new ReleaseStatus(ReleaseState::Untested, '5.3.0'));
|
||||
}
|
||||
|
||||
public function testTheTestCaseDefaultIsReleased(): void
|
||||
{
|
||||
self::assertTrue(ReleaseGate::status()->writable());
|
||||
ReleaseGate::assertWritable(7);
|
||||
}
|
||||
|
||||
public function testAssertWritableThrowsTheLockWithTheStatus(): void
|
||||
{
|
||||
$this->untested();
|
||||
|
||||
try {
|
||||
ReleaseGate::assertWritable(7);
|
||||
self::fail('an untested Divi must lock writes');
|
||||
} catch (DiviLocked $locked) {
|
||||
self::assertSame('5.3.0', $locked->status->version);
|
||||
self::assertToolError($locked->toError(), 'divi_untested');
|
||||
}
|
||||
}
|
||||
|
||||
public function testProbingAllowsOnlyThatPostAndOnlyMeanwhile(): void
|
||||
{
|
||||
$this->untested();
|
||||
|
||||
$result = ReleaseGate::whileProbing(41, static function (): string {
|
||||
ReleaseGate::assertWritable(41);
|
||||
|
||||
return 'written';
|
||||
});
|
||||
self::assertSame('written', $result);
|
||||
|
||||
foreach ([static fn () => ReleaseGate::whileProbing(41, static fn () => ReleaseGate::assertWritable(42)),
|
||||
static fn () => ReleaseGate::whileProbing(41, static fn () => ReleaseGate::assertWritable()),
|
||||
static fn () => ReleaseGate::assertWritable(41)] as $attempt) {
|
||||
try {
|
||||
$attempt();
|
||||
self::fail('only post 41, only while probing');
|
||||
} catch (DiviLocked) {
|
||||
self::addToAssertionCount(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testProbingEndsEvenWhenTheWriteThrows(): void
|
||||
{
|
||||
$this->untested();
|
||||
|
||||
try {
|
||||
ReleaseGate::whileProbing(41, static function (): never {
|
||||
throw new RuntimeException('boom');
|
||||
});
|
||||
} catch (RuntimeException) {
|
||||
}
|
||||
|
||||
$this->expectException(DiviLocked::class);
|
||||
ReleaseGate::assertWritable(41);
|
||||
}
|
||||
|
||||
public function testStatusIsComputedOncePerRequestUntilForgotten(): void
|
||||
{
|
||||
$calls = 0;
|
||||
ReleaseGate::useResolver(static function () use (&$calls): ReleaseStatus {
|
||||
++$calls;
|
||||
|
||||
return ReleaseStatus::released('5.2.1');
|
||||
});
|
||||
|
||||
ReleaseGate::status();
|
||||
ReleaseGate::status();
|
||||
self::assertSame(1, $calls);
|
||||
|
||||
ReleaseGate::forget();
|
||||
ReleaseGate::status();
|
||||
self::assertSame(2, $calls);
|
||||
}
|
||||
|
||||
public function testAFailingResolverLocksWrites(): void
|
||||
{
|
||||
ReleaseGate::useResolver(static function (): never {
|
||||
throw new RuntimeException('theme API gone');
|
||||
});
|
||||
$log = (string) tempnam(sys_get_temp_dir(), 'lit-mcp-log');
|
||||
$previous = ini_set('error_log', $log);
|
||||
|
||||
try {
|
||||
$status = ReleaseGate::status();
|
||||
} finally {
|
||||
ini_set('error_log', (string) $previous);
|
||||
}
|
||||
|
||||
self::assertSame(ReleaseState::Incompatible, $status->state);
|
||||
self::assertStringContainsString('theme API gone', (string) file_get_contents($log));
|
||||
unlink($log);
|
||||
$this->expectException(DiviLocked::class);
|
||||
ReleaseGate::assertWritable();
|
||||
}
|
||||
|
||||
public function testFindsTheLockInsideAWrappedFailure(): void
|
||||
{
|
||||
$locked = new DiviLocked(new ReleaseStatus(ReleaseState::Untested, '5.3.0'));
|
||||
$wrapped = WriteFailed::rolledBack('Nicht gespeichert.', new RuntimeException('draft', 0, $locked));
|
||||
|
||||
self::assertSame($locked, DiviLocked::in($wrapped));
|
||||
self::assertNull(DiviLocked::in(new RuntimeException('other')));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user