feat: Fundstellen aller Module eines Typs, Standard-Gruppen-Presets in der Fundstellensuche (ModuleUsageQuery)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
1f9b50f1a6
commit
763d765660
@@ -98,6 +98,7 @@ final class DiviPresetsDeleteAbilityTest extends TestCase
|
||||
|
||||
self::assertSame(3, $error['usages'][0]['post_id']);
|
||||
self::assertStringContainsString('lit/divi-design-detach', $error['hint']);
|
||||
self::assertStringNotContainsString('4b', $error['hint'], 'the tool exists now');
|
||||
}
|
||||
|
||||
public function testNestedUseInAnotherPresetCounts(): void
|
||||
|
||||
@@ -138,6 +138,16 @@ final class DiviPresetsSetAbilityTest extends TestCase
|
||||
self::assertSame(['changed', 'default_set'], array_column($dry['diff'], 'action'));
|
||||
}
|
||||
|
||||
/** R11: a default group preset no longer warns that pages are "not listed" – the dry run lists them. */
|
||||
public function testDefaultGroupPresetHasNoNotListedWarning(): void
|
||||
{
|
||||
$dry = self::assertToolError($this->ability()->execute(['items' => [[
|
||||
'group' => 'font-body', 'preset' => 'Lesetext', 'rename' => 'Lesetext neu', 'make_default' => true,
|
||||
]]]), 'confirm_required');
|
||||
|
||||
self::assertSame([], $dry['warnings']);
|
||||
}
|
||||
|
||||
public function testUnknownPresetAndBadItemsAreCollected(): void
|
||||
{
|
||||
$result = self::assertToolError($this->ability()->execute(['items' => [
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use LIT\MCP\Integrations\Divi\Design\ModuleUsageQuery;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
|
||||
final class ModuleUsageQueryTest extends TestCase
|
||||
{
|
||||
private static function page(string $inner): string
|
||||
{
|
||||
return '<!-- wp:divi/section --><!-- wp:divi/row --><!-- wp:divi/column -->' . $inner
|
||||
. '<!-- /wp:divi/column --><!-- /wp:divi/row --><!-- /wp:divi/section -->';
|
||||
}
|
||||
|
||||
public function testCandidatesContainTheNameAnEscapedSlashOrAnEscapedLetter(): void
|
||||
{
|
||||
$db = Mockery::mock(\wpdb::class);
|
||||
$db->allows('esc_like')->andReturnUsing(static fn (string $text): string => $text);
|
||||
$db->expects('prepare')
|
||||
->with(
|
||||
'(post_content LIKE %s OR post_content REGEXP %s OR post_content REGEXP %s)',
|
||||
'%divi/button%',
|
||||
'divi(\\\\/|\\\\u002[fF])button',
|
||||
'\\\\u00[4-7][0-9a-fA-F]'
|
||||
)
|
||||
->andReturn('(prepared)');
|
||||
|
||||
self::assertSame('(prepared)', (new ModuleUsageQuery('divi/button'))->candidateCondition($db));
|
||||
}
|
||||
|
||||
public function testNeedsAFullBlockName(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
new ModuleUsageQuery('button');
|
||||
}
|
||||
|
||||
public function testMatchesBlocksOfTheModule(): void
|
||||
{
|
||||
$query = new ModuleUsageQuery('divi/button');
|
||||
|
||||
self::assertTrue($query->matches(self::page('<!-- wp:divi/button {"a":1} /-->')));
|
||||
self::assertTrue($query->matches(self::page('<!-- wp:divi/button /-->')));
|
||||
self::assertTrue($query->matches(self::page(
|
||||
'<!-- wp:divi/button {"a":1} --><!-- wp:divi/text /--><!-- /wp:divi/button -->'
|
||||
)));
|
||||
self::assertFalse($query->matches(self::page('<!-- wp:divi/text {"a":1} /-->')));
|
||||
self::assertFalse($query->matches(self::page('<!-- wp:divi/button-group /-->')), 'another module name');
|
||||
self::assertFalse($query->matches('<p>Kein Divi-Inhalt</p>'));
|
||||
}
|
||||
|
||||
public function testGlobalInstancesOfTheModuleCountSoThatTheyAreReportedAsSkipped(): void
|
||||
{
|
||||
$query = new ModuleUsageQuery('divi/button');
|
||||
|
||||
self::assertTrue($query->matches(self::page(
|
||||
'<!-- wp:divi/global-layout {"globalModule":"1058","blockName":"divi/button"} /-->'
|
||||
)));
|
||||
self::assertTrue($query->matches(self::page(
|
||||
'<!-- wp:divi/global-layout {"globalModule":"1058","blockName":"divi\/button"} /-->'
|
||||
)), 'an escaped slash decodes to the same name');
|
||||
self::assertFalse($query->matches(self::page(
|
||||
'<!-- wp:divi/global-layout {"globalModule":"1058","blockName":"divi/text"} /-->'
|
||||
)));
|
||||
self::assertTrue($query->matches(self::page(
|
||||
'<!-- wp:divi/button {"globalModule":"1058"} /-->'
|
||||
)), 'Divi 4 conversion: the block itself carries globalModule');
|
||||
self::assertTrue($query->matches(self::page('<!-- wp:divi/button {"a":1,} /-->')), 'unreadable attributes');
|
||||
}
|
||||
|
||||
public function testBrokenMarkupCountsAsUse(): void
|
||||
{
|
||||
self::assertTrue((new ModuleUsageQuery('divi/button'))->matches(
|
||||
'<!-- wp:divi/section {"a": --><!-- /wp:divi/row -->'
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class PresetUsageMatcherTest extends TestCase
|
||||
{
|
||||
private const TEXT = '<!-- wp:divi/section --><!-- wp:divi/text %s /--><!-- /wp:divi/section -->';
|
||||
private const BUTTON = '<!-- wp:divi/section --><!-- wp:divi/row --><!-- wp:divi/column -->'
|
||||
. '<!-- wp:divi/button %s /--><!-- /wp:divi/column --><!-- /wp:divi/row --><!-- /wp:divi/section -->';
|
||||
|
||||
@@ -62,4 +63,58 @@ final class PresetUsageMatcherTest extends TestCase
|
||||
false
|
||||
));
|
||||
}
|
||||
|
||||
private static function groupsOf(string $module): array
|
||||
{
|
||||
return $module === 'divi/text' ? ['content.decoration.bodyFont' => 'divi/font-body'] : [];
|
||||
}
|
||||
|
||||
public function testDefaultGroupPresetReachesModulesWithTheGroup(): void
|
||||
{
|
||||
$matcher = new PresetUsageMatcher(groupsOf: self::groupsOf(...));
|
||||
$group = new PresetScope('group', 'divi/font-body');
|
||||
$own = '{"groupPreset":{"content.decoration.bodyFont":{"presetId":["%s"],"groupName":"divi/font-body"}}}';
|
||||
|
||||
self::assertTrue($matcher->uses(sprintf(self::TEXT, '{}'), $group, 'gggggggggg', true));
|
||||
self::assertTrue(
|
||||
$matcher->uses(sprintf(self::TEXT, sprintf($own, 'default')), $group, 'gggggggggg', true),
|
||||
'an entry with the default ID is no own preset'
|
||||
);
|
||||
self::assertFalse(
|
||||
$matcher->uses(sprintf(self::TEXT, sprintf($own, 'hhhhhhhhhh')), $group, 'gggggggggg', true),
|
||||
'an own group preset replaces the default'
|
||||
);
|
||||
self::assertFalse(
|
||||
$matcher->uses(self::page('{}'), $group, 'gggggggggg', true),
|
||||
'a button has no font-body group'
|
||||
);
|
||||
self::assertFalse(
|
||||
$matcher->uses(sprintf(self::TEXT, '{}'), new PresetScope('group', 'divi/spacing'), 'gggggggggg', true),
|
||||
'the text module has no spacing group in this fixture'
|
||||
);
|
||||
self::assertFalse(
|
||||
$matcher->uses(sprintf(self::TEXT, '{}'), $group, 'gggggggggg', false),
|
||||
'a preset that is not the default needs an explicit entry'
|
||||
);
|
||||
}
|
||||
|
||||
public function testDefaultGroupPresetIsNotDetectedWithoutGroupsOf(): void
|
||||
{
|
||||
self::assertFalse((new PresetUsageMatcher())->uses(
|
||||
sprintf(self::TEXT, '{}'),
|
||||
new PresetScope('group', 'divi/font-body'),
|
||||
'gggggggggg',
|
||||
true
|
||||
));
|
||||
}
|
||||
|
||||
public function testGlobalInstancesDoNotReachADefaultGroupPreset(): void
|
||||
{
|
||||
$matcher = new PresetUsageMatcher(groupsOf: static fn (string $module): array => [
|
||||
'content.decoration.bodyFont' => 'divi/font-body',
|
||||
]);
|
||||
$instance = '<!-- wp:divi/global-layout {"globalModule":"1058","blockName":"divi/text"} /-->';
|
||||
|
||||
self::assertFalse($matcher->uses($instance, new PresetScope('group', 'divi/font-body'), 'gggggggggg', true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,4 +62,37 @@ final class PresetUsageQueryTest extends TestCase
|
||||
|
||||
new PresetUsageQuery([]);
|
||||
}
|
||||
|
||||
public function testADefaultGroupPresetLooksForEveryDiviBlock(): void
|
||||
{
|
||||
$db = Mockery::mock(\wpdb::class);
|
||||
$db->allows('esc_like')->andReturnUsing(static fn (string $text): string => $text);
|
||||
$db->expects('prepare')
|
||||
->with(
|
||||
'(post_content LIKE %s OR post_content LIKE %s OR post_content REGEXP %s)',
|
||||
'%gggggggggg%',
|
||||
'%wp:divi/%',
|
||||
'\\\\u00[4-7][0-9a-fA-F]'
|
||||
)
|
||||
->andReturn('(prepared)');
|
||||
|
||||
$query = new PresetUsageQuery([
|
||||
['scope' => new PresetScope('group', 'divi/font-body'), 'id' => 'gggggggggg', 'default' => true],
|
||||
]);
|
||||
|
||||
self::assertSame('(prepared)', $query->candidateCondition($db));
|
||||
}
|
||||
|
||||
public function testWithGroupsDetectsTheImplicitUseOfADefaultGroupPreset(): void
|
||||
{
|
||||
$query = PresetUsageQuery::withGroups(
|
||||
[['scope' => new PresetScope('group', 'divi/font-body'), 'id' => 'gggggggggg', 'default' => true]],
|
||||
static fn (string $module): array => $module === 'divi/text'
|
||||
? ['content.decoration.bodyFont' => 'divi/font-body']
|
||||
: []
|
||||
);
|
||||
|
||||
self::assertTrue($query->matches('<!-- wp:divi/text {} /-->'));
|
||||
self::assertFalse($query->matches('<!-- wp:divi/button {} /-->'));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user