fix: Divi-Reiter ohne Divi, Zustandstexte, Schreibsperren und Aufräum-Filter aus der Abschlussprüfung

Behebt die fünf Befunde der Abschlussprüfung von divi-absicherung: Divi-Reiter ohne aktives Divi zeigt nur
noch einen Hinweis (kein Status, keine Prüfung, kein Aufräumen), Zustandstexte werden erst beim Rendern
übersetzt, DiviPages::setFlags() und DiviThemeBuilder::liveId(true) prüfen jetzt selbst die
Freigabesperre, WriteProbe::removeOrphans() löscht nur noch Entwürfe mit passendem Titel, und
wp lit-mcp divi-check --update-reference verweigert sich ohne Entwicklungskopie, bevor irgendetwas
geschrieben wird.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-30 03:33:16 +02:00
co-authored by Claude Opus 5.5
parent 35ea47d832
commit 43c0a78374
9 changed files with 122 additions and 24 deletions
+28
View File
@@ -200,6 +200,34 @@ final class DiviTabTest extends TestCase
self::assertStringContainsString('Freigabe zurückziehen', $this->rendered($status, self::report()));
}
public function testWithoutDiviShowsOnlyAShortNotice(): void
{
ReleaseGate::useResolver(static function (): ReleaseStatus {
self::fail('resolver called although Divi is not active');
});
$reports = Mockery::mock(CheckReportStore::class);
$reports->expects('latest')->never();
$tab = new DiviTab(
$reports,
Mockery::mock(ReleaseStore::class),
FakeChangeLog::forbidden(),
new AdminPostAction(static function (): void {
}),
static fn (): string => '',
static fn (string $version): string => 'key'
);
ob_start();
$tab->render();
$html = (string) ob_get_clean();
self::assertStringContainsString(
'Divi ist auf dieser Website nicht aktiv; die Divi-Freigabe ist ohne Bedeutung.',
$html
);
self::assertStringNotContainsString('Prüfung starten', $html);
}
public function testIncompatibleListsTheProblems(): void
{
$html = $this->rendered(
+18 -3
View File
@@ -49,8 +49,11 @@ final class DiviCheckCommandTest extends TestCase
* @param bool $expectSave True asserts save() is called exactly once (the green happy path); otherwise it is
* merely allowed, since some tests (e.g. no admin) never reach the save() call.
*/
private function command(array $problems = [], bool $expectSave = false): DiviCheckCommand
{
private function command(
array $problems = [],
bool $expectSave = false,
bool $noSourceDir = false
): DiviCheckCommand {
$steps = array_map(
static fn (string $key): CheckStep => new CheckStep($key, $problems[$key] ?? []),
[CheckStep::MANIFEST, CheckStep::MIRRORS, CheckStep::CATALOG, CheckStep::FORMAT, CheckStep::WRITE]
@@ -72,7 +75,7 @@ final class DiviCheckCommandTest extends TestCase
},
fn (): ?string => $this->themeDir,
$this->expectedFile,
fn (): ?string => $this->sourceDir
$noSourceDir ? static fn (): ?string => null : fn (): ?string => $this->sourceDir
);
}
@@ -105,6 +108,18 @@ final class DiviCheckCommandTest extends TestCase
self::assertFileDoesNotExist($this->expectedFile);
}
public function testUpdateReferenceRefusesWithoutADevelopmentSourceDir(): void
{
$code = $this->command(noSourceDir: true)->run(['update-reference' => true]);
self::assertSame(1, $code);
self::assertStringContainsString(
'Referenz nicht aktualisiert: nur in einer Entwicklungskopie mit tests/ möglich.',
implode("\n", $this->lines)
);
self::assertFileDoesNotExist($this->expectedFile);
}
public function testDiffShowsWhatChangedInAMirroredFunction(): void
{
file_put_contents(
@@ -7,6 +7,7 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
use Brain\Monkey\Functions;
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
use LIT\MCP\Integrations\Divi\Library\LibraryItemSpec;
use LIT\MCP\Integrations\Divi\Pages\DiviPages;
use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
@@ -56,6 +57,8 @@ final class ReleaseGuardsTest extends TestCase
yield 'tb setConditions' => [static fn () => (new DiviThemeBuilder())->setConditions(9, ['singular'], [])];
yield 'tb setEnabled' => [static fn () => (new DiviThemeBuilder())->setEnabled(9, true)];
yield 'tb unmarkUnused' => [static fn () => (new DiviThemeBuilder())->unmarkUnused(9)];
yield 'pages setFlags' => [static fn () => DiviPages::setFlags(7)];
yield 'tb liveId create' => [static fn () => (new DiviThemeBuilder())->liveId(true)];
}
/** @dataProvider writes */
@@ -149,11 +149,24 @@ final class WriteProbeTest extends TestCase
{
Functions\expect('get_posts')->once()->with(Mockery::on(static fn (array $query): bool =>
$query['meta_key'] === '_lit_mcp_check_page'
&& $query['post_status'] === 'any'
&& $query['fields'] === 'ids'
&& ($query['date_query'][0]['before'] ?? null) === '10 minutes ago'))->andReturn([51, 52]);
&& $query['post_status'] === 'draft'
&& $query['fields'] === 'all'
&& ($query['date_query'][0]['before'] ?? null) === '10 minutes ago'))->andReturn([
new WP_Post(['ID' => 51, 'post_title' => WriteProbe::TITLE . ' 2026-01-01 00:00']),
new WP_Post(['ID' => 52, 'post_title' => WriteProbe::TITLE . ' 2026-01-02 00:00']),
]);
self::assertSame([51, 52], WriteProbe::removeOrphans());
self::assertSame([51, 52], $this->deleted);
}
public function testKeepsAMarkedDraftWhoseTitleDoesNotMatch(): void
{
Functions\when('get_posts')->justReturn([
new WP_Post(['ID' => 60, 'post_title' => 'Ein anderer Entwurf']),
]);
self::assertSame([], WriteProbe::removeOrphans());
self::assertSame([], $this->deleted);
}
}