fix: Standard-Preset löschen – nur ausdrückliche Verweise blockieren, implizite Nutzung im Probelauf

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-16 18:10:11 +02:00
co-authored by Claude Opus 5.5
parent 75714429be
commit 3d760113ec
2 changed files with 61 additions and 4 deletions
@@ -8,12 +8,14 @@ use Brain\Monkey\Functions;
use LIT\MCP\Integrations\Divi\Design\DesignChange;
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
use LIT\MCP\Integrations\Divi\Design\DiviPresetsDeleteAbility;
use LIT\MCP\Integrations\Divi\Design\PresetUsageQuery;
use LIT\MCP\Integrations\Divi\Design\SnapshotStore;
use LIT\MCP\Integrations\Divi\Library\GlobalUsages;
use LIT\MCP\Integrations\Divi\Library\UsageReport;
use LIT\MCP\Tests\Support\FakeChangeLog;
use LIT\MCP\Tests\Unit\TestCase;
use Mockery;
use ReflectionProperty;
final class DiviPresetsDeleteAbilityTest extends TestCase
{
@@ -135,6 +137,47 @@ final class DiviPresetsDeleteAbilityTest extends TestCase
self::assertToolError($this->ability(self::unused(), null, null, false)->execute($input), 'confirm_required');
}
/** @return list<bool> The default flags of a PresetUsageQuery's targets. */
private static function defaultFlags(PresetUsageQuery $query): array
{
$targets = (new ReflectionProperty(PresetUsageQuery::class, 'targets'))->getValue($query);
return array_column($targets, 'default');
}
/** Final review I-6 (spec §6.4): implicit use of a default preset does not block; the dry run lists it. */
public function testImplicitUseOfADefaultPresetIsListedNotBlocking(): void
{
$used = new UsageReport(1, [['post_id' => 3, 'title' => 'Start', 'status' => 'publish', 'type' => 'page']],
0, 1, [], 0, false);
Functions\when('current_user_can')->justReturn(true);
$writer = Mockery::mock(DesignSystemWriter::class);
$writer->allows('presets')->andReturn(PresetBookTest::stored());
$writer->allows('canUseVisualBuilder')->andReturn(true);
$usages = Mockery::mock(GlobalUsages::class);
$usages->expects('reportFor')
->with(Mockery::on(static fn (PresetUsageQuery $q): bool => self::defaultFlags($q) === [false]), false)
->andReturn(self::unused());
$usages->expects('reportFor')
->with(Mockery::on(static fn (PresetUsageQuery $q): bool => self::defaultFlags($q) === [true]))
->andReturn($used);
$ability = new DiviPresetsDeleteAbility(
$writer,
new DesignChange(Mockery::mock(SnapshotStore::class), FakeChangeLog::forbidden()),
$usages,
static fn (): bool => true
);
$dry = self::assertToolError(
$ability->execute(['items' => [['module' => 'text', 'preset' => 'Fließtext']]]),
'confirm_required'
);
self::assertSame(3, $dry['affected'][0]['post_id']);
self::assertSame(1, $dry['affected_count']);
self::assertContains('Module ohne eigenes Preset verwenden danach das Divi-Standardaussehen.', $dry['warnings']);
}
public function testUnknownPreset(): void
{
self::assertToolError(