feat: divi-check gibt die Matrix je Fähigkeit aus (Exit 2 bei nicht nutzbarer Fähigkeit); Texte nennen Fähigkeiten statt pauschal gesperrt

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-18 22:29:38 +02:00
co-authored by Claude Sonnet 5.5
parent 2aef6e1154
commit a4faeda326
4 changed files with 204 additions and 45 deletions
+107 -2
View File
@@ -10,7 +10,14 @@ use LIT\MCP\Integrations\Divi\Release\CheckReport;
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
use LIT\MCP\Integrations\Divi\Release\CheckStep;
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
use LIT\MCP\Integrations\Divi\Release\DiviReference;
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
use LIT\MCP\Tests\Support\MatrixFixtures;
use LIT\MCP\Tests\Unit\TestCase;
use Mockery;
use RuntimeException;
@@ -61,7 +68,8 @@ final class DiviCheckCommandTest extends TestCase
private function command(
array $problems = [],
bool $expectSave = false,
bool $noSourceDir = false
bool $noSourceDir = false,
?CompatibilityMatrix $matrix = null
): DiviCheckCommand {
$steps = array_map(
static fn (string $key): CheckStep => new CheckStep($key, $problems[$key] ?? []),
@@ -91,7 +99,8 @@ final class DiviCheckCommandTest extends TestCase
}
return $this->signatures;
}
},
$matrix === null ? null : static fn (): CompatibilityMatrix => $matrix
);
}
@@ -256,4 +265,100 @@ final class DiviCheckCommandTest extends TestCase
file_put_contents($file, "<?php\n" . $code . "\n");
}
}
public function testPrintsTheMatrixAfterTheReport(): void
{
self::assertSame(0, $this->command()->run([]));
$schreibtest = array_search('✓ Schreibtest auf einer Wegwerfseite', $this->lines, true);
$header = array_search('Fähigkeiten:', $this->lines, true);
self::assertIsInt($schreibtest);
self::assertIsInt($header);
self::assertGreaterThan($schreibtest, $header);
self::assertContains('✓ Seiten schreiben – freigegeben (code)', $this->lines);
self::assertContains('✓ Theme Builder lesen – freigegeben (code)', $this->lines);
}
public function testEveryFeatureGetsOneLine(): void
{
$this->command()->run([]);
$matrixLines = array_filter(
$this->lines,
static fn (string $line): bool => str_contains($line, ' – freigegeben')
);
self::assertCount(count(DiviFeature::cases()), $matrixLines);
}
public function testAnIncompatibleFeatureFailsWithItsProblemsIndented(): void
{
$matrix = MatrixFixtures::with(
DiviFeature::PageWrite,
ReleaseState::Incompatible,
'auto',
'Seiten: et_pb_x() fehlt'
);
$code = $this->command(matrix: $matrix)->run([]);
self::assertSame(2, $code);
self::assertContains('✗ Seiten schreiben – inkompatibel', $this->lines);
self::assertContains(' Seiten: et_pb_x() fehlt', $this->lines);
self::assertContains('✓ Seiten lesen – freigegeben (auto)', $this->lines);
}
public function testAnUntestedFeatureFailsWithExitTwoAlthoughTheReportIsGreen(): void
{
$matrix = MatrixFixtures::with(DiviFeature::Catalog, ReleaseState::Untested, 'auto');
$code = $this->command(expectSave: true, matrix: $matrix)->run([]);
self::assertSame(2, $code);
self::assertContains('– Modulkatalog – ungetestet', $this->lines);
}
public function testARedReportKeepsExitOneWhateverTheMatrixSays(): void
{
$red = [CheckStep::CATALOG => ['divi/text: unbekanntes Modul']];
$incompatible = MatrixFixtures::with(DiviFeature::Catalog, ReleaseState::Incompatible, 'auto', 'x');
self::assertSame(1, $this->command($red)->run([]));
self::assertSame(1, $this->command($red, matrix: $incompatible)->run([]));
}
public function testUpdateReferenceKeepsItsOwnExitCodeAndStillPrintsTheMatrix(): void
{
$this->writeDivi();
$matrix = MatrixFixtures::with(
DiviFeature::PageWrite,
ReleaseState::Incompatible,
'auto',
'Seiten: Nachbau geändert'
);
$code = $this->command([CheckStep::MIRRORS => ['geändert']], matrix: $matrix)
->run(['update-reference' => true]);
self::assertSame(0, $code);
self::assertContains('✗ Seiten schreiben – inkompatibel', $this->lines);
}
public function testWithoutAnInjectedMatrixTheStateIsComputedAfterTheCheck(): void
{
$order = [];
Functions\when('delete_transient')->alias(static function (string $key) use (&$order): bool {
$order[] = 'delete:' . $key;
return true;
});
ReleaseGate::useResolver(static function () use (&$order): ReleaseStatus {
$order[] = 'resolve';
return ReleaseStatus::released('5.3.0');
});
$this->command()->run([]);
self::assertSame(['delete:' . ReleaseResolver::CACHE, 'resolve'], $order);
}
}
@@ -30,12 +30,14 @@ final class ReleaseStatusTest extends TestCase
);
self::assertSame(
'Achtung: Divi 5.3.0 ist auf dieser Website noch nicht für LIT MCP freigegeben. Schreibende '
. 'Divi-Werkzeuge sind gesperrt, bis ein Administrator unter Einstellungen → LIT MCP → Divi die '
. 'Prüfung ausführt und die Version freigibt. Es wurde nichts geändert.',
'Achtung: Divi 5.3.0 ist auf dieser Website noch nicht für LIT MCP freigegeben. Dieses Werkzeug braucht '
. 'Divi-Fähigkeiten, die noch nicht geprüft sind; andere Divi-Werkzeuge laufen weiter. Ein '
. 'Administrator kann unter Einstellungen → LIT MCP → Divi die Prüfung ausführen und die Version '
. 'freigeben. Es wurde nichts geändert.',
$payload['message']
);
self::assertStringContainsString('lesende Divi-Werkzeuge funktionieren weiter', $payload['hint']);
self::assertStringContainsString('ein Werkzeug ohne die betroffene Fähigkeit nutzen', $payload['hint']);
self::assertStringContainsString('components → divi → features', $payload['hint']);
}
public function testIncompatibleRefusalListsTheProblems(): void
@@ -44,26 +46,14 @@ final class ReleaseStatusTest extends TestCase
$payload = self::assertToolError($status->refusal(), 'divi_incompatible');
self::assertSame(
'Divi 5.3.0 hat Stellen geändert, die LIT MCP nutzt. Schreibende Divi-Werkzeuge sind gesperrt, bis '
. 'LIT MCP aktualisiert wurde. Es wurde nichts geändert.',
'Divi 5.3.0 hat Stellen geändert, die LIT MCP für dieses Werkzeug nutzt; andere Divi-Werkzeuge laufen '
. 'weiter. Die betroffenen Werkzeuge bleiben gesperrt, bis LIT MCP aktualisiert wurde. Es wurde '
. 'nichts geändert.',
$payload['message']
);
self::assertSame(['Theme Builder: Nachbau von x()'], $payload['problems']);
}
public function testNoticesForReadingTools(): void
{
self::assertSame(
'Achtung: Divi 5.3.0 ist für LIT MCP ungetestet; Lesen funktioniert, Schreiben ist gesperrt.',
(new ReleaseStatus(ReleaseState::Untested, '5.3.0'))->notice()
);
self::assertSame(
'Achtung: Divi (Version unbekannt) ist für LIT MCP inkompatibel; Lesen funktioniert, Schreiben ist '
. 'gesperrt.',
(new ReleaseStatus(ReleaseState::Incompatible, ''))->notice()
);
}
public function testAReleasedStatusHasNoRefusal(): void
{
$this->expectException(LogicException::class);