feat: lit/divi-move, lit/divi-delete, lit/divi-duplicate-node
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
@@ -21,6 +21,9 @@ final class DiviIntegrationTest extends TestCase
|
||||
'lit/divi-design-system',
|
||||
'lit/divi-insert',
|
||||
'lit/divi-update',
|
||||
'lit/divi-move',
|
||||
'lit/divi-delete',
|
||||
'lit/divi-duplicate-node',
|
||||
];
|
||||
|
||||
public function testProvidesTheDiviAbilitiesOnlyWithDivi5(): void
|
||||
|
||||
@@ -11,7 +11,10 @@ use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviComposition;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviDeleteAbility;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviDuplicateNodeAbility;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviInsertAbility;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviMoveAbility;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviPageLoader;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviUpdateAbility;
|
||||
@@ -83,6 +86,21 @@ final class DiviWriteAbilitiesTest extends TestCase
|
||||
return new DiviUpdateAbility($this->writer);
|
||||
}
|
||||
|
||||
private function move(): DiviMoveAbility
|
||||
{
|
||||
return new DiviMoveAbility($this->writer);
|
||||
}
|
||||
|
||||
private function delete(): DiviDeleteAbility
|
||||
{
|
||||
return new DiviDeleteAbility($this->writer);
|
||||
}
|
||||
|
||||
private function duplicate(): DiviDuplicateNodeAbility
|
||||
{
|
||||
return new DiviDuplicateNodeAbility($this->writer);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> The structured error the client sees (message JSON, spec §8.2). */
|
||||
private static function clientError(WP_Error $error): array
|
||||
{
|
||||
@@ -236,6 +254,40 @@ final class DiviWriteAbilitiesTest extends TestCase
|
||||
self::assertSame([], $this->saved);
|
||||
}
|
||||
|
||||
/** Ruling S14: move there and back restores the exact bytes; delete of the copy too. */
|
||||
public function testMoveDuplicateAndDelete(): void
|
||||
{
|
||||
$moved = $this->move()->execute([
|
||||
'post_id' => 7, 'tree_rev' => $this->treeRev(), 'id' => 's0.r0.c1.m2', 'parent' => 's1.r0.c0',
|
||||
]);
|
||||
self::assertSame([['id' => 's1.r0.c0.m1', 'type' => 'divi/button', 'action' => 'moved', 'label' => 'Hero – Button']], $moved['changed']);
|
||||
|
||||
$back = $this->move()->execute([
|
||||
'post_id' => 7, 'tree_rev' => Rev::of($this->saved[0]), 'id' => 's1.r0.c0.m1', 'parent' => 's0.r0.c1',
|
||||
]);
|
||||
self::assertSame([['id' => 's0.r0.c1.m2', 'type' => 'divi/button', 'action' => 'moved', 'label' => 'Hero – Button']], $back['changed']);
|
||||
self::assertSame($this->original, $this->saved[1], 'move there and back restores the exact bytes (S14)');
|
||||
|
||||
$duplicated = $this->duplicate()->execute([
|
||||
'post_id' => 7, 'tree_rev' => $this->treeRev(), 'id' => 's1',
|
||||
]);
|
||||
self::assertSame('s2', $duplicated['changed'][0]['id']);
|
||||
self::assertSame('Leistungen (Kopie)', $duplicated['changed'][0]['label']);
|
||||
|
||||
$delete = $this->delete();
|
||||
$ask = $delete->execute(['post_id' => 7, 'tree_rev' => Rev::of($this->saved[2]), 'ids' => ['s2', 's2.r0']]);
|
||||
self::assertSame('lit_confirm_required', $ask->get_error_code());
|
||||
self::assertSame(
|
||||
'1 Divi-Knoten würden samt Inhalt entfernt: s2 section "Leistungen (Kopie)" (1 Kind-Knoten).',
|
||||
json_decode($ask->get_error_message(), true)['message']
|
||||
);
|
||||
|
||||
$deleted = $delete->execute(['post_id' => 7, 'tree_rev' => Rev::of($this->saved[2]), 'ids' => ['s2'], 'confirm' => true]);
|
||||
self::assertSame([['id' => 's2', 'type' => 'divi/section', 'action' => 'deleted', 'label' => 'Leistungen (Kopie)']], $deleted['changed']);
|
||||
self::assertSame($this->saved[1], $this->saved[3], 'deleting the copy restores the exact bytes');
|
||||
self::assertTrue($delete->annotations()['destructive']);
|
||||
}
|
||||
|
||||
public function testReadOnlyNodesCannotBeUpdated(): void
|
||||
{
|
||||
$this->post->post_content = DiviPageLoaderTest::fixture('synthetic-mixed.html');
|
||||
|
||||
Reference in New Issue
Block a user