feat: Divi composer – short/full form to blocks with structure rules, presets and labels
Labels, background_color and preset ids go through the choke point (S13); ambiguous preset names fail with their ids (S13a); fullwidth + rows is an error. Carry-ins: control characters stripped before the marker check (S32), kind override may only tighten, reference alt texts dropped, color check via VariableRef::typeOf (S33). 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,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Compose;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class StructureRulesTest extends TestCase
|
||||
{
|
||||
/** @return array<string, array{?Block, string, ?string}> Parent, child, part of the reason (null = allowed). */
|
||||
public static function placements(): array
|
||||
{
|
||||
$section = static fn (string $type): Block => Block::create(
|
||||
'divi/section',
|
||||
['module' => ['advanced' => ['type' => ['desktop' => ['value' => $type]]]]]
|
||||
);
|
||||
|
||||
return [
|
||||
'section on top' => [null, 'divi/section', null],
|
||||
'module on top' => [null, 'divi/text', 'oberster Ebene'],
|
||||
'unknown module' => [Block::create('divi/column'), 'divi/slider-pro', 'unbekanntes Modul'],
|
||||
'row in a section' => [Block::create('divi/section'), 'divi/row', null],
|
||||
'module in a section' => [Block::create('divi/section'), 'divi/text', 'Zeilen'],
|
||||
'fullwidth module in a fullwidth section' => [$section('fullwidth'), 'divi/fullwidth-header', null],
|
||||
'row in a fullwidth section' => [$section('fullwidth'), 'divi/row', 'fullwidth-Module'],
|
||||
'anything in a specialty section' => [$section('specialty'), 'divi/row', 'Spezialabschnitte'],
|
||||
'column in a row' => [Block::create('divi/row'), 'divi/column', 'Spalten entstehen mit der Zeile'],
|
||||
'module in a column' => [Block::create('divi/column'), 'divi/button', null],
|
||||
'group in a column' => [Block::create('divi/column'), 'divi/group', null],
|
||||
'module in a group' => [Block::create('divi/group'), 'divi/text', null],
|
||||
'fullwidth module in a column' => [Block::create('divi/column'), 'divi/fullwidth-header', 'passt nicht'],
|
||||
'child module in a column' => [Block::create('divi/column'), 'divi/accordion-item', 'passt nicht'],
|
||||
'section in a column' => [Block::create('divi/column'), 'divi/section', 'passt nicht'],
|
||||
'item in its parent' => [Block::create('divi/accordion'), 'divi/accordion-item', null],
|
||||
'other module in a parent' => [Block::create('divi/accordion'), 'divi/text', 'erlaubt nur divi/accordion-item'],
|
||||
'child in a plain module' => [Block::create('divi/text'), 'divi/button', 'keine Kind-Module'],
|
||||
'opaque parent' => [Block::parsed('divi/column', [], '<!-- wp:divi/column -->', false, true), 'divi/text', 'nur lesbar'],
|
||||
'foreign parent' => [Block::create('core/group'), 'divi/text', 'nur lesbar'],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider placements */
|
||||
public function testWhatGoesWhere(?Block $parent, string $child, ?string $reason): void
|
||||
{
|
||||
$violation = ComposeFixture::rules()->violation($parent, $child);
|
||||
|
||||
if ($reason === null) {
|
||||
self::assertNull($violation);
|
||||
} else {
|
||||
self::assertIsString($violation);
|
||||
self::assertStringContainsString($reason, $violation);
|
||||
}
|
||||
}
|
||||
|
||||
public function testPlainModules(): void
|
||||
{
|
||||
$rules = ComposeFixture::rules();
|
||||
|
||||
self::assertTrue($rules->isPlainModule('divi/button'));
|
||||
self::assertFalse($rules->isPlainModule('divi/fullwidth-header'));
|
||||
self::assertFalse($rules->isPlainModule('divi/accordion-item'));
|
||||
self::assertFalse($rules->isPlainModule('divi/row'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user