feat: Umschreib-Strategien für Preset-Zuweisung und -Entkopplung (TreeRewrite, AssignRewrite, DetachRewrite)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
763d765660
commit
d36e8286e8
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||
use LIT\MCP\Integrations\Divi\Design\AssignRewrite;
|
||||
use LIT\MCP\Integrations\Divi\Design\PresetAssignment;
|
||||
use LIT\MCP\Integrations\Divi\Design\PresetBook;
|
||||
use LogicException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class AssignRewriteTest extends TestCase
|
||||
{
|
||||
private const BUTTON = ['module' => 'divi/button', 'preset' => 'aaaaaaaaaa'];
|
||||
|
||||
/** PresetBookTest::stored() with settings in "CTA primär" (aaaaaaaaaa): background colour #111111. */
|
||||
private static function stored(): array
|
||||
{
|
||||
$stored = PresetBookTest::stored();
|
||||
$stored['module']['divi/button']['items']['aaaaaaaaaa']['attrs'] = [
|
||||
'button' => ['decoration' => ['background' => ['desktop' => ['value' => ['color' => '#111111']]]]],
|
||||
];
|
||||
|
||||
return $stored;
|
||||
}
|
||||
|
||||
private static function assignment(): PresetAssignment
|
||||
{
|
||||
return new PresetAssignment(
|
||||
static fn (): PresetBook => PresetBook::fromDivi(self::stored()),
|
||||
static fn (string $module): array => $module === 'divi/text'
|
||||
? ['content.decoration.bodyFont' => 'divi/font-body']
|
||||
: [],
|
||||
static fn (string $id): bool => preg_match('/^[a-z0-9]{10}$/D', $id) === 1
|
||||
);
|
||||
}
|
||||
|
||||
/** @return NodeIndex Blocks below s0.r0.c0 are m0, m1, … in the order of $inner. */
|
||||
private static function index(string $inner): NodeIndex
|
||||
{
|
||||
return NodeIndex::build((new Parser())->parse(
|
||||
'<!-- wp:divi/section --><!-- wp:divi/row --><!-- wp:divi/column -->' . $inner
|
||||
. '<!-- /wp:divi/column --><!-- /wp:divi/row --><!-- /wp:divi/section -->'
|
||||
));
|
||||
}
|
||||
|
||||
private static function node(NodeIndex $index, string $id): Block
|
||||
{
|
||||
$block = $index->find('s0.r0.c0.' . $id);
|
||||
self::assertNotNull($block);
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
public function testAssignsTheStackToBlocksOfTheModuleOnly(): void
|
||||
{
|
||||
$index = self::index('<!-- wp:divi/button /--><!-- wp:divi/text /-->');
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), ['preset' => ['aaaaaaaaaa', 'bbbbbbbbbb']]);
|
||||
|
||||
$button = $rewrite->rewrite(self::node($index, 'm0'));
|
||||
|
||||
self::assertSame(['aaaaaaaaaa', 'bbbbbbbbbb'], $button['modulePreset'] ?? null);
|
||||
self::assertNull($rewrite->rewrite(self::node($index, 'm1')), 'another module');
|
||||
}
|
||||
|
||||
public function testOnlyWithoutPresetSkipsBlocksWithAnExplicitPreset(): void
|
||||
{
|
||||
$index = self::index(
|
||||
'<!-- wp:divi/button {"modulePreset":["bbbbbbbbbb"]} /-->'
|
||||
. '<!-- wp:divi/button /-->'
|
||||
. '<!-- wp:divi/button {"modulePreset":["default"]} /-->'
|
||||
);
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), self::BUTTON, onlyWithoutPreset: true);
|
||||
|
||||
self::assertNull($rewrite->rewrite(self::node($index, 'm0')));
|
||||
self::assertSame(['aaaaaaaaaa'], $rewrite->rewrite(self::node($index, 'm1'))['modulePreset'] ?? null);
|
||||
self::assertSame(['aaaaaaaaaa'], $rewrite->rewrite(self::node($index, 'm2'))['modulePreset'] ?? null);
|
||||
}
|
||||
|
||||
public function testOnlyWithPresetIdReplacesThatPreset(): void
|
||||
{
|
||||
$index = self::index(
|
||||
'<!-- wp:divi/button {"modulePreset":["bbbbbbbbbb"]} /-->'
|
||||
. '<!-- wp:divi/button {"modulePreset":["cccccccccc"]} /-->'
|
||||
. '<!-- wp:divi/button /-->'
|
||||
);
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), self::BUTTON, onlyWithPresetId: 'bbbbbbbbbb');
|
||||
|
||||
self::assertSame(['aaaaaaaaaa'], $rewrite->rewrite(self::node($index, 'm0'))['modulePreset'] ?? null);
|
||||
self::assertNull($rewrite->rewrite(self::node($index, 'm1')), 'another preset');
|
||||
self::assertNull($rewrite->rewrite(self::node($index, 'm2')), 'no preset at all');
|
||||
}
|
||||
|
||||
public function testBothFiltersMustHold(): void
|
||||
{
|
||||
$index = self::index('<!-- wp:divi/button {"modulePreset":["bbbbbbbbbb"]} /-->');
|
||||
$rewrite = new AssignRewrite(
|
||||
'divi/button',
|
||||
self::assignment(),
|
||||
self::BUTTON,
|
||||
onlyWithoutPreset: true,
|
||||
onlyWithPresetId: 'bbbbbbbbbb'
|
||||
);
|
||||
|
||||
self::assertNull($rewrite->rewrite(self::node($index, 'm0')));
|
||||
}
|
||||
|
||||
public function testRunningAgainChangesNothing(): void
|
||||
{
|
||||
$index = self::index('<!-- wp:divi/button {"modulePreset":["aaaaaaaaaa"],"x":1} /-->');
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), self::BUTTON);
|
||||
|
||||
self::assertNull($rewrite->rewrite(self::node($index, 'm0')));
|
||||
}
|
||||
|
||||
public function testGroupPresetsAreAssignedThroughTheKeyOfTheGroup(): void
|
||||
{
|
||||
$index = self::index('<!-- wp:divi/text /-->');
|
||||
$rewrite = new AssignRewrite(
|
||||
'divi/text',
|
||||
self::assignment(),
|
||||
['group_presets' => ['font-body' => 'Lesetext']]
|
||||
);
|
||||
|
||||
$attrs = $rewrite->rewrite(self::node($index, 'm0'));
|
||||
|
||||
self::assertSame(
|
||||
['presetId' => ['gggggggggg'], 'groupName' => 'divi/font-body'],
|
||||
$attrs['groupPreset']['content.decoration.bodyFont'] ?? null
|
||||
);
|
||||
self::assertArrayNotHasKey('modulePreset', $attrs);
|
||||
}
|
||||
|
||||
public function testNotesDescribeWhatTheAssignedPresetCovers(): void
|
||||
{
|
||||
$index = self::index(
|
||||
'<!-- wp:divi/button {"button":{"decoration":{"background":{"desktop":{"value":{"color":"#ff0000"}}}}}} /-->'
|
||||
. '<!-- wp:divi/button {"button":{"decoration":{"background":{"desktop":{"value":{"color":"#111111"}}}}}} /-->'
|
||||
);
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), self::BUTTON);
|
||||
|
||||
$different = self::node($index, 'm0');
|
||||
$different->setAttrs($rewrite->rewrite($different) ?? []);
|
||||
$notes = $rewrite->notes($different, 's0.r0.c0.m0');
|
||||
|
||||
self::assertCount(1, $notes);
|
||||
self::assertStringContainsString('s0.r0.c0.m0: lokale Werte überdecken „CTA primär“', $notes[0]);
|
||||
self::assertStringContainsString('clear_overrides: true entfernt sie.', $notes[0]);
|
||||
|
||||
$same = self::node($index, 'm1');
|
||||
$same->setAttrs($rewrite->rewrite($same) ?? []);
|
||||
self::assertSame([], $rewrite->notes($same, 's0.r0.c0.m1'), 'the same value covers nothing');
|
||||
}
|
||||
|
||||
public function testClearOverridesRemovesTheCoveredValuesAndHasNoNotes(): void
|
||||
{
|
||||
$index = self::index(
|
||||
'<!-- wp:divi/button {"button":{"decoration":{"background":{"desktop":{"value":{"color":"#ff0000"}}}}}} /-->'
|
||||
);
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), self::BUTTON, clearOverrides: true);
|
||||
$block = self::node($index, 'm0');
|
||||
|
||||
$attrs = $rewrite->rewrite($block);
|
||||
|
||||
self::assertSame(['aaaaaaaaaa'], $attrs['modulePreset'] ?? null);
|
||||
self::assertArrayNotHasKey('button', $attrs, 'the local value and its empty parents are gone');
|
||||
$block->setAttrs($attrs);
|
||||
self::assertSame([], $rewrite->notes($block, 's0.r0.c0.m0'));
|
||||
}
|
||||
|
||||
public function testClearOverridesAloneAlsoChangesABlockThatAlreadyHasThePreset(): void
|
||||
{
|
||||
$index = self::index(
|
||||
'<!-- wp:divi/button {"modulePreset":["aaaaaaaaaa"],"button":{"decoration":{"background":'
|
||||
. '{"desktop":{"value":{"color":"#ff0000"}}}}}} /-->'
|
||||
);
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), self::BUTTON, clearOverrides: true);
|
||||
|
||||
$attrs = $rewrite->rewrite(self::node($index, 'm0'));
|
||||
|
||||
self::assertSame(['modulePreset' => ['aaaaaaaaaa']], $attrs);
|
||||
}
|
||||
|
||||
public function testAnUnvalidatedSpecIsALogicError(): void
|
||||
{
|
||||
$index = self::index('<!-- wp:divi/button /-->');
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), ['preset' => 'Gibt es nicht']);
|
||||
|
||||
$this->expectException(LogicException::class);
|
||||
|
||||
$rewrite->rewrite(self::node($index, 'm0'));
|
||||
}
|
||||
|
||||
public function testGlobalInstancesOfTheModuleConcernTheRewrite(): void
|
||||
{
|
||||
$index = self::index(
|
||||
'<!-- wp:divi/global-layout {"globalModule":"1058","blockName":"divi/button"} /-->'
|
||||
. '<!-- wp:divi/global-layout {"globalModule":"1059","blockName":"divi/text"} /-->'
|
||||
);
|
||||
$rewrite = new AssignRewrite('divi/button', self::assignment(), self::BUTTON);
|
||||
|
||||
self::assertTrue($rewrite->concernsInstance(self::node($index, 'g0')));
|
||||
self::assertFalse($rewrite->concernsInstance(self::node($index, 'g1')));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user