test: split DiviWriteAbilitiesTest per tool (T5)
One test class per Divi write tool on a shared DiviWriteAbilityTestCase; the 30 tests move verbatim (per-test assertion counts identical). Adds the ledger T4 test for a TreeEditor::move() StructureRules refusal. 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:
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
||||
|
||||
use LIT\MCP\Abilities\Rev;
|
||||
|
||||
final class DiviInsertAbilityTest extends DiviWriteAbilityTestCase
|
||||
{
|
||||
public function testInsertComposesAndSavesWithTreeRevAndPostRev(): void
|
||||
{
|
||||
$result = $this->insert()->execute([
|
||||
'post_id' => 7,
|
||||
'tree_rev' => $this->treeRev(),
|
||||
'after' => 's0.r0.c1.m1',
|
||||
'nodes' => [['type' => 'text', 'content' => '<p>Neu</p>']],
|
||||
]);
|
||||
|
||||
self::assertTrue($result['ok'], (string) json_encode($result));
|
||||
self::assertCount(1, $this->saved);
|
||||
self::assertSame([['id' => 's0.r0.c1.m2', 'type' => 'divi/text', 'action' => 'inserted', 'label' => 'Hero – Text']], $result['changed']);
|
||||
self::assertSame(Rev::of($this->saved[0]), $result['tree_rev']);
|
||||
self::assertSame(Rev::ofPost($this->post), $result['rev']);
|
||||
self::assertSame(811, $result['revision_id']);
|
||||
self::assertSame(4711, $result['log_id']);
|
||||
self::assertStringStartsWith('s0 section "Hero"', (string) $result['outline']);
|
||||
self::assertSame('https://kunde.test/?page_id=7&et_fb=1', $result['edit_url']);
|
||||
|
||||
// Byte identity: only the new block was added, every other byte is unchanged.
|
||||
$inserted = '<!-- wp:divi/text {"builderVersion":"5.2.1","content":{"innerContent":{"desktop":{"value":'
|
||||
. '"\u003cp\u003eNeu\u003c/p\u003e"}}},"module":{"meta":{"adminLabel":{"desktop":{"value":"Hero – Text"}}}}} '
|
||||
. '--><!-- /wp:divi/text -->';
|
||||
self::assertSame(str_replace('<!-- /wp:divi/text --><!-- wp:divi/button', '<!-- /wp:divi/text -->' . $inserted . '<!-- wp:divi/button', $this->original), $this->saved[0]);
|
||||
}
|
||||
|
||||
public function testStaleTreeRevAndInvalidNodesWriteNothing(): void
|
||||
{
|
||||
$stale = $this->insert()->execute(['post_id' => 7, 'tree_rev' => '000000000000', 'nodes' => [['type' => 'section']]]);
|
||||
self::assertToolError($stale, 'rev_mismatch');
|
||||
self::assertSame('rev_mismatch', self::clientError($stale)['code'], 'the client sees the code without lit_');
|
||||
self::assertStringContainsString('lit-divi-outline', $stale->get_error_data()['hint']);
|
||||
self::assertSame($stale->get_error_code(), $this->insert()->permission(['post_id' => 7, 'tree_rev' => 'x'])->get_error_code());
|
||||
|
||||
$invalid = $this->insert()->execute([
|
||||
'post_id' => 7,
|
||||
'tree_rev' => $this->treeRev(),
|
||||
'parent' => 's0.r0.c0',
|
||||
'nodes' => [
|
||||
['type' => 'heading', 'attrs' => ['title.fnt' => ['desktop' => 'x']]],
|
||||
['type' => 'button', 'url' => 'javascript:alert(1)', 'text' => 'x', 'nope' => 1],
|
||||
],
|
||||
]);
|
||||
self::assertToolError($invalid, 'invalid_attr_path');
|
||||
$client = self::clientError($invalid);
|
||||
self::assertSame('invalid_attr_path', $client['code']);
|
||||
self::assertArrayHasKey('nodes[0].attrs.title.fnt', $client['fields']);
|
||||
self::assertGreaterThanOrEqual(2, count($client['fields']), 'every error of the call in one response (S39)');
|
||||
self::assertStringContainsString('lit-divi-catalog', $client['hint']);
|
||||
|
||||
$wrongPlace = $this->insert()->execute(['post_id' => 7, 'tree_rev' => $this->treeRev(), 'nodes' => [['type' => 'button']]]);
|
||||
self::assertToolError($wrongPlace, 'validation_failed');
|
||||
|
||||
$badPosition = $this->insert()->execute([
|
||||
'post_id' => 7,
|
||||
'tree_rev' => $this->treeRev(),
|
||||
'parent' => 's0.r0.c0',
|
||||
'after' => 's0.r0.c1.m1',
|
||||
'nodes' => [['type' => 'text']],
|
||||
]);
|
||||
self::assertToolError($badPosition, 'validation_failed');
|
||||
self::assertArrayHasKey('position', self::clientError($badPosition)['fields']);
|
||||
|
||||
$unknown = $this->insert()->execute([
|
||||
'post_id' => 7,
|
||||
'tree_rev' => $this->treeRev(),
|
||||
'parent' => 's9',
|
||||
'nodes' => [['type' => 'section']],
|
||||
]);
|
||||
self::assertToolError($unknown, 'validation_failed');
|
||||
self::assertSame([], $this->saved);
|
||||
self::assertSame($this->original, $this->post->post_content);
|
||||
}
|
||||
|
||||
/** Ruling S9: the first section of an empty page goes into a divi/placeholder. */
|
||||
public function testInsertIntoAnEmptyPageWrapsInAPlaceholder(): void
|
||||
{
|
||||
$this->post->post_content = '';
|
||||
|
||||
$result = $this->insert()->execute([
|
||||
'post_id' => 7,
|
||||
'tree_rev' => Rev::of(''),
|
||||
'nodes' => [['type' => 'section', 'label' => 'Start', 'modules' => [['type' => 'heading', 'text' => 'Hallo']]]],
|
||||
]);
|
||||
|
||||
self::assertTrue($result['ok'], (string) json_encode($result));
|
||||
self::assertCount(1, $this->saved);
|
||||
self::assertStringStartsWith('<!-- wp:divi/placeholder --><!-- wp:divi/section ', $this->saved[0]);
|
||||
self::assertStringEndsWith('<!-- /wp:divi/section --><!-- /wp:divi/placeholder -->', $this->saved[0]);
|
||||
self::assertSame('s0', $result['changed'][0]['id']);
|
||||
self::assertSame('Start', $result['changed'][0]['label']);
|
||||
}
|
||||
|
||||
/** Ruling S40: the S38 overlap rule for new nodes too. */
|
||||
public function testInsertRefusesShortFormAndAttrsOnTheSamePath(): void
|
||||
{
|
||||
$result = $this->insert()->execute([
|
||||
'post_id' => 7,
|
||||
'tree_rev' => $this->treeRev(),
|
||||
'parent' => 's0.r0.c1',
|
||||
'nodes' => [[
|
||||
'type' => 'button',
|
||||
'text' => 'Neu',
|
||||
'attrs' => ['button.innerContent' => ['desktop' => ['linkUrl' => '/neu']]],
|
||||
]],
|
||||
]);
|
||||
|
||||
self::assertToolError($result, 'validation_failed');
|
||||
self::assertArrayHasKey('nodes[0].attrs.button.innerContent', self::clientError($result)['fields']);
|
||||
self::assertSame([], $this->saved);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user