- DiviFixtures: markup(), givenPost(), schema(), designSystem(), catalog(), dynamicContentRegistry(), maliciousRefs() - moved verbatim out of DiviPageLoaderTest, DesignSystemTest, ModuleCatalogTest, DynamicContentMapTest and VariableRefTest (its malicious() provider now returns maliciousRefs()). - ComposeFixture moves to tests/Support. - DiviWriterFixture: modules(), designReader(), composition(), a recording saver(), log() and writer(&$saved, &$failures, unfiltered, loader) for the five tests that wired the Divi write stack by hand. No test cases or assertions changed (1397 / 5834). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
113 lines
4.3 KiB
PHP
113 lines
4.3 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
||
|
||
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
|
||
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
||
use LIT\MCP\Integrations\Divi\BlockTree\Document;
|
||
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
|
||
use LIT\MCP\Integrations\Divi\Compose\TreeEditor;
|
||
use LIT\MCP\Integrations\Divi\Compose\VariableRef;
|
||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||
use LIT\MCP\Integrations\Divi\Pages\DiviComposition;
|
||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||
use LIT\MCP\Tests\Support\ComposeFixture;
|
||
use LIT\MCP\Tests\Support\DiviFixtures;
|
||
use LIT\MCP\Tests\Unit\TestCase;
|
||
use Mockery;
|
||
|
||
final class DiviCompositionTest extends TestCase
|
||
{
|
||
/** @var list<int> */
|
||
private array $registryCalls = [];
|
||
|
||
private function composition(): DiviComposition
|
||
{
|
||
$modules = Mockery::mock(DiviModules::class);
|
||
$modules->allows('catalog')->andReturn(DiviFixtures::catalog());
|
||
$modules->allows('builderVersion')->andReturn('5.2.1');
|
||
$design = Mockery::mock(DesignSystemReader::class);
|
||
$design->allows('read')->andReturn(DiviFixtures::designSystem());
|
||
$registry = new DynamicContentMap(function (int $postId): array {
|
||
$this->registryCalls[] = $postId;
|
||
|
||
return DiviFixtures::dynamicContentRegistry();
|
||
});
|
||
|
||
return new DiviComposition($modules, $design, ComposeFixture::sanitizer(), ComposeFixture::media(), $registry);
|
||
}
|
||
|
||
private static function siteTitle(): string
|
||
{
|
||
return VariableRef::serialize('content', 'site_title', ['before' => '', 'after' => '']);
|
||
}
|
||
|
||
public function testOneLiveMapIsSharedByTheFullAndTheShortForm(): void
|
||
{
|
||
$composition = $this->composition()->forPost(7);
|
||
|
||
// Full form (AttrWriter).
|
||
$full = $composition->attrWriter()->apply(
|
||
'divi/text',
|
||
[],
|
||
['content.innerContent' => ['desktop' => self::siteTitle()]],
|
||
'attrs'
|
||
);
|
||
self::assertSame([], $full['errors']);
|
||
self::assertSame(self::siteTitle(), AttrMap::desktop($full['attrs'], 'content.innerContent'));
|
||
|
||
// Short form through the Composer (ShortformWriter) – same map, same AttrWriter.
|
||
$short = $composition->composer()->compose(
|
||
[['type' => 'button', 'text' => self::siteTitle()]],
|
||
Block::create('divi/column'),
|
||
'nodes'
|
||
);
|
||
self::assertSame([], $short['errors']);
|
||
self::assertStringContainsString('site_title', json_encode($short['blocks'][0]->attrs(), JSON_THROW_ON_ERROR));
|
||
|
||
self::assertSame([7], $this->registryCalls, 'the registry is read once per post');
|
||
self::assertSame($composition->attrWriter(), $composition->attrWriter());
|
||
self::assertSame($composition->placeholders(), $composition->placeholders());
|
||
}
|
||
|
||
public function testWithoutAPostTheDefaultMapApplies(): void
|
||
{
|
||
$composition = $this->composition();
|
||
|
||
$result = $composition->attrWriter()->apply(
|
||
'divi/text',
|
||
[],
|
||
['content.innerContent' => ['desktop' => self::siteTitle()]],
|
||
'attrs'
|
||
);
|
||
|
||
self::assertStringContainsString('Unbekannter Name "site_title"', $result['errors']['attrs.content.innerContent']);
|
||
self::assertSame([], $this->registryCalls);
|
||
}
|
||
|
||
public function testForPostIsAFreshCompositionPerPost(): void
|
||
{
|
||
$base = $this->composition();
|
||
$seven = $base->forPost(7);
|
||
$eight = $base->forPost(8);
|
||
|
||
self::assertNotSame($base, $seven);
|
||
self::assertNotSame($seven->placeholders(), $eight->placeholders());
|
||
self::assertNotSame($base->placeholders(), $seven->placeholders());
|
||
self::assertSame([7, 8], $this->registryCalls);
|
||
}
|
||
|
||
public function testRulesEditorAndWarnings(): void
|
||
{
|
||
$composition = $this->composition();
|
||
|
||
self::assertNull($composition->rules()->violation(Block::create('divi/column'), 'divi/button'));
|
||
self::assertNotNull($composition->rules()->violation(null, 'divi/button'));
|
||
self::assertSame([], $composition->warnings()->collect(NodeIndex::build(new Document()), []));
|
||
self::assertInstanceOf(TreeEditor::class, $composition->editor());
|
||
}
|
||
}
|