feat: Fähigkeiten color-write/variable-write; GlobalColorsAdapter und GlobalVariablesAdapter (Manifest, Signatur-Referenzen) und DesignRights::colors()/variables()

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-19 13:55:09 +02:00
co-authored by Claude Sonnet 5.5
parent d73144ab36
commit 9b7c3c1d3b
12 changed files with 537 additions and 19 deletions
@@ -0,0 +1,112 @@
<?php
declare(strict_types=1);
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
use Brain\Monkey\Functions;
use LIT\MCP\Integrations\Divi\Design\GlobalVariablesAdapter;
use LIT\MCP\Integrations\Divi\Release\Call;
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
use LIT\MCP\Integrations\Divi\Release\Manifest;
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
use LIT\MCP\Tests\Support\ReleaseMatrices;
use LIT\MCP\Tests\Unit\TestCase;
use Mockery;
use RuntimeException;
use WP_Error;
/**
* Divi's GlobalData is replaced by a Mockery alias and et_pb_is_allowed() by Brain Monkey; those tests run in their
* own process (both define a symbol for the rest of the process).
*/
final class GlobalVariablesAdapterTest extends TestCase
{
private const GLOBAL_DATA = 'ET\\Builder\\Packages\\GlobalData\\GlobalData';
public function testIsARegisteredDesignAdapterForVariableWrite(): void
{
$manifest = GlobalVariablesAdapter::manifest();
self::assertContains(GlobalVariablesAdapter::class, DiviAdapters::CLASSES);
self::assertSame(Manifest::DESIGN, $manifest->area);
self::assertSame(
['GlobalData::get_global_variables()', 'GlobalData::set_global_variables()', 'et_pb_is_allowed()'],
array_map(static fn (Call $call): string => $call->label(), $manifest->calls)
);
self::assertSame([0, 2, 1], array_map(static fn (Call $call): ?int => $call->args, $manifest->calls));
self::assertSame([], $manifest->keys);
self::assertSame([DiviFeature::VariableWrite], $manifest->features);
}
public function testWritesNeedAReleasedDivi(): void
{
ReleaseGate::useResolver(
static fn (): ReleaseStatus => ReleaseMatrices::uniform(ReleaseState::Untested, '5.16.0')
);
$this->expectException(DiviLocked::class);
(new GlobalVariablesAdapter())->save([], []);
}
public function testWithoutDiviNobodyManagesVariables(): void
{
// Unit tests have no et_pb_is_allowed(): a missing Divi function never means "allowed".
self::assertFalse((new GlobalVariablesAdapter())->canManage());
}
/** @runInSeparateProcess */
public function testCanManageAsksTheVariablesManagerRight(): void
{
Functions\when('et_pb_is_allowed')->alias(static fn (string $cap): bool => $cap === 'variables_manager');
self::assertTrue((new GlobalVariablesAdapter())->canManage());
}
/** @runInSeparateProcess */
public function testReadReturnsTheStoredForm(): void
{
$actions = ['allowedActions' => ['editLabel' => true, 'editValue' => true, 'remove' => true]];
$space = ['label' => 'Abstand', 'value' => '24px', 'order' => '1', 'status' => 'active'];
$wave = ['label' => 'Welle', 'value' => 'linear-gradient(#fff,#000)', 'order' => '1', 'status' => 'active'];
Mockery::mock('alias:' . self::GLOBAL_DATA)->allows('get_global_variables')->andReturn([
'numbers' => (object) ['gvid-space00001' => $space + $actions],
'strings' => (object) [],
'colors' => (object) ['gcid-x' => ['label' => 'X'] + $actions],
'fonts' => (object) [
'--et_global_heading_font' => ['label' => 'Überschrift', 'value' => 'Open Sans'] + $actions,
'gvid-font000001' => (object) (['label' => 'Fließtext', 'value' => 'Inter'] + $actions),
],
'gradients' => (object) ['gvid-wave000001' => $wave + $actions],
]);
self::assertSame(
[
'numbers' => ['gvid-space00001' => $space],
'fonts' => ['gvid-font000001' => ['label' => 'Fließtext', 'value' => 'Inter']],
'gradients' => ['gvid-wave000001' => $wave],
],
(new GlobalVariablesAdapter())->read()
);
}
/** @runInSeparateProcess */
public function testSavePassesThePlannedInventoryAndThrowsOnARefusal(): void
{
$data = ['numbers' => ['gvid-space00001' => ['label' => 'Abstand', 'value' => '32px']]];
$expected = ['numbers' => ['gvid-space00001' => ['label' => 'Abstand', 'value' => '24px']]];
Mockery::mock('alias:' . self::GLOBAL_DATA)->expects('set_global_variables')->twice()->with($data, $expected)
->andReturn(null, new WP_Error('global_variables_stale', 'Global variables changed.'));
(new GlobalVariablesAdapter())->save($data, $expected);
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('global variables refused: global_variables_stale Global variables changed.');
(new GlobalVariablesAdapter())->save($data, $expected);
}
}