feat: ColorValue prüft Farbwerte (Hex, rgb/hsl, Schlüsselwort) und die relativen Einstellungen von Farbverweisen

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-19 13:56:34 +02:00
co-authored by Claude Sonnet 5.5
parent 9b7c3c1d3b
commit fb46078d42
2 changed files with 202 additions and 0 deletions
@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
use LIT\MCP\Integrations\Divi\Design\ColorValue;
use PHPUnit\Framework\TestCase;
final class ColorValueTest extends TestCase
{
/** @return array<string, array{string}> */
public static function validColors(): array
{
return [
'hex3' => ['#abc'], 'hex4' => ['#abcd'], 'hex6' => ['#5B3A29'], 'hex8' => ['#5b3a29cc'],
'rgb' => ['rgb(10, 20, 30)'], 'rgba' => ['rgba(10,20,30,0.5)'], 'rgb modern' => ['rgb(10 20 30 / 50%)'],
'hsl' => ['hsl(210, 50%, 40%)'], 'hsla' => ['hsla(210deg, 50%, 40%, .5)'],
'keyword' => ['red'], 'keyword upper' => ['Transparent'], 'keyword long' => ['lightgoldenrodyellow'],
];
}
/** @dataProvider validColors */
public function testValidColors(string $color): void
{
self::assertNull(ColorValue::check($color));
}
/** @return array<string, array{string}> */
public static function invalidColors(): array
{
return [
'empty' => [''], 'hex5' => ['#abcde'], 'hex7' => ['#abcdef1'], 'hex without hash' => ['abcdef12'],
'hex digits' => ['#ggg'], 'surrounding space' => [' #fff'], 'function without number' => ['rgb()'],
'function with var' => ['rgb(var(--x))'], 'function with semicolon' => ['rgb(1;2;3)'],
'unknown function' => ['url(1)'], 'keyword too short' => ['re'], 'keyword with digit' => ['red1'],
'keyword too long' => ['abcdefghijklmnopqrstu'], 'css injection' => ['red;}body{x:y'],
'too long' => ['rgb(' . str_repeat('1,', 60) . '1)'],
'reference' => ['$variable({"type":"color","value":{"name":"gcid-a","settings":{}}})$'],
'placeholder' => ['{{color:primary}}'],
];
}
/** @dataProvider invalidColors */
public function testInvalidColorsGetAGermanMessage(string $color): void
{
$message = ColorValue::check($color);
self::assertIsString($message);
self::assertNotSame('', $message);
}
public function testMessageNamesTheAllowedForms(): void
{
self::assertStringContainsString(ColorValue::TYPES_NOTE, (string) ColorValue::check('#abcde'));
self::assertStringContainsString('Farbschlüsselwort', ColorValue::TYPES_NOTE);
self::assertStringContainsString('Platzhalter', (string) ColorValue::check('{{color:primary}}'));
}
public function testRelativeKeepsTheOrderAndNormalizesWholeFloats(): void
{
self::assertSame(
['hue' => 10, 'lightness' => -12.5, 'opacity' => 100],
ColorValue::relative(['opacity' => 100.0, 'lightness' => -12.5, 'hue' => 10])
);
self::assertSame(['saturation' => 0], ColorValue::relative(['saturation' => 0]));
}
public function testRelativeBoundsAreInclusive(): void
{
self::assertSame(['hue' => -360], ColorValue::relative(['hue' => -360]));
self::assertSame(['hue' => 360], ColorValue::relative(['hue' => 360]));
self::assertSame(['opacity' => 100], ColorValue::relative(['opacity' => 100]));
self::assertSame(['opacity' => -100], ColorValue::relative(['opacity' => -100]));
}
public function testRelativeRejectsRangesTypesAndUnknownKeys(): void
{
self::assertSame('relative.hue: Zahl zwischen -360 und 360 erwartet.', ColorValue::relative(['hue' => 361]));
self::assertSame(
'relative.lightness: Zahl zwischen -100 und 100 erwartet.',
ColorValue::relative(['lightness' => -101])
);
self::assertSame(
'relative.saturation: Zahl zwischen -100 und 100 erwartet.',
ColorValue::relative(['saturation' => '10'])
);
self::assertSame(
'relative.opacity: Zahl zwischen -100 und 100 erwartet.',
ColorValue::relative(['opacity' => true])
);
self::assertSame(
'relative.hue: Zahl zwischen -360 und 360 erwartet.',
ColorValue::relative(['hue' => NAN])
);
self::assertSame(
'relative: unbekannte Einstellung "alpha"; erlaubt: hue, saturation, lightness, opacity.',
ColorValue::relative(['alpha' => 1])
);
self::assertSame(
'relative: mindestens eine Einstellung nötig (hue, saturation, lightness, opacity).',
ColorValue::relative([])
);
}
}