feat: design-system filters and global module ids in node-get/outline (S19)
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:
@@ -10,6 +10,7 @@ use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\NodeSummary;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Outline;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||
use LIT\MCP\Tests\Support\DiviFixtures;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use stdClass;
|
||||
|
||||
@@ -26,7 +27,7 @@ final class OutlineTest extends TestCase
|
||||
self::assertSame(
|
||||
['id' => 's0.r0.c1.m0', 'type' => 'heading', 'label' => '', 'excerpt' => 'Willkommen bei Müller & Söhne',
|
||||
'info' => '', 'presets' => ['Hero-Titel'], 'children' => 0, 'editable' => true, 'depth' => 3,
|
||||
'truncated' => false],
|
||||
'truncated' => false, 'global_id' => null],
|
||||
$rows[5]
|
||||
);
|
||||
self::assertSame('Spalten 8_24+16_24', $rows[1]['info']);
|
||||
@@ -40,6 +41,22 @@ final class OutlineTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testGlobalInstancesShowTheirLibraryIdAndRootType(): void
|
||||
{
|
||||
$content = DiviFixtures::markup('stage3/page--globale-instanzen.html');
|
||||
$outline = new Outline();
|
||||
$rows = $outline->rows(NodeIndex::build((new Parser())->parse($content)));
|
||||
|
||||
$byId = array_column($rows, null, 'id');
|
||||
self::assertSame('1058', $byId['g0']['global_id']);
|
||||
self::assertSame('section', $byId['g0']['type']);
|
||||
self::assertFalse($byId['g0']['editable']);
|
||||
self::assertSame('1059', $byId['s0.r0.c0.g0']['global_id']);
|
||||
self::assertSame('text', $byId['s0.r0.c0.g0']['type']);
|
||||
self::assertNull($byId['s0']['global_id']);
|
||||
self::assertStringContainsString('g0 section "Global Abschnitt" [global 1058]', $outline->text($rows));
|
||||
}
|
||||
|
||||
public function testSubtreeAndDepthLimit(): void
|
||||
{
|
||||
$index = NodeIndex::build((new Parser())->parse($this->fixture('synthetic-basic.html')));
|
||||
@@ -104,7 +121,7 @@ final class OutlineTest extends TestCase
|
||||
$text = (new Outline())->text((new Outline())->rows($index));
|
||||
|
||||
self::assertStringContainsString('x0 core/paragraph (nur lesbar)', $text);
|
||||
self::assertStringContainsString('s1.g1 row "Globale Zeile" (nur lesbar)', $text);
|
||||
self::assertStringContainsString('s1.g1 row "Globale Zeile" [global 913] (nur lesbar)', $text);
|
||||
self::assertStringContainsString('s0 section [specialty]', $text);
|
||||
self::assertStringContainsString('s0.c1.r0 row-inner [Spalten 1_2+1_2]', $text);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystem;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||
use LIT\MCP\Integrations\Divi\Design\DiviDesignSystemAbility;
|
||||
use LIT\MCP\Tests\Support\DiviFixtures;
|
||||
@@ -41,4 +42,38 @@ final class DiviDesignSystemAbilityTest extends TestCase
|
||||
|
||||
self::assertToolError($result, 'forbidden');
|
||||
}
|
||||
|
||||
public function testFiltersPartsAndPresetsOfOneModule(): void
|
||||
{
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
$reader = Mockery::mock(DesignSystemReader::class);
|
||||
$reader->allows('read')->andReturn(DiviFixtures::designSystem());
|
||||
$ability = new DiviDesignSystemAbility($reader);
|
||||
|
||||
$result = $ability->execute(['only' => ['presets'], 'module' => 'button']);
|
||||
|
||||
self::assertSame([], $result['colors']);
|
||||
self::assertSame([], $result['variables']);
|
||||
self::assertSame(['p-1', 'p-2'], array_column($result['presets'], 'id'));
|
||||
self::assertSame(['divi/button'], array_values(array_unique(array_column($result['presets'], 'module'))));
|
||||
self::assertNotEmpty($result['fonts']['heading']);
|
||||
self::assertContains('Nicht angefordert: colors, variables.', $result['notes']);
|
||||
}
|
||||
|
||||
public function testCapsThePresetList(): void
|
||||
{
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
$items = [];
|
||||
for ($i = 0; $i < 250; ++$i) {
|
||||
$items['p' . $i] = ['id' => 'p' . $i, 'name' => 'Preset ' . $i, 'moduleName' => 'divi/text'];
|
||||
}
|
||||
$design = DesignSystem::fromDivi([], [], ['module' => ['divi/text' => ['default' => '', 'items' => $items]]], []);
|
||||
$reader = Mockery::mock(DesignSystemReader::class);
|
||||
$reader->allows('read')->andReturn($design);
|
||||
|
||||
$result = (new DiviDesignSystemAbility($reader))->execute([]);
|
||||
|
||||
self::assertCount(DiviDesignSystemAbility::PRESET_LIMIT, $result['presets']);
|
||||
self::assertContains('200 von 250 Presets gezeigt; mit module auf ein Modul eingrenzen.', $result['notes']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,4 +123,19 @@ final class DiviReadAbilitiesTest extends TestCase
|
||||
self::assertToolError($ability->execute(['post_id' => 7, 'id' => 'hero']), 'validation_failed');
|
||||
self::assertToolError($ability->execute(['post_id' => 7, 'id' => 's5.r0']), 'not_found');
|
||||
}
|
||||
|
||||
public function testNodeGetNamesTheLibraryEntryOfAGlobalModule(): void
|
||||
{
|
||||
DiviFixtures::givenPost(DiviFixtures::markup('stage3/page--globale-instanzen.html'));
|
||||
$ability = new DiviNodeGetAbility(new DiviPageLoader(DiviFixtures::schema()), $this->design());
|
||||
|
||||
$global = $ability->execute(['post_id' => 7, 'id' => 'g0']);
|
||||
$plain = $ability->execute(['post_id' => 7, 'id' => 's0']);
|
||||
|
||||
self::assertSame('1058', $global['global']['id']);
|
||||
self::assertSame('divi/section', $global['global']['block_name']);
|
||||
self::assertStringContainsString('post_id 1058', $global['global']['hint']);
|
||||
self::assertFalse($global['editable']);
|
||||
self::assertNull($plain['global']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user