Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
110 lines
4.7 KiB
PHP
110 lines
4.7 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||
|
||
use LIT\MCP\Integrations\Divi\Design\DesignPlan;
|
||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||
use LIT\MCP\Integrations\Divi\Design\PresetArea;
|
||
use LIT\MCP\Integrations\Divi\Design\PresetRestorePlanner;
|
||
use LIT\MCP\Integrations\Divi\Design\PresetUsageQuery;
|
||
use LIT\MCP\Integrations\Divi\Library\GlobalUsages;
|
||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||
use LIT\MCP\Tests\Support\UsageFixture;
|
||
use LIT\MCP\Tests\Unit\TestCase;
|
||
use Mockery;
|
||
|
||
final class PresetRestorePlannerTest extends TestCase
|
||
{
|
||
private static function planner(bool $unfiltered = true, ?GlobalUsages $usages = null): PresetRestorePlanner
|
||
{
|
||
return new PresetRestorePlanner(
|
||
Mockery::mock(DesignSystemWriter::class),
|
||
$usages ?? UsageFixture::none(),
|
||
static fn (): bool => $unfiltered);
|
||
}
|
||
|
||
public function testAreaFeaturesAndDesignArea(): void
|
||
{
|
||
$planner = self::planner();
|
||
|
||
self::assertSame('presets', $planner->area());
|
||
self::assertSame([DiviFeature::DesignRead, DiviFeature::PresetWrite], $planner->features());
|
||
self::assertInstanceOf(PresetArea::class, $planner->designArea());
|
||
}
|
||
|
||
public function testPlansTheWholeSnapshotWithRemovals(): void
|
||
{
|
||
$older = PresetBookTest::stored();
|
||
unset($older['module']['divi/button']['items']['bbbbbbbbbb']);
|
||
|
||
$plan = self::planner()->plan(PresetBookTest::stored(), $older, 'presets-20261016T100000Z-aaaaaa');
|
||
|
||
self::assertInstanceOf(DesignPlan::class, $plan);
|
||
self::assertTrue($plan->mayRemove);
|
||
self::assertSame([['bbbbbbbbbb', 'removed']], array_map(
|
||
static fn (array $row): array => [$row['id'], $row['action']],
|
||
$plan->diff
|
||
));
|
||
self::assertStringStartsWith('Snapshot presets-20261016T100000Z-aaaaaa wiederherstellen – ', $plan->summary);
|
||
self::assertStringContainsString('Standard-Preset', $plan->warnings[0]);
|
||
}
|
||
|
||
public function testMarkupNeedsUnfilteredHtml(): void
|
||
{
|
||
$plan = self::planner(false)->plan(PresetBookTest::stored(), PresetBookTest::storedWithMarkup(), 'presets-1');
|
||
|
||
self::assertToolError($plan, 'forbidden');
|
||
}
|
||
|
||
/** Audit L4: removed and changed presets are looked up (spec §5 orphan warning stays); P8a can block. */
|
||
public function testReportsThePagesUsingRemovedPresets(): void
|
||
{
|
||
$older = PresetBookTest::stored();
|
||
unset($older['module']['divi/button']['items']['bbbbbbbbbb']);
|
||
$older['module']['divi/button']['items']['aaaaaaaaaa']['attrs'] = ['button' => ['x' => 2]];
|
||
$usages = Mockery::mock(GlobalUsages::class);
|
||
$usages->expects('reportFor')->once()->with(Mockery::on(
|
||
static fn (mixed $query): bool => $query instanceof PresetUsageQuery
|
||
&& $query->matches('<!-- wp:divi/button {"modulePreset":["bbbbbbbbbb"]} /-->')
|
||
&& $query->matches('<!-- wp:divi/button {"modulePreset":["aaaaaaaaaa"]} /-->')
|
||
&& ! $query->matches('<!-- wp:divi/button {"modulePreset":["cccccccccc"]} /-->')
|
||
))->andReturn(UsageFixture::blockedReport());
|
||
|
||
$plan = self::planner(true, $usages)->plan(PresetBookTest::stored(), $older, 'presets-1');
|
||
|
||
self::assertInstanceOf(DesignPlan::class, $plan);
|
||
self::assertTrue($plan->usages?->blocks());
|
||
self::assertStringContainsString('Standard-Preset', $plan->warnings[0]);
|
||
}
|
||
|
||
public function testNoUsageLookupWithoutChangedOrRemovedPresets(): void
|
||
{
|
||
$usages = Mockery::mock(GlobalUsages::class);
|
||
$usages->expects('reportFor')->never();
|
||
|
||
$plan = self::planner(true, $usages)->plan(PresetBookTest::stored(), PresetBookTest::stored(), 'presets-1');
|
||
|
||
self::assertInstanceOf(DesignPlan::class, $plan);
|
||
self::assertNull($plan->usages);
|
||
}
|
||
|
||
/** Audit L4 (re-review): a preset becoming the default reaches modules without an own preset – looked up as default. */
|
||
public function testALookupCoversPresetsTheSnapshotMakesDefault(): void
|
||
{
|
||
$older = PresetBookTest::stored();
|
||
$older['module']['divi/button']['default'] = 'aaaaaaaaaa';
|
||
$usages = Mockery::mock(GlobalUsages::class);
|
||
$usages->expects('reportFor')->once()->with(Mockery::on(
|
||
static fn (mixed $query): bool => $query instanceof PresetUsageQuery
|
||
&& $query->matches('<!-- wp:divi/button {} /-->')
|
||
))->andReturn(UsageFixture::blockedReport());
|
||
|
||
$plan = self::planner(true, $usages)->plan(PresetBookTest::stored(), $older, 'presets-1');
|
||
|
||
self::assertInstanceOf(DesignPlan::class, $plan);
|
||
self::assertTrue($plan->usages?->blocks());
|
||
}
|
||
}
|