feat: ColorArea schreibt geänderte globale Farben gemischt und stellt Snapshots ersetzend wieder her
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
e269fcb1f8
commit
c1f77d2017
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Compose\VariableRef;
|
||||
use LIT\MCP\Integrations\Divi\Design\ColorArea;
|
||||
use LIT\MCP\Integrations\Divi\Design\ColorBook;
|
||||
use LIT\MCP\Integrations\Divi\Design\GlobalColorsAdapter;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
|
||||
final class ColorAreaTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* GlobalColorsAdapter::read(): the main color primary, the color Holz dunkel and the relative color Sand built
|
||||
* on it.
|
||||
*
|
||||
* @return array<string, array<string, mixed>>
|
||||
*/
|
||||
public static function stored(): array
|
||||
{
|
||||
return [
|
||||
'gcid-primary-color' => ['color' => '#2ea3f2', 'folder' => 'customizer', 'label' => 'Primärfarbe',
|
||||
'lastUpdated' => '2026-10-19T08:00:00.000Z', 'status' => 'active', 'usedInPosts' => []],
|
||||
'gcid-holz000001' => ['color' => '#5b3a29', 'folder' => '', 'label' => 'Holz dunkel',
|
||||
'lastUpdated' => '2026-10-01T10:00:00.000Z', 'status' => 'active', 'usedInPosts' => []],
|
||||
'gcid-sand000002' => ['color' => VariableRef::serialize('color', 'gcid-holz000001', ['lightness' => 40]),
|
||||
'folder' => '', 'label' => 'Sand', 'lastUpdated' => '2026-10-01T10:00:00.000Z', 'status' => 'active',
|
||||
'usedInPosts' => []],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* A GlobalColorsAdapter over $stored: save() merges (replace false) or replaces (true) like set_global_colors()
|
||||
* and notes each call in $saves.
|
||||
*
|
||||
* @param array<string, array<string, mixed>> $stored
|
||||
* @param list<array{0: array<string, mixed>, 1: bool}> $saves
|
||||
*/
|
||||
public static function adapter(array &$stored, array &$saves): GlobalColorsAdapter
|
||||
{
|
||||
$colors = Mockery::mock(GlobalColorsAdapter::class);
|
||||
$colors->allows('read')->andReturnUsing(static function () use (&$stored): array {
|
||||
return $stored;
|
||||
});
|
||||
$colors->allows('save')->andReturnUsing(
|
||||
static function (array $entries, bool $replace) use (&$stored, &$saves): void {
|
||||
$saves[] = [$entries, $replace];
|
||||
$stored = $replace ? $entries : array_merge($stored, $entries);
|
||||
}
|
||||
);
|
||||
|
||||
return $colors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string, mixed>> $stored
|
||||
* @param array<string, mixed> $fields
|
||||
* @return array<string, array<string, mixed>>
|
||||
*/
|
||||
private static function changed(array $stored, string $id, array $fields): array
|
||||
{
|
||||
$stored[$id] = $fields + $stored[$id];
|
||||
|
||||
return $stored;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private static function white(): array
|
||||
{
|
||||
return ['color' => '#ffffff', 'folder' => '', 'label' => 'Weiß', 'lastUpdated' => '2026-10-19T09:00:00.000Z',
|
||||
'status' => 'active', 'usedInPosts' => []];
|
||||
}
|
||||
|
||||
public function testAreaReadsThroughTheAdapter(): void
|
||||
{
|
||||
$stored = self::stored();
|
||||
$saves = [];
|
||||
$area = new ColorArea(self::adapter($stored, $saves));
|
||||
|
||||
self::assertSame(['colors', 'Farben'], [$area->name(), $area->label()]);
|
||||
self::assertSame(DiviFeature::ColorWrite, $area->feature());
|
||||
self::assertSame(ColorBook::fromDivi($stored)->data(), $area->raw());
|
||||
self::assertSame(ColorBook::fromDivi($stored)->rev(), $area->rev($stored));
|
||||
}
|
||||
|
||||
/** Ruling V4: only new and changed colors are merged; the unchanged main color is not written again. */
|
||||
public function testWriteSavesOnlyNewAndChangedColorsAndReadsBack(): void
|
||||
{
|
||||
$stored = self::stored();
|
||||
$saves = [];
|
||||
$area = new ColorArea(self::adapter($stored, $saves));
|
||||
$planned = self::changed(self::stored(), 'gcid-holz000001', ['color' => '#000000']);
|
||||
$planned['gcid-neu0000003'] = self::white();
|
||||
|
||||
$saved = $area->write($planned, false);
|
||||
|
||||
self::assertCount(1, $saves);
|
||||
self::assertFalse($saves[0][1], 'merge, never replace');
|
||||
$keys = array_keys($saves[0][0]);
|
||||
sort($keys);
|
||||
self::assertSame(['gcid-holz000001', 'gcid-neu0000003'], $keys);
|
||||
self::assertSame('#000000', $saved['gcid-holz000001']['color']);
|
||||
self::assertSame(ColorBook::fromDivi($stored)->data(), $saved);
|
||||
}
|
||||
|
||||
public function testWriteWithoutChangesSavesNothing(): void
|
||||
{
|
||||
$stored = self::stored();
|
||||
$saves = [];
|
||||
|
||||
(new ColorArea(self::adapter($stored, $saves)))->write(self::stored(), false);
|
||||
|
||||
self::assertSame([], $saves);
|
||||
}
|
||||
|
||||
/** Ruling V4: a restore (and a rollback) replaces all stored colors with the snapshot. */
|
||||
public function testRestoreReplacesAllColorsWithTheSnapshot(): void
|
||||
{
|
||||
$stored = self::changed(self::stored(), 'gcid-holz000001', ['color' => '#000000']);
|
||||
$stored['gcid-neu0000003'] = self::white();
|
||||
$saves = [];
|
||||
$area = new ColorArea(self::adapter($stored, $saves));
|
||||
$snapshot = ColorBook::fromDivi(self::stored())->data();
|
||||
|
||||
$saved = $area->restore($snapshot);
|
||||
|
||||
self::assertSame([[$snapshot, true]], $saves);
|
||||
self::assertSame($snapshot, $saved);
|
||||
}
|
||||
|
||||
public function testVerifyInsistsOnTheSameColorsWithTheSameStatus(): void
|
||||
{
|
||||
$stored = self::stored();
|
||||
$saves = [];
|
||||
$area = new ColorArea(self::adapter($stored, $saves));
|
||||
$expected = self::stored();
|
||||
$missing = $expected;
|
||||
unset($missing['gcid-sand000002']);
|
||||
|
||||
self::assertTrue($area->verify($expected, self::changed($expected, 'gcid-holz000001', ['color' => '#5B3A29'])));
|
||||
self::assertFalse($area->verify($expected, $missing));
|
||||
$inactive = self::changed($expected, 'gcid-holz000001', ['status' => 'inactive']);
|
||||
self::assertFalse($area->verify($expected, $inactive));
|
||||
}
|
||||
|
||||
public function testDifferencesNameTheColorsDiviChanged(): void
|
||||
{
|
||||
$stored = self::stored();
|
||||
$saves = [];
|
||||
$area = new ColorArea(self::adapter($stored, $saves));
|
||||
$expected = self::stored();
|
||||
|
||||
self::assertSame([], $area->differences($expected, $expected));
|
||||
self::assertSame(
|
||||
['Divi hat die Farbe „Holz dunkel“ beim Speichern bereinigt.'],
|
||||
$area->differences($expected, self::changed($expected, 'gcid-holz000001', ['color' => '#5B3A29']))
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user