Files
WP-LIT-MCP/tests/Unit/Integrations/Divi/Pages/DiviInsertAbilityTest.php
T
janniclas.loosenandClaude Opus 5.5 dcae2d4b91 fix: name the WordPress revision screen for library and layout revisions (audit L3)
lit/revision-restore takes only content types, so a write to a library entry
or a Theme Builder layout now answers with restore_url (wp-admin
revision.php for its revision_id), also per page in lit/divi-replace-text.
The guides and readme no longer present lit/revision-restore as the way back
for these types.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-27 23:05:05 +02:00

124 lines
5.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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::assertArrayNotHasKey('restore_url', $result, 'pages: lit/revision-restore');
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);
}
}