Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
132 lines
6.2 KiB
PHP
132 lines
6.2 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||
|
||
use Brain\Monkey\Functions;
|
||
use LIT\MCP\Integrations\Divi\Design\DesignChange;
|
||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||
use LIT\MCP\Integrations\Divi\Design\DiviDesignRestoreAbility;
|
||
use LIT\MCP\Integrations\Divi\Design\PresetRestorePlanner;
|
||
use LIT\MCP\Integrations\Divi\Design\SnapshotStore;
|
||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||
use LIT\MCP\Tests\Unit\TestCase;
|
||
use Mockery;
|
||
|
||
final class DiviDesignRestoreAbilityTest extends TestCase
|
||
{
|
||
protected function setUp(): void
|
||
{
|
||
parent::setUp();
|
||
// DesignLock (final review I-5): the lock is always free here.
|
||
Functions\when('add_option')->justReturn(true);
|
||
Functions\when('delete_option')->justReturn(true);
|
||
}
|
||
|
||
public function testRestoresWithDryRunAndASnapshotOfTheCurrentState(): void
|
||
{
|
||
Functions\when('current_user_can')->justReturn(true);
|
||
$older = PresetBookTest::stored();
|
||
unset($older['module']['divi/button']['items']['bbbbbbbbbb']);
|
||
$writer = Mockery::mock(DesignSystemWriter::class);
|
||
$writer->allows('presets')->andReturn(PresetBookTest::stored());
|
||
$writer->allows('canUseVisualBuilder')->andReturn(true);
|
||
$writer->expects('savePresets')->with(Mockery::type('array'), true)->andReturn($older);
|
||
$snapshots = Mockery::mock(SnapshotStore::class);
|
||
$snapshots->allows('get')->with('presets', 'presets-20261016T100000Z-aaaaaa')->andReturn(['id' => 'presets-20261016T100000Z-aaaaaa', 'data' => $older,
|
||
'created' => 'x', 'user_id' => 1, 'ability' => 'lit/divi-presets-set', 'log_id' => 2, 'size' => 1]);
|
||
$snapshots->expects('save')->with('presets', Mockery::type('array'), 'lit/divi-design-restore')->andReturn('presets-3');
|
||
$snapshots->expects('attachLog');
|
||
$ability = new DiviDesignRestoreAbility(
|
||
new DesignChange($snapshots, new FakeChangeLog(8)),
|
||
$snapshots,
|
||
new PresetRestorePlanner($writer)
|
||
);
|
||
|
||
$dry = self::assertToolError($ability->execute(['snapshot_id' => 'presets-20261016T100000Z-aaaaaa']), 'confirm_required');
|
||
self::assertSame('removed', $dry['diff'][0]['action']);
|
||
|
||
$result = $ability->execute(['snapshot_id' => 'presets-20261016T100000Z-aaaaaa', 'confirm' => true, 'design_rev' => $dry['design_rev']]);
|
||
self::assertSame('presets-3', $result['snapshot_id']);
|
||
}
|
||
|
||
private static function snapshotOf(array $data): array
|
||
{
|
||
return ['id' => 'presets-20261016T100000Z-aaaaaa', 'data' => $data, 'created' => 'x', 'user_id' => 1,
|
||
'ability' => 'lit/divi-presets-set', 'log_id' => 2, 'size' => 1];
|
||
}
|
||
|
||
private static function restoring(array $current, array $snapshot, bool $unfiltered): DiviDesignRestoreAbility
|
||
{
|
||
Functions\when('current_user_can')->justReturn(true);
|
||
$writer = Mockery::mock(DesignSystemWriter::class);
|
||
$writer->allows('presets')->andReturn($current);
|
||
$writer->allows('canUseVisualBuilder')->andReturn(true);
|
||
$snapshots = Mockery::mock(SnapshotStore::class);
|
||
$snapshots->allows('get')->andReturn(self::snapshotOf($snapshot));
|
||
$snapshots->shouldNotReceive('save');
|
||
|
||
return new DiviDesignRestoreAbility(
|
||
new DesignChange($snapshots, FakeChangeLog::forbidden()),
|
||
$snapshots,
|
||
new PresetRestorePlanner($writer, static fn (): bool => $unfiltered)
|
||
);
|
||
}
|
||
|
||
/** Final review I-2: markup in the snapshot or in the current inventory is lost for editors – refused. */
|
||
public function testEditorIsRefusedWhenTheSnapshotOrTheInventoryCarriesMarkup(): void
|
||
{
|
||
$plain = PresetBookTest::stored();
|
||
$markup = PresetBookTest::storedWithMarkup();
|
||
$older = $plain;
|
||
unset($older['module']['divi/button']['items']['cccccccccc']);
|
||
$input = ['snapshot_id' => 'presets-20261016T100000Z-aaaaaa'];
|
||
|
||
$inSnapshot = self::assertToolError(self::restoring($plain, $markup, false)->execute($input), 'forbidden');
|
||
self::assertStringContainsString('unfiltered_html', $inSnapshot['message']);
|
||
self::assertToolError(self::restoring($markup, $older, false)->execute($input), 'forbidden');
|
||
|
||
self::assertToolError(self::restoring($plain, $markup, true)->execute($input), 'confirm_required');
|
||
self::assertToolError(self::restoring($plain, $older, false)->execute($input), 'confirm_required');
|
||
}
|
||
|
||
/** T13: restoring needs the preset rights. */
|
||
public function testNeedsEditThemeOptions(): void
|
||
{
|
||
Functions\when('current_user_can')->justReturn(false);
|
||
$writer = Mockery::mock(DesignSystemWriter::class);
|
||
$writer->allows('canUseVisualBuilder')->andReturn(true);
|
||
$writer->shouldNotReceive('savePresets');
|
||
$snapshots = Mockery::mock(SnapshotStore::class);
|
||
$snapshots->shouldNotReceive('get');
|
||
$ability = new DiviDesignRestoreAbility(
|
||
new DesignChange($snapshots, FakeChangeLog::forbidden()),
|
||
$snapshots,
|
||
new PresetRestorePlanner($writer)
|
||
);
|
||
$input = ['snapshot_id' => 'presets-20261016T100000Z-aaaaaa', 'confirm' => true, 'design_rev' => 'x'];
|
||
|
||
self::assertToolError($ability->permission($input), 'forbidden');
|
||
self::assertToolError($ability->execute($input), 'forbidden');
|
||
}
|
||
|
||
public function testUnknownSnapshotAndOtherAreas(): void
|
||
{
|
||
Functions\when('current_user_can')->justReturn(true);
|
||
$writer = Mockery::mock(DesignSystemWriter::class);
|
||
$writer->allows('canUseVisualBuilder')->andReturn(true);
|
||
$snapshots = Mockery::mock(SnapshotStore::class);
|
||
$snapshots->allows('get')->andReturn(null);
|
||
$ability = new DiviDesignRestoreAbility(
|
||
new DesignChange($snapshots, FakeChangeLog::forbidden()),
|
||
$snapshots,
|
||
new PresetRestorePlanner($writer)
|
||
);
|
||
|
||
self::assertToolError($ability->execute(['snapshot_id' => 'presets-20261016T100000Z-abcdef']), 'not_found');
|
||
self::assertToolError($ability->execute(['snapshot_id' => 'colors-20261016T100000Z-abcdef']), 'unsupported');
|
||
self::assertToolError($ability->execute(['snapshot_id' => 'kaputt']), 'validation_failed');
|
||
}
|
||
}
|