feat: Fähigkeiten theme-option-read/-write und font-upload; ThemeOptionsAdapter und FontCatalog (Manifest, Nachbau customizer-typography, Signatur-Referenzen) und DesignRights::themeOptions()/fonts()

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-19 17:44:57 +02:00
co-authored by Claude Sonnet 5.5
parent 8379c55c89
commit a90cd7f5bd
14 changed files with 4765 additions and 26 deletions
@@ -0,0 +1,98 @@
<?php
declare(strict_types=1);
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
use Brain\Monkey\Functions;
use LIT\MCP\Integrations\Divi\Design\FontCatalog;
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\Manifest;
use LIT\MCP\Tests\Unit\TestCase;
/**
* Divi's font lists and et_pb_is_allowed() are faked with Brain Monkey; those tests run in their own process (Brain
* Monkey defines a missing function for the rest of the process, and other tests rely on Divi's functions being
* absent).
*/
final class FontCatalogTest extends TestCase
{
public function testIsARegisteredDesignAdapterForTheFontLists(): void
{
$manifest = FontCatalog::manifest();
self::assertContains(FontCatalog::class, DiviAdapters::CLASSES);
self::assertSame(Manifest::DESIGN, $manifest->area);
self::assertSame(
[
'et_builder_get_fonts()', 'et_builder_get_custom_fonts()', 'et_builder_get_google_fonts()',
'et_builder_get_websafe_fonts()', 'et_pb_is_allowed()',
],
array_map(static fn (Call $call): string => $call->label(), $manifest->calls)
);
self::assertSame([0, 0, 0, 0, 1], array_map(static fn (Call $call): ?int => $call->args, $manifest->calls));
self::assertSame(['et_uploaded_fonts', 'et_google_fonts_cache', 'et_google_api_settings'], $manifest->keys);
// Plan 4d W1: a broken font list locks every tool that checks font names against it.
self::assertSame(
[DiviFeature::ThemeOptionWrite, DiviFeature::FontUpload, DiviFeature::VariableWrite],
$manifest->features
);
self::assertSame([DiviFeature::FontUpload], $manifest->featuresOf($manifest->calls[4]));
}
/** @runInSeparateProcess */
public function testNamesAreTheExactFamiliesOfDivisSanitizerLoadedOnce(): void
{
Functions\expect('et_builder_get_custom_fonts')->once()->andReturn(['Hausschrift' => [], '1942' => []]);
Functions\expect('et_builder_get_fonts')->once()
->andReturn(['Arial' => [], 'Open Sans' => [], 'Roboto' => []]);
$catalog = new FontCatalog();
self::assertSame(['Hausschrift', '1942', 'Arial', 'Open Sans', 'Roboto'], $catalog->names());
self::assertTrue($catalog->has('Roboto'));
self::assertTrue($catalog->has('1942'), 'a numeric family name stays a string');
self::assertFalse($catalog->has('roboto'), 'exact, like Divi');
self::assertFalse($catalog->has('none'), 'Divi stores the default font as false, never as a name');
self::assertSame($catalog->names(), $catalog->names());
}
/** @runInSeparateProcess */
public function testUploadedAndReservedAreReadFreshEachTime(): void
{
Functions\expect('et_builder_get_custom_fonts')->twice()
->andReturn(['Hausschrift' => []], ['Hausschrift' => [], 'Neu' => []]);
Functions\when('et_builder_get_google_fonts')->justReturn(['Roboto' => []]);
Functions\when('et_builder_get_websafe_fonts')->justReturn(['Arial' => [], 'Roboto' => []]);
$catalog = new FontCatalog();
self::assertSame(['Hausschrift'], $catalog->uploaded());
self::assertSame(['Roboto', 'Arial', 'Hausschrift', 'Neu'], $catalog->reserved(), 'after an upload');
}
/** @runInSeparateProcess */
public function testABrokenListCountsAsEmpty(): void
{
// A filter of et_builder_google_fonts that returns no array (Divi passes it on unchecked).
Functions\when('et_builder_get_google_fonts')->justReturn(null);
Functions\when('et_builder_get_websafe_fonts')->justReturn(['Arial' => []]);
Functions\when('et_builder_get_custom_fonts')->justReturn([]);
self::assertSame(['Arial'], (new FontCatalog())->reserved());
}
public function testWithoutDiviNobodyManagesFonts(): void
{
// Unit tests have no et_pb_is_allowed(): a missing Divi function never means "allowed".
self::assertFalse((new FontCatalog())->canManage());
}
/** @runInSeparateProcess */
public function testCanManageAsksTheCustomFontsRight(): void
{
Functions\when('et_pb_is_allowed')->alias(static fn (string $cap): bool => $cap === 'custom_fonts_management');
self::assertTrue((new FontCatalog())->canManage());
}
}