refactor(compat): Prüfbausteine nach src/Compatibility, Matrix und ManifestCheck generisch
Requirement, Call, ConstantRequirement, Mirror, Problem, FeatureStatus, CompatibilityMatrix, Manifest, ManifestCheck sowie Fingerprints und LineDiff liegen jetzt im divi-freien Kern. Neu: GlobalRequirement, CompatibilityMatrix::fromProblems(), ManifestCheck-Option signatures, DiviManifestCheck::create() und DiviAreas. Divi-Verhalten unverändert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9beb55e228
commit
b511ef6348
@@ -7,15 +7,15 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Admin;
|
||||
use Brain\Monkey\Actions;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Admin\AdminPostAction;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Admin\DiviTab;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
||||
use LIT\MCP\Compatibility\FeatureStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
||||
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
||||
|
||||
@@ -5,17 +5,17 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Cli;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Cli\DiviCheckCommand;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckReport;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckReportStore;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
||||
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviReference;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Tests\Support\MatrixFixtures;
|
||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||
|
||||
@@ -14,7 +14,7 @@ use LIT\MCP\Integrations\Divi\Library\UsageReport;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
|
||||
@@ -6,9 +6,9 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
|
||||
final class DesignSystemReaderTest extends TestCase
|
||||
@@ -18,7 +18,7 @@ final class DesignSystemReaderTest extends TestCase
|
||||
$manifest = DesignSystemReader::manifest();
|
||||
|
||||
self::assertContains(DesignSystemReader::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
||||
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||
self::assertSame(
|
||||
['GlobalData::get_global_colors()', 'GlobalData::get_global_variables()',
|
||||
'GlobalPreset::get_data()'],
|
||||
|
||||
@@ -4,13 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
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;
|
||||
@@ -22,7 +22,7 @@ final class DesignSystemWriterTest extends TestCase
|
||||
$manifest = DesignSystemWriter::manifest();
|
||||
|
||||
self::assertContains(DesignSystemWriter::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
||||
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||
self::assertSame(
|
||||
[
|
||||
'GlobalPreset::get_data()', 'GlobalPreset::prepare_data()', 'GlobalPreset::validate_preset_count()',
|
||||
|
||||
@@ -8,6 +8,7 @@ use Brain\Monkey\Functions;
|
||||
use Closure;
|
||||
use LIT\MCP\Abilities\Errors;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignChange;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||
@@ -24,7 +25,6 @@ use LIT\MCP\Integrations\Divi\Library\GlobalUsages;
|
||||
use LIT\MCP\Integrations\Divi\Library\UsageReport;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\LockTable;
|
||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||
|
||||
@@ -7,12 +7,12 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Errors;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Design\DiviFontsUploadAbility;
|
||||
use LIT\MCP\Integrations\Divi\Design\FontCatalog;
|
||||
use LIT\MCP\Integrations\Divi\Design\FontInstaller;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Media\RemoteFileFetcher;
|
||||
use LIT\MCP\Limits;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
|
||||
@@ -6,10 +6,10 @@ 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\Compatibility\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
|
||||
/**
|
||||
@@ -24,7 +24,7 @@ final class FontCatalogTest extends TestCase
|
||||
$manifest = FontCatalog::manifest();
|
||||
|
||||
self::assertContains(FontCatalog::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
||||
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||
self::assertSame(
|
||||
[
|
||||
'et_builder_get_fonts()', 'et_builder_get_custom_fonts()', 'et_builder_get_google_fonts()',
|
||||
|
||||
@@ -5,15 +5,15 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Design\FontInstaller;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\ConstantRequirement;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Compatibility\ConstantRequirement;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
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;
|
||||
@@ -65,7 +65,7 @@ final class FontInstallerTest extends TestCase
|
||||
$manifest = FontInstaller::manifest();
|
||||
|
||||
self::assertContains(FontInstaller::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
||||
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||
self::assertSame(
|
||||
['FontsUtility::mime_types_font()', 'HooksRegistration::check_filetype_and_ext_font()',
|
||||
'FontsUtility::font_add()', 'FontsUtility::font_remove()'],
|
||||
|
||||
@@ -5,14 +5,14 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Design\GlobalColorsAdapter;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
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;
|
||||
@@ -32,7 +32,7 @@ final class GlobalColorsAdapterTest extends TestCase
|
||||
$manifest = GlobalColorsAdapter::manifest();
|
||||
|
||||
self::assertContains(GlobalColorsAdapter::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
||||
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||
self::assertSame(
|
||||
['GlobalData::get_global_colors()', 'GlobalData::sanitize_global_colors_data()',
|
||||
'GlobalData::set_global_colors()'],
|
||||
|
||||
@@ -5,14 +5,14 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Design\GlobalVariablesAdapter;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
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;
|
||||
@@ -33,7 +33,7 @@ final class GlobalVariablesAdapterTest extends TestCase
|
||||
$manifest = GlobalVariablesAdapter::manifest();
|
||||
|
||||
self::assertContains(GlobalVariablesAdapter::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
||||
self::assertSame(DiviAreas::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)
|
||||
|
||||
@@ -21,7 +21,7 @@ use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
||||
use LIT\MCP\Integrations\Divi\Pages\SaveScope;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\LibraryFixtures;
|
||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||
|
||||
@@ -6,14 +6,14 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use InvalidArgumentException;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Design\ThemeOptionsAdapter;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
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;
|
||||
@@ -40,7 +40,7 @@ final class ThemeOptionsAdapterTest extends TestCase
|
||||
$manifest = ThemeOptionsAdapter::manifest();
|
||||
|
||||
self::assertContains(ThemeOptionsAdapter::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::DESIGN, $manifest->area);
|
||||
self::assertSame(DiviAreas::DESIGN, $manifest->area);
|
||||
self::assertSame(
|
||||
[
|
||||
'et_sanitize_font_choices()', 'et_sanitize_global_font_weight()', 'et_sanitize_float_number()',
|
||||
|
||||
@@ -5,10 +5,11 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\DiviCompatibility;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
use LIT\MCP\Compatibility\Manifest;
|
||||
use LIT\MCP\Compatibility\ManifestCheck;
|
||||
use LIT\MCP\Compatibility\Mirror;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RuntimeException;
|
||||
|
||||
@@ -31,7 +32,7 @@ final class DiviCompatibilityTest extends TestCase
|
||||
{
|
||||
$check = new ManifestCheck(
|
||||
['X' => new Manifest(
|
||||
Manifest::LIBRARY,
|
||||
DiviAreas::LIBRARY,
|
||||
calls: [new Call('strlen', 1)],
|
||||
postTypes: ['et_pb_layout'],
|
||||
mirrors: [new Mirror('m', 'a.php', 'a', null, 'Terme')]
|
||||
@@ -51,7 +52,7 @@ final class DiviCompatibilityTest extends TestCase
|
||||
{
|
||||
$labels = implode("\n", array_keys(DiviCompatibility::defaults()));
|
||||
|
||||
$areas = [Manifest::PAGES, Manifest::LIBRARY, Manifest::THEME_BUILDER, Manifest::DESIGN, Manifest::CATALOG];
|
||||
$areas = [DiviAreas::PAGES, DiviAreas::LIBRARY, DiviAreas::THEME_BUILDER, DiviAreas::DESIGN, DiviAreas::CATALOG];
|
||||
foreach ($areas as $area) {
|
||||
self::assertStringContainsString($area . ': ', $labels);
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Core\EnvironmentComponent;
|
||||
use LIT\MCP\Integrations\Divi\DiviCompatibility;
|
||||
use LIT\MCP\Integrations\Divi\DiviEnvironmentComponent;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
||||
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\FeatureFakeTool;
|
||||
use LIT\MCP\Tests\Support\MatrixFixtures;
|
||||
|
||||
@@ -9,7 +9,7 @@ use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||
use LIT\MCP\Integrations\Divi\Library\LibraryItemSpec;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
@@ -121,7 +121,7 @@ final class DiviLibraryStoreTest extends TestCase
|
||||
$manifest = DiviLibraryStore::manifest();
|
||||
|
||||
self::assertContains(DiviLibraryStore::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::LIBRARY, $manifest->area);
|
||||
self::assertSame(DiviAreas::LIBRARY, $manifest->area);
|
||||
self::assertSame(['et_pb_layout'], $manifest->postTypes);
|
||||
self::assertSame(
|
||||
['scope', 'layout_type', 'module_width', 'layout_category', 'layout_tag'],
|
||||
|
||||
@@ -4,13 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
||||
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||
use LIT\MCP\Integrations\Divi\Compose\VariableRef;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviContentComposer;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Tests\Support\DiviFeatureFixtures;
|
||||
use LIT\MCP\Tests\Support\DiviFixtures;
|
||||
use LIT\MCP\Tests\Support\DiviWriterFixture;
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviPages;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use RuntimeException;
|
||||
use WP_Post;
|
||||
@@ -63,7 +63,7 @@ final class DiviPagesTest extends TestCase
|
||||
$manifest = DiviPages::manifest();
|
||||
|
||||
self::assertContains(DiviPages::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::PAGES, $manifest->area);
|
||||
self::assertSame(DiviAreas::PAGES, $manifest->area);
|
||||
self::assertSame(['vb-sync-flags'], array_map(static fn ($mirror): string => $mirror->id, $manifest->mirrors));
|
||||
self::assertSame('SyncToServerController::update()', $manifest->mirrors[0]->label());
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\Divi\Release\CheckStep;
|
||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\FormatCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
||||
use LIT\MCP\Compatibility\ManifestCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
||||
use LIT\MCP\Plugin;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class CompatibilityMatrixTest extends TestCase
|
||||
{
|
||||
public function testAFeatureWithoutResultIsIncompatible(): void
|
||||
{
|
||||
$matrix = new CompatibilityMatrix([
|
||||
'page-read' => new FeatureStatus(DiviFeature::PageRead, ReleaseState::Released, [], 'code'),
|
||||
// Under the wrong key: does not count for page-write.
|
||||
'page-write' => new FeatureStatus(DiviFeature::PageRead, ReleaseState::Released, [], 'code'),
|
||||
]);
|
||||
|
||||
self::assertTrue($matrix->of(DiviFeature::PageRead)->usable());
|
||||
foreach ([DiviFeature::PageWrite, DiviFeature::ThemeBuilderWrite] as $feature) {
|
||||
$status = $matrix->of($feature);
|
||||
self::assertSame(ReleaseState::Incompatible, $status->state);
|
||||
self::assertSame([CompatibilityMatrix::MISSING], $status->problems);
|
||||
}
|
||||
self::assertCount(count(DiviFeature::cases()) - 1, $matrix->unusable());
|
||||
}
|
||||
|
||||
public function testAllReleasedAndAllIncompatible(): void
|
||||
{
|
||||
$released = CompatibilityMatrix::allReleased('database');
|
||||
$broken = CompatibilityMatrix::allIncompatible('kaputt');
|
||||
|
||||
foreach (DiviFeature::cases() as $feature) {
|
||||
self::assertTrue($released->of($feature)->usable());
|
||||
self::assertSame('database', $released->of($feature)->source);
|
||||
self::assertSame(ReleaseState::Incompatible, $broken->of($feature)->state);
|
||||
self::assertSame(['kaputt'], $broken->of($feature)->problems);
|
||||
self::assertNull($broken->of($feature)->source);
|
||||
}
|
||||
self::assertSame([], $released->unusable());
|
||||
self::assertSame('code', CompatibilityMatrix::allReleased()->source());
|
||||
}
|
||||
|
||||
public function testTheStateIsTheWorstFeatureAndEveryProblemIsListedOnce(): void
|
||||
{
|
||||
$matrix = self::matrix([
|
||||
'page-write' => [ReleaseState::Untested, ['a']],
|
||||
'tb-write' => [ReleaseState::Incompatible, ['b', 'a']],
|
||||
]);
|
||||
|
||||
self::assertSame(ReleaseState::Incompatible, $matrix->state());
|
||||
self::assertSame(['a', 'b'], $matrix->problems());
|
||||
self::assertNull($matrix->source());
|
||||
self::assertSame(ReleaseState::Untested, self::matrix(['catalog' => [ReleaseState::Untested, []]])->state());
|
||||
self::assertSame(ReleaseState::Released, self::matrix([])->state());
|
||||
}
|
||||
|
||||
public function testTheSourceOfAReleasedMatrixIsCommonOrNull(): void
|
||||
{
|
||||
self::assertSame('auto', self::matrix([])->source());
|
||||
|
||||
$mixed = new CompatibilityMatrix(array_merge(
|
||||
self::features([]),
|
||||
['roles' => new FeatureStatus(DiviFeature::Roles, ReleaseState::Released, [], 'code')]
|
||||
));
|
||||
self::assertSame(ReleaseState::Released, $mixed->state());
|
||||
self::assertNull($mixed->source());
|
||||
}
|
||||
|
||||
public function testUsableAndUnusable(): void
|
||||
{
|
||||
$matrix = self::matrix(['catalog' => [ReleaseState::Untested, []]]);
|
||||
|
||||
self::assertTrue($matrix->usable([DiviFeature::PageWrite, DiviFeature::PageRead]));
|
||||
self::assertFalse($matrix->usable([DiviFeature::PageWrite, DiviFeature::Catalog]));
|
||||
self::assertTrue($matrix->usable([]));
|
||||
self::assertSame(
|
||||
[DiviFeature::Catalog],
|
||||
array_map(static fn (FeatureStatus $status): DiviFeature => $status->feature, $matrix->unusable())
|
||||
);
|
||||
}
|
||||
|
||||
public function testLockedNamesEveryUnusableFeatureOnceInTheGivenOrder(): void
|
||||
{
|
||||
$matrix = ReleaseMatrices::matrix(
|
||||
[DiviFeature::LibraryWrite, DiviFeature::ThemeBuilderWrite, DiviFeature::Catalog],
|
||||
ReleaseState::Incompatible
|
||||
);
|
||||
|
||||
$locked = $matrix->locked([
|
||||
DiviFeature::PageWrite,
|
||||
DiviFeature::ThemeBuilderWrite,
|
||||
DiviFeature::LibraryWrite,
|
||||
DiviFeature::ThemeBuilderWrite,
|
||||
]);
|
||||
|
||||
self::assertSame(
|
||||
[DiviFeature::ThemeBuilderWrite, DiviFeature::LibraryWrite],
|
||||
array_map(static fn (FeatureStatus $status): DiviFeature => $status->feature, $locked)
|
||||
);
|
||||
self::assertSame(ReleaseState::Incompatible, $locked[0]->state);
|
||||
self::assertSame([], $matrix->locked([DiviFeature::PageWrite, DiviFeature::PageRead]));
|
||||
self::assertSame([], $matrix->locked([]));
|
||||
}
|
||||
|
||||
public function testToArrayListsEveryFeatureInCaseOrder(): void
|
||||
{
|
||||
$rows = self::matrix(['tb-write' => [ReleaseState::Incompatible, ['b']]])->toArray();
|
||||
|
||||
self::assertSame(
|
||||
array_map(static fn (DiviFeature $feature): string => $feature->value, DiviFeature::cases()),
|
||||
array_column($rows, 'id')
|
||||
);
|
||||
self::assertContains(
|
||||
['id' => 'tb-write', 'label' => DiviFeature::ThemeBuilderWrite->label(), 'state' => 'incompatible',
|
||||
'problems' => ['b'], 'source' => null],
|
||||
$rows
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array{ReleaseState, list<string>}> $locked
|
||||
* @return array<string, FeatureStatus>
|
||||
*/
|
||||
private static function features(array $locked): array
|
||||
{
|
||||
$features = [];
|
||||
foreach (DiviFeature::cases() as $feature) {
|
||||
[$state, $problems] = $locked[$feature->value] ?? [ReleaseState::Released, []];
|
||||
$features[$feature->value] = new FeatureStatus(
|
||||
$feature,
|
||||
$state,
|
||||
$problems,
|
||||
$state === ReleaseState::Released ? 'auto' : null
|
||||
);
|
||||
}
|
||||
|
||||
return $features;
|
||||
}
|
||||
|
||||
/** @param array<string, array{ReleaseState, list<string>}> $locked */
|
||||
private static function matrix(array $locked): CompatibilityMatrix
|
||||
{
|
||||
return new CompatibilityMatrix(self::features($locked));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class DiviAreasTest extends TestCase
|
||||
{
|
||||
public function testTheFiveAreasAreNamedAsInSpecSection3(): void
|
||||
{
|
||||
self::assertSame('Seiten', DiviAreas::PAGES);
|
||||
self::assertSame('Bibliothek', DiviAreas::LIBRARY);
|
||||
self::assertSame('Theme Builder', DiviAreas::THEME_BUILDER);
|
||||
self::assertSame('Designsystem', DiviAreas::DESIGN);
|
||||
self::assertSame('Katalog', DiviAreas::CATALOG);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ use LIT\MCP\Integrations\Divi\Pages\DiviPages;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
||||
use LIT\MCP\Compatibility\Mirror;
|
||||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -7,11 +7,11 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Ability;
|
||||
use LIT\MCP\Abilities\DeclaresRequirements;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\DiviIntegration;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeatureGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureSets;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
|
||||
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
||||
use LIT\MCP\Integrations\WordPress\Content\ContentCreateAbility;
|
||||
|
||||
@@ -5,9 +5,9 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Abilities\ToolRefusal;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use LogicException;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviManifestCheck;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
|
||||
final class DiviManifestCheckTest extends TestCase
|
||||
{
|
||||
public function testCreateChecksEveryDiviManifest(): void
|
||||
{
|
||||
$code = [];
|
||||
$mirrors = [];
|
||||
foreach (DiviAdapters::manifests() as $manifest) {
|
||||
foreach ([...$manifest->calls, ...$manifest->constants] as $requirement) {
|
||||
$code[] = $manifest->area . ': ' . $requirement->label();
|
||||
}
|
||||
$mirrors = [...$mirrors, ...array_map(static fn ($mirror): string => $mirror->id, $manifest->mirrors)];
|
||||
}
|
||||
$check = DiviManifestCheck::create();
|
||||
|
||||
self::assertNotSame([], $code);
|
||||
self::assertSame(array_values(array_unique($code)), array_keys($check->codeChecks()));
|
||||
self::assertCount(count(array_unique($mirrors)), $check->mirrorChecks());
|
||||
self::assertNotSame([], $check->registrationChecks(), 'DiviModules::knowsBlock is wired for block types');
|
||||
}
|
||||
|
||||
public function testCreateLoadsTheSignatureReferences(): void
|
||||
{
|
||||
$kinds = array_map(static fn ($problem): string => $problem->kind, DiviManifestCheck::create()->codeProblems());
|
||||
|
||||
self::assertNotContains('reference-missing', $kinds);
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Compatibility\SignatureFingerprint;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviReference;
|
||||
use LIT\MCP\Integrations\Divi\Release\SignatureFingerprint;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RuntimeException;
|
||||
|
||||
@@ -19,7 +19,7 @@ final class DiviReferenceTest extends TestCase
|
||||
$signatureKeys = [];
|
||||
foreach (DiviAdapters::manifests() as $manifest) {
|
||||
foreach ($manifest->calls as $call) {
|
||||
$signatureKeys[] = 'sig:' . ltrim($call->symbol, '\\');
|
||||
$signatureKeys[] = $call->signatureKey();
|
||||
}
|
||||
}
|
||||
$keys = array_values(array_unique(array_merge($mirrorIds, $signatureKeys)));
|
||||
@@ -40,10 +40,10 @@ final class DiviReferenceTest extends TestCase
|
||||
foreach (DiviAdapters::mirrors() as $mirror) {
|
||||
self::assertStringStartsNotWith(DiviReference::SIGNATURE_PREFIX, $mirror->id);
|
||||
}
|
||||
self::assertSame('sig:et_pb_is_allowed', DiviReference::signatureKey(new Call('et_pb_is_allowed', 1)));
|
||||
self::assertSame('sig:et_pb_is_allowed', (new Call('et_pb_is_allowed', 1))->signatureKey());
|
||||
self::assertSame(
|
||||
'sig:ET_Core_PageResource::remove_static_resources',
|
||||
DiviReference::signatureKey(new Call('\\ET_Core_PageResource::remove_static_resources', 3))
|
||||
(new Call('\\ET_Core_PageResource::remove_static_resources', 3))->signatureKey()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureOverview;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Tests\Support\FeatureFakeTool;
|
||||
use LIT\MCP\Tests\Support\MatrixFixtures;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class FeatureStatusTest extends TestCase
|
||||
{
|
||||
public function testOnlyAReleasedFeatureIsUsable(): void
|
||||
{
|
||||
self::assertTrue((new FeatureStatus(DiviFeature::PageRead, ReleaseState::Released, [], 'auto'))->usable());
|
||||
self::assertFalse((new FeatureStatus(DiviFeature::PageRead, ReleaseState::Untested))->usable());
|
||||
self::assertFalse((new FeatureStatus(DiviFeature::PageRead, ReleaseState::Incompatible, ['x']))->usable());
|
||||
}
|
||||
|
||||
public function testSummaryForRefusalsAndToArrayWithTheSource(): void
|
||||
{
|
||||
$status = new FeatureStatus(DiviFeature::PresetWrite, ReleaseState::Incompatible, ['Designsystem: x()']);
|
||||
|
||||
self::assertSame(
|
||||
['id' => 'preset-write', 'label' => DiviFeature::PresetWrite->label(), 'state' => 'incompatible',
|
||||
'problems' => ['Designsystem: x()']],
|
||||
$status->summary()
|
||||
);
|
||||
self::assertSame($status->summary() + ['source' => null], $status->toArray());
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\LineDiff;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LineDiffTest extends TestCase
|
||||
{
|
||||
public function testShowsChangedLinesWithTwoLinesOfContext(): void
|
||||
{
|
||||
$old = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
|
||||
$new = ['a', 'b', 'c', 'd', 'E', 'f', 'g', 'h', 'i', 'j'];
|
||||
|
||||
self::assertSame(
|
||||
[' c', ' d', '- e', '+ E', ' f', ' g', ' h', ' i', '+ j'],
|
||||
LineDiff::lines($old, $new)
|
||||
);
|
||||
}
|
||||
|
||||
public function testMarksAGapBetweenDistantChanges(): void
|
||||
{
|
||||
$old = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
|
||||
$new = ['A', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'J'];
|
||||
|
||||
self::assertSame(['- a', '+ A', ' b', ' c', '…', ' h', ' i', '- j', '+ J'], LineDiff::lines($old, $new));
|
||||
}
|
||||
|
||||
public function testEqualInputHasNoLines(): void
|
||||
{
|
||||
self::assertSame([], LineDiff::lines(['a', 'b'], ['a', 'b']));
|
||||
}
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use ArrayObject;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\ConstantRequirement;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
||||
use LIT\MCP\Integrations\Divi\Release\Problem;
|
||||
use LIT\MCP\Integrations\Divi\Release\SignatureFingerprint;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use RuntimeException;
|
||||
|
||||
final class ManifestCheckTest extends TestCase
|
||||
{
|
||||
private function check(?\Closure $current = null): ManifestCheck
|
||||
{
|
||||
$manifests = [
|
||||
'A' => new Manifest(
|
||||
Manifest::PAGES,
|
||||
calls: [
|
||||
new Call('strlen', 1),
|
||||
new Call('lit_mcp_missing_function', 0),
|
||||
new Call(ArrayObject::class . '::count', 0),
|
||||
new Call('Missing\Klass::run', 0),
|
||||
new Call('str_replace'),
|
||||
],
|
||||
constants: ['PHP_VERSION', 'LIT_MCP_MISSING_CONSTANT'],
|
||||
postTypes: ['et_pb_layout'],
|
||||
taxonomies: ['scope'],
|
||||
blockTypes: ['divi/global-layout'],
|
||||
mirrors: [
|
||||
new Mirror('same', 'a.php', 'a', null, 'gleich'),
|
||||
new Mirror('changed', 'b.php', 'b', null, 'geändert'),
|
||||
new Mirror('unreadable', 'c.php', 'c', null, 'fehlt'),
|
||||
new Mirror('no-expectation', 'd.php', 'd', null, 'ohne Soll'),
|
||||
]
|
||||
),
|
||||
];
|
||||
|
||||
$currentHashes = ['same' => 'h1', 'changed' => 'hX', 'no-expectation' => 'h4'];
|
||||
|
||||
return new ManifestCheck(
|
||||
$manifests,
|
||||
['same' => 'h1', 'changed' => 'h2', 'unreadable' => 'h3'],
|
||||
$current ?? static fn (Mirror $mirror): ?string => $currentHashes[$mirror->id] ?? null,
|
||||
static fn (string $name): bool => false
|
||||
);
|
||||
}
|
||||
|
||||
public function testCodeChecksCoverExistenceAndArgumentCount(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[
|
||||
'Seiten: strlen()',
|
||||
'Seiten: lit_mcp_missing_function()',
|
||||
'Seiten: ArrayObject::count()',
|
||||
'Seiten: Klass::run()',
|
||||
'Seiten: str_replace()',
|
||||
'Seiten: Konstante PHP_VERSION',
|
||||
'Seiten: Konstante LIT_MCP_MISSING_CONSTANT',
|
||||
],
|
||||
array_keys($this->check()->codeChecks())
|
||||
);
|
||||
self::assertSame(
|
||||
[
|
||||
'Seiten: lit_mcp_missing_function()',
|
||||
'Seiten: Klass::run()',
|
||||
'Seiten: Konstante LIT_MCP_MISSING_CONSTANT',
|
||||
],
|
||||
ManifestCheck::failed($this->check()->codeChecks())
|
||||
);
|
||||
}
|
||||
|
||||
public function testAcceptsChecksTheArgumentCountTheAdapterPasses(): void
|
||||
{
|
||||
self::assertTrue(ManifestCheck::accepts(new Call('strlen', 1)));
|
||||
self::assertFalse(ManifestCheck::accepts(new Call('strlen', 2)), 'strlen takes one argument');
|
||||
self::assertFalse(ManifestCheck::accepts(new Call('str_replace', 2)), 'str_replace needs three');
|
||||
self::assertTrue(ManifestCheck::accepts(new Call('sprintf', 5)), 'variadic');
|
||||
self::assertTrue(ManifestCheck::accepts(new Call('str_replace')), 'existence only');
|
||||
}
|
||||
|
||||
public function testMirrorChecksCompareWithTheExpectedFingerprints(): void
|
||||
{
|
||||
$checks = $this->check()->mirrorChecks();
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
'Seiten: Nachbau von a() – gleich',
|
||||
'Seiten: Nachbau von b() – geändert',
|
||||
'Seiten: Nachbau von c() – fehlt',
|
||||
'Seiten: Nachbau von d() – ohne Soll',
|
||||
],
|
||||
array_keys($checks)
|
||||
);
|
||||
self::assertSame(
|
||||
[
|
||||
'Seiten: Nachbau von b() – geändert',
|
||||
'Seiten: Nachbau von c() – fehlt',
|
||||
'Seiten: Nachbau von d() – ohne Soll',
|
||||
],
|
||||
ManifestCheck::failed($checks)
|
||||
);
|
||||
}
|
||||
|
||||
public function testUnreadableMirrorIsAFailedCheck(): void
|
||||
{
|
||||
$check = $this->check(static function (): ?string {
|
||||
throw new RuntimeException('Divi file gone');
|
||||
});
|
||||
|
||||
self::assertCount(4, ManifestCheck::failed($check->mirrorChecks()));
|
||||
}
|
||||
|
||||
public function testRegistrationChecksAskWordPressAndDivi(): void
|
||||
{
|
||||
Functions\when('post_type_exists')->justReturn(true);
|
||||
Functions\when('taxonomy_exists')->justReturn(false);
|
||||
|
||||
$checks = $this->check()->registrationChecks();
|
||||
|
||||
self::assertSame(
|
||||
['Seiten: Post-Typ et_pb_layout', 'Seiten: Taxonomie scope', 'Seiten: Block-Typ divi/global-layout'],
|
||||
array_keys($checks)
|
||||
);
|
||||
self::assertSame(
|
||||
['Seiten: Taxonomie scope', 'Seiten: Block-Typ divi/global-layout'],
|
||||
ManifestCheck::failed($checks)
|
||||
);
|
||||
}
|
||||
|
||||
/** A manifest with one requirement per problem kind; the default feature is page-read. */
|
||||
private function featureCheck(?\Closure $current = null): ManifestCheck
|
||||
{
|
||||
$manifest = new Manifest(
|
||||
Manifest::PAGES,
|
||||
calls: [
|
||||
new Call('strlen', 1),
|
||||
new Call('str_replace', 3, [DiviFeature::PageWrite]),
|
||||
new Call('trim', 1),
|
||||
new Call('lit_mcp_missing_function', 0, [DiviFeature::PageWrite, DiviFeature::ThemeBuilderWrite]),
|
||||
],
|
||||
constants: [
|
||||
new ConstantRequirement('PHP_VERSION'),
|
||||
new ConstantRequirement('LIT_MCP_MISSING_CONSTANT', [DiviFeature::Catalog]),
|
||||
],
|
||||
postTypes: ['lit_mcp_missing_type'],
|
||||
mirrors: [
|
||||
new Mirror('same', 'a.php', 'a', null, 'gleich'),
|
||||
new Mirror('changed', 'b.php', 'b', null, 'geändert', [DiviFeature::ThemeBuilderWrite]),
|
||||
new Mirror('no-expectation', 'd.php', 'd', null, 'ohne Soll'),
|
||||
],
|
||||
features: [DiviFeature::PageRead]
|
||||
);
|
||||
$hashes = ['same' => 'h1', 'changed' => 'hX', 'no-expectation' => 'h4'];
|
||||
|
||||
return new ManifestCheck(
|
||||
['A' => $manifest],
|
||||
[
|
||||
'same' => 'h1',
|
||||
'changed' => 'h2',
|
||||
'sig:strlen' => (string) SignatureFingerprint::of(new Call('strlen', 1)),
|
||||
'sig:str_replace' => 'a different signature',
|
||||
],
|
||||
$current ?? static fn (Mirror $mirror): ?string => $hashes[$mirror->id] ?? null,
|
||||
static fn (string $name): bool => false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<Problem> $problems
|
||||
* @return list<array{label: string, kind: string, features: list<string>}>
|
||||
*/
|
||||
private static function rows(array $problems): array
|
||||
{
|
||||
return array_map(static fn (Problem $problem): array => $problem->toArray(), $problems);
|
||||
}
|
||||
|
||||
public function testCodeProblemsNameKindAndFeaturesOfEveryFailedCall(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[
|
||||
['label' => 'Seiten: str_replace() – Signatur geändert', 'kind' => 'signature',
|
||||
'features' => ['page-write']],
|
||||
['label' => 'Seiten: trim() – Referenz der Signatur fehlt', 'kind' => 'reference-missing',
|
||||
'features' => ['page-read']],
|
||||
['label' => 'Seiten: lit_mcp_missing_function()', 'kind' => 'call',
|
||||
'features' => ['page-write', 'tb-write']],
|
||||
['label' => 'Seiten: Konstante LIT_MCP_MISSING_CONSTANT', 'kind' => 'constant',
|
||||
'features' => ['catalog']],
|
||||
],
|
||||
self::rows($this->featureCheck(static function (): never {
|
||||
self::fail('code problems never read Divi files');
|
||||
})->codeProblems())
|
||||
);
|
||||
}
|
||||
|
||||
public function testAMirrorWithoutReferenceIsAMirrorProblemLikeAChangedOne(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[
|
||||
['label' => 'Seiten: Nachbau von b() – geändert', 'kind' => 'mirror', 'features' => ['tb-write']],
|
||||
['label' => 'Seiten: Nachbau von d() – ohne Soll', 'kind' => 'mirror', 'features' => ['page-read']],
|
||||
],
|
||||
self::rows($this->featureCheck()->mirrorProblems())
|
||||
);
|
||||
}
|
||||
|
||||
public function testAnUnreadableMirrorIsAMirrorProblem(): void
|
||||
{
|
||||
$problems = $this->featureCheck(static function (): never {
|
||||
throw new RuntimeException('Divi file gone');
|
||||
})->mirrorProblems();
|
||||
|
||||
self::assertSame(['mirror', 'mirror', 'mirror'], array_column(self::rows($problems), 'kind'));
|
||||
}
|
||||
|
||||
public function testProblemsAreCodeThenMirrorsAndRegistrationIsNone(): void
|
||||
{
|
||||
$check = $this->featureCheck();
|
||||
|
||||
self::assertEquals(array_merge($check->codeProblems(), $check->mirrorProblems()), $check->problems());
|
||||
self::assertNotContains(
|
||||
'Seiten: Post-Typ lit_mcp_missing_type',
|
||||
array_column(self::rows($check->problems()), 'label')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\ConstantRequirement;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\Release\Mirror;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class ManifestTest extends TestCase
|
||||
{
|
||||
public function testCallsKnowTheirClassMemberAndLabel(): void
|
||||
{
|
||||
$function = new Call('et_pb_is_allowed', 1);
|
||||
$method = new Call('ET\Builder\Packages\GlobalData\GlobalData::get_global_colors', 0);
|
||||
|
||||
self::assertNull($function->className());
|
||||
self::assertSame('et_pb_is_allowed', $function->member());
|
||||
self::assertSame('et_pb_is_allowed()', $function->label());
|
||||
self::assertSame('ET\Builder\Packages\GlobalData\GlobalData', $method->className());
|
||||
self::assertSame('get_global_colors', $method->member());
|
||||
self::assertSame('GlobalData::get_global_colors()', $method->label());
|
||||
self::assertSame('ET_Core_PageResource', (new Call('\ET_Core_PageResource::remove_static_resources', 3))->className());
|
||||
}
|
||||
|
||||
public function testMirrorLabel(): void
|
||||
{
|
||||
$function = new Mirror('tb-api-save', 'includes/api.php', 'et_theme_builder_api_save', null, 'Vorlagenliste');
|
||||
$method = new Mirror('vb-flags', 'x.php', 'update', 'SyncToServerController', 'Kennzeichen');
|
||||
|
||||
self::assertSame('et_theme_builder_api_save()', $function->label());
|
||||
self::assertSame('SyncToServerController::update()', $method->label());
|
||||
}
|
||||
|
||||
public function testNamesListEveryDeclaredDiviName(): void
|
||||
{
|
||||
$manifest = new Manifest(
|
||||
Manifest::LIBRARY,
|
||||
calls: [new Call('et_pb_is_allowed', 1), new Call('ET\Builder\GlobalLayout::is_global_layout_template', 1)],
|
||||
constants: ['ET_BUILDER_PRODUCT_VERSION'],
|
||||
postTypes: ['et_pb_layout'],
|
||||
taxonomies: ['scope'],
|
||||
blockTypes: ['divi/global-layout'],
|
||||
keys: ['_et_pb_module_type']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['et_pb_is_allowed', 'ET\Builder\GlobalLayout', 'ET_BUILDER_PRODUCT_VERSION', 'et_pb_layout', 'scope',
|
||||
'_et_pb_module_type'],
|
||||
$manifest->names()
|
||||
);
|
||||
self::assertSame('Bibliothek', $manifest->area);
|
||||
}
|
||||
|
||||
public function testPlainConstantNamesBecomeRequirementsWithALabel(): void
|
||||
{
|
||||
$manifest = new Manifest(
|
||||
Manifest::CATALOG,
|
||||
constants: ['ET_BUILDER_PRODUCT_VERSION', new ConstantRequirement('ET_OTHER', [DiviFeature::Roles])]
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['ET_BUILDER_PRODUCT_VERSION', 'ET_OTHER'],
|
||||
array_map(static fn (ConstantRequirement $constant): string => $constant->name, $manifest->constants)
|
||||
);
|
||||
self::assertSame('Konstante ET_OTHER', $manifest->constants[1]->label());
|
||||
self::assertSame([], $manifest->constants[0]->features());
|
||||
self::assertSame([DiviFeature::Roles], $manifest->constants[1]->features());
|
||||
self::assertSame(['ET_BUILDER_PRODUCT_VERSION', 'ET_OTHER'], $manifest->names());
|
||||
}
|
||||
|
||||
public function testRequirementsAreCallsConstantsAndMirrorsInThatOrder(): void
|
||||
{
|
||||
$call = new Call('et_pb_is_allowed', 1);
|
||||
$mirror = new Mirror('m', 'a.php', 'a', null, 'Terme');
|
||||
$manifest = new Manifest(Manifest::LIBRARY, calls: [$call], constants: ['ET_X'], mirrors: [$mirror]);
|
||||
|
||||
$requirements = $manifest->requirements();
|
||||
|
||||
self::assertCount(3, $requirements);
|
||||
self::assertSame($call, $requirements[0]);
|
||||
self::assertSame('Konstante ET_X', $requirements[1]->label());
|
||||
self::assertSame($mirror, $requirements[2]);
|
||||
}
|
||||
|
||||
public function testFeaturesOfPrefersTheOwnFeaturesOverTheManifestDefault(): void
|
||||
{
|
||||
$own = new Call('et_a', null, [DiviFeature::PageWrite, DiviFeature::ThemeBuilderWrite]);
|
||||
$inherited = new Call('et_b');
|
||||
$mirror = new Mirror('m', 'a.php', 'a', null, 'x', [DiviFeature::LibraryWrite]);
|
||||
$manifest = new Manifest(
|
||||
Manifest::PAGES,
|
||||
calls: [$own, $inherited],
|
||||
constants: ['ET_X'],
|
||||
mirrors: [$mirror],
|
||||
features: [DiviFeature::PageRead]
|
||||
);
|
||||
|
||||
self::assertSame([DiviFeature::PageWrite, DiviFeature::ThemeBuilderWrite], $manifest->featuresOf($own));
|
||||
self::assertSame([DiviFeature::PageRead], $manifest->featuresOf($inherited));
|
||||
self::assertSame([DiviFeature::PageRead], $manifest->featuresOf($manifest->constants[0]));
|
||||
self::assertSame([DiviFeature::LibraryWrite], $manifest->featuresOf($mirror));
|
||||
}
|
||||
|
||||
public function testWithoutAnyFeaturesAnEntryHasNone(): void
|
||||
{
|
||||
$call = new Call('et_a');
|
||||
|
||||
self::assertSame([], (new Manifest(Manifest::PAGES, calls: [$call]))->featuresOf($call));
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\Problem;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class ProblemTest extends TestCase
|
||||
{
|
||||
public function testOnlyCallMirrorConstantAndResolverAreHard(): void
|
||||
{
|
||||
$hard = [];
|
||||
foreach (['call', 'signature', 'mirror', 'constant', 'reference-missing', 'resolver'] as $kind) {
|
||||
$hard[$kind] = (new Problem('x', [DiviFeature::PageWrite], $kind))->isHard();
|
||||
}
|
||||
|
||||
self::assertSame(
|
||||
['call' => true, 'signature' => false, 'mirror' => true, 'constant' => true,
|
||||
'reference-missing' => false, 'resolver' => true],
|
||||
$hard
|
||||
);
|
||||
}
|
||||
|
||||
public function testConcernsItsFeaturesAndWithoutFeaturesEveryFeature(): void
|
||||
{
|
||||
$problem = new Problem('x', [DiviFeature::PageWrite, DiviFeature::ThemeBuilderWrite], Problem::CALL);
|
||||
self::assertTrue($problem->concerns(DiviFeature::ThemeBuilderWrite));
|
||||
self::assertFalse($problem->concerns(DiviFeature::PageRead));
|
||||
|
||||
$unassigned = new Problem('x', [], Problem::CALL);
|
||||
foreach (DiviFeature::cases() as $feature) {
|
||||
self::assertTrue($unassigned->concerns($feature), $feature->value);
|
||||
}
|
||||
}
|
||||
|
||||
public function testRoundTripsThroughTheCacheFormat(): void
|
||||
{
|
||||
$problem = new Problem('Seiten: Nachbau von a() – x', [DiviFeature::PageWrite], Problem::MIRROR);
|
||||
|
||||
self::assertSame(
|
||||
['label' => 'Seiten: Nachbau von a() – x', 'kind' => 'mirror', 'features' => ['page-write']],
|
||||
$problem->toArray()
|
||||
);
|
||||
self::assertEquals($problem, Problem::fromArray($problem->toArray()));
|
||||
}
|
||||
|
||||
public function testFromArrayRefusesAnythingElse(): void
|
||||
{
|
||||
foreach ([
|
||||
'no array' => 'Seiten: x()',
|
||||
'no label' => ['kind' => 'call', 'features' => []],
|
||||
'unknown kind' => ['label' => 'x', 'kind' => 'other', 'features' => []],
|
||||
'unknown feature' => ['label' => 'x', 'kind' => 'call', 'features' => ['page-delete']],
|
||||
'features no list' => ['label' => 'x', 'kind' => 'call', 'features' => 'page-write'],
|
||||
] as $case => $row) {
|
||||
self::assertNull(Problem::fromArray($row), $case);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,13 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\Compatibility\Capability;
|
||||
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Tests\Support\DiviFeatureFixtures;
|
||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||
@@ -43,6 +45,37 @@ final class ReleaseGateTest extends TestCase
|
||||
self::assertSame('5.3.0', $lock->status->version);
|
||||
}
|
||||
|
||||
public function testALockWhoseLockedCapabilityIsNoDiviFeatureStillRefusesTheFeatureAsked(): void
|
||||
{
|
||||
$foreign = new class () implements Capability {
|
||||
public function id(): string
|
||||
{
|
||||
return DiviFeature::PageWrite->id();
|
||||
}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return 'fremde Fähigkeit';
|
||||
}
|
||||
|
||||
public function isWrite(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
ReleaseGate::useResolver(static fn (): ReleaseStatus => ReleaseStatus::of(
|
||||
'5.3.0',
|
||||
CompatibilityMatrix::uniform([$foreign], ReleaseState::Incompatible, ['fremde Fähigkeit'])
|
||||
));
|
||||
|
||||
try {
|
||||
ReleaseGate::assertFeature(DiviFeature::PageWrite);
|
||||
self::fail('a locked feature must refuse');
|
||||
} catch (DiviLocked $locked) {
|
||||
self::assertSame([DiviFeature::PageWrite], $locked->features);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssertFeatureRefusesOnlyALockedFeature(): void
|
||||
{
|
||||
ReleaseGate::useResolver(static fn (): ReleaseStatus => ReleaseMatrices::status(
|
||||
|
||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||
use LIT\MCP\Integrations\Divi\Library\LibraryItemSpec;
|
||||
@@ -14,7 +15,6 @@ use LIT\MCP\Integrations\Divi\Pages\SaveScope;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviLocked;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
||||
|
||||
@@ -6,11 +6,11 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use Brain\Monkey\Filters;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\ManifestCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\Problem;
|
||||
use LIT\MCP\Compatibility\ManifestCheck;
|
||||
use LIT\MCP\Compatibility\Problem;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStore;
|
||||
use LIT\MCP\Plugin;
|
||||
|
||||
@@ -4,10 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityMatrix;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Compatibility\CompatibilityMatrix;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Compatibility\FeatureStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Tests\Support\ReleaseMatrices;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
@@ -57,14 +57,14 @@ final class ReleaseStatusTest extends TestCase
|
||||
self::assertNull($status->source);
|
||||
self::assertSame(['Seiten: et_x() – Signatur geändert'], $status->problems);
|
||||
self::assertSame(['user_id' => 1], $status->release);
|
||||
self::assertSame('auto', ReleaseStatus::of('5.99.0', CompatibilityMatrix::allReleased('auto'))->source);
|
||||
self::assertSame('auto', ReleaseStatus::of('5.99.0', CompatibilityMatrix::allReleased(DiviFeature::cases(), 'auto'))->source);
|
||||
}
|
||||
|
||||
public function testAMatrixInAnotherStateThanTheStatusIsRefused(): void
|
||||
{
|
||||
$this->expectException(LogicException::class);
|
||||
|
||||
new ReleaseStatus(ReleaseState::Released, '5.2.1', 'code', [], null, CompatibilityMatrix::allIncompatible('x'));
|
||||
new ReleaseStatus(ReleaseState::Released, '5.2.1', 'code', [], null, CompatibilityMatrix::allIncompatible(DiviFeature::cases(), 'x'));
|
||||
}
|
||||
|
||||
public function testRefusalForAnUntestedFeatureNamesItAndKeepsTheOthersWorking(): void
|
||||
@@ -101,7 +101,7 @@ final class ReleaseStatusTest extends TestCase
|
||||
$features[$feature->value] = $matrix->of($feature);
|
||||
}
|
||||
$features['library-write'] = new FeatureStatus(DiviFeature::LibraryWrite, ReleaseState::Untested);
|
||||
$status = ReleaseStatus::of('5.99.0', new CompatibilityMatrix($features));
|
||||
$status = ReleaseStatus::of('5.99.0', new CompatibilityMatrix(DiviFeature::cases(), $features));
|
||||
|
||||
$payload = self::assertToolError(
|
||||
$status->refusalFor([DiviFeature::PageWrite, DiviFeature::LibraryWrite, DiviFeature::ThemeBuilderWrite]),
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use ArrayObject;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\SignatureFingerprint;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/** Stand-in for a Divi class: one baseline method and one variant per property the fingerprint covers. */
|
||||
final class SignatureFixture
|
||||
{
|
||||
public static function base(int $id, string|array $data = [], &$ref = null, ...$rest): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Same signature, other parameter names and other default values: no change. */
|
||||
public static function renamed(int $post, string|array $payload = '', &$out = 5, ...$more): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function extraRequired(int $id, string|array $data, &$ref = null, ...$rest): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function fewer(int $id, string|array $data = []): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function typeChanged(string $id, string|array $data = [], &$ref = null, ...$rest): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function unionWidened(int $id, string|array|int $data = [], &$ref = null, ...$rest): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function notNullable(int $id, string|array $data = [], &$ref = null, ...$rest): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function byValue(int $id, string|array $data = [], $ref = null, ...$rest): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function notVariadic(int $id, string|array $data = [], &$ref = null, $rest = null): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function defaultRemoved(int $id, string|array $data, &$ref, ...$rest): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function returnChanged(int $id, string|array $data = [], &$ref = null, ...$rest): ?int
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function notStatic(int $id, string|array $data = [], &$ref = null, ...$rest): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static function notPublic(int $id, string|array $data = [], &$ref = null, ...$rest): ?bool
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function untyped($id, $data = [])
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function mixedTyped(mixed $id, mixed $data = []): mixed
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final class SignatureFingerprintTest extends TestCase
|
||||
{
|
||||
private const FIXTURE = SignatureFixture::class;
|
||||
|
||||
private static function method(string $name): Call
|
||||
{
|
||||
return new Call(self::FIXTURE . '::' . $name);
|
||||
}
|
||||
|
||||
public function testIsASha256OfAnExistingFunctionAndStable(): void
|
||||
{
|
||||
$hash = SignatureFingerprint::of(new Call('strlen', 1));
|
||||
|
||||
self::assertMatchesRegularExpression('/^[0-9a-f]{64}$/', (string) $hash);
|
||||
self::assertSame($hash, SignatureFingerprint::of(new Call('strlen', 1)));
|
||||
self::assertNotSame($hash, SignatureFingerprint::of(new Call('str_replace', 3)));
|
||||
}
|
||||
|
||||
public function testMissingSymbolsGiveNull(): void
|
||||
{
|
||||
self::assertNull(SignatureFingerprint::of(new Call('lit_mcp_missing_function')));
|
||||
self::assertNull(SignatureFingerprint::of(new Call('Missing\Klass::run')));
|
||||
self::assertNull(SignatureFingerprint::of(new Call(ArrayObject::class . '::missing')));
|
||||
self::assertNull(SignatureFingerprint::canonical(new Call('lit_mcp_missing_function')));
|
||||
}
|
||||
|
||||
public function testCanonicalTextDescribesTheSignature(): void
|
||||
{
|
||||
self::assertSame(
|
||||
'public static (int, array|string=, &mixed=, ...mixed): ?bool',
|
||||
SignatureFingerprint::canonical(self::method('base'))
|
||||
);
|
||||
self::assertSame('function (string): int', SignatureFingerprint::canonical(new Call('strlen')));
|
||||
self::assertSame(
|
||||
'public (int, array|string=, &mixed=, ...mixed): ?bool',
|
||||
SignatureFingerprint::canonical(self::method('notStatic'))
|
||||
);
|
||||
}
|
||||
|
||||
/** @return array<string, array{string}> */
|
||||
public static function changedSignatures(): array
|
||||
{
|
||||
return [
|
||||
'extra required parameter' => ['extraRequired'],
|
||||
'fewer parameters' => ['fewer'],
|
||||
'parameter type' => ['typeChanged'],
|
||||
'wider union' => ['unionWidened'],
|
||||
'return type loses null' => ['notNullable'],
|
||||
'by reference lost' => ['byValue'],
|
||||
'variadic lost' => ['notVariadic'],
|
||||
'default removed' => ['defaultRemoved'],
|
||||
'return type' => ['returnChanged'],
|
||||
'no longer static' => ['notStatic'],
|
||||
'no longer public' => ['notPublic'],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider changedSignatures */
|
||||
public function testAnyChangeOfTheInterfaceChangesTheHash(string $variant): void
|
||||
{
|
||||
self::assertNotSame(
|
||||
SignatureFingerprint::of(self::method('base')),
|
||||
SignatureFingerprint::of(self::method($variant)),
|
||||
$variant
|
||||
);
|
||||
}
|
||||
|
||||
public function testRenamedParametersAndOtherDefaultValuesKeepTheHash(): void
|
||||
{
|
||||
self::assertSame(
|
||||
SignatureFingerprint::of(self::method('base')),
|
||||
SignatureFingerprint::of(self::method('renamed'))
|
||||
);
|
||||
}
|
||||
|
||||
public function testNoTypeReadsAsMixed(): void
|
||||
{
|
||||
self::assertSame(
|
||||
SignatureFingerprint::of(self::method('untyped')),
|
||||
SignatureFingerprint::of(self::method('mixedTyped'))
|
||||
);
|
||||
}
|
||||
|
||||
public function testTheCallsOwnArgumentCountAndFeaturesAreNotPartOfIt(): void
|
||||
{
|
||||
self::assertSame(
|
||||
SignatureFingerprint::of(new Call(self::FIXTURE . '::base', 2)),
|
||||
SignatureFingerprint::of(new Call('\\' . self::FIXTURE . '::base', null, []))
|
||||
);
|
||||
}
|
||||
|
||||
public function testAFunctionAndAMethodOfTheSameShapeDiffer(): void
|
||||
{
|
||||
self::assertNotSame(
|
||||
SignatureFingerprint::of(new Call('strlen')),
|
||||
SignatureFingerprint::of(new Call(ArrayObject::class . '::count'))
|
||||
);
|
||||
}
|
||||
|
||||
public function testTheClassNeverIncludesAFile(): void
|
||||
{
|
||||
$source = (string) file_get_contents(
|
||||
dirname(__DIR__, 5) . '/src/Integrations/Divi/Release/SignatureFingerprint.php'
|
||||
);
|
||||
$forbidden = [T_INCLUDE, T_INCLUDE_ONCE, T_REQUIRE, T_REQUIRE_ONCE, T_EVAL];
|
||||
|
||||
foreach (token_get_all($source) as $token) {
|
||||
self::assertFalse(is_array($token) && in_array($token[0], $forbidden, true), 'no include, require or eval');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Release\SourceFingerprint;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RuntimeException;
|
||||
|
||||
final class SourceFingerprintTest extends TestCase
|
||||
{
|
||||
/** Shaped like Divi's files: a guarded function, two classes with a method of the same name. */
|
||||
private const SOURCE = <<<'PHP'
|
||||
<?php
|
||||
use function et_demo_save;
|
||||
if ( ! function_exists( 'et_demo_save' ) ) {
|
||||
/**
|
||||
* Saves.
|
||||
*/
|
||||
function et_demo_save( $id, $data = array() ) {
|
||||
$value = "{$data['x']}";
|
||||
if ( $id ) {
|
||||
update_post_meta( $id, '_et_demo', $value );
|
||||
}
|
||||
return Foo::class;
|
||||
}
|
||||
}
|
||||
|
||||
class Controller {
|
||||
public static function update( $request ) {
|
||||
return array( 'a' => 1 );
|
||||
}
|
||||
}
|
||||
|
||||
class Other {
|
||||
public static function update( $request ) {
|
||||
return array( 'b' => 2 );
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
public function testFindsAFunctionInsideAFunctionExistsGuard(): void
|
||||
{
|
||||
$print = SourceFingerprint::fromSource(self::SOURCE, 'et_demo_save');
|
||||
|
||||
self::assertNotNull($print);
|
||||
self::assertSame(7, $print->startLine);
|
||||
self::assertSame(13, $print->endLine);
|
||||
self::assertStringStartsWith('function et_demo_save(', $print->source);
|
||||
self::assertStringEndsWith('}', $print->source);
|
||||
self::assertMatchesRegularExpression('/^[0-9a-f]{64}$/', $print->hash);
|
||||
}
|
||||
|
||||
public function testClassConstantsAndInterpolationDoNotConfuseTheBraceCount(): void
|
||||
{
|
||||
$print = SourceFingerprint::fromSource(self::SOURCE, 'et_demo_save');
|
||||
|
||||
self::assertNotNull($print);
|
||||
self::assertStringContainsString('return Foo::class;', $print->source);
|
||||
self::assertStringNotContainsString('class Controller', $print->source);
|
||||
}
|
||||
|
||||
public function testMethodIsFoundInItsOwnClassOnly(): void
|
||||
{
|
||||
$controller = SourceFingerprint::fromSource(self::SOURCE, 'update', 'ET\Builder\VisualBuilder\Controller');
|
||||
$other = SourceFingerprint::fromSource(self::SOURCE, 'update', 'Other');
|
||||
|
||||
self::assertNotNull($controller);
|
||||
self::assertNotNull($other);
|
||||
self::assertStringContainsString("'a' => 1", $controller->source);
|
||||
self::assertStringContainsString("'b' => 2", $other->source);
|
||||
self::assertNotSame($controller->hash, $other->hash);
|
||||
self::assertNull(SourceFingerprint::fromSource(self::SOURCE, 'update'), 'a method is no top-level function');
|
||||
self::assertNull(SourceFingerprint::fromSource(self::SOURCE, 'et_demo_save', 'Controller'));
|
||||
self::assertNull(SourceFingerprint::fromSource(self::SOURCE, 'missing'));
|
||||
}
|
||||
|
||||
public function testCommentsAndWhitespaceDoNotChangeTheHash(): void
|
||||
{
|
||||
$reformatted = str_replace(
|
||||
["\t\t\$value = ", "if ( \$id ) {"],
|
||||
["\t\t// Why: demo.\n\t\t\$value = ", "if (\$id)\n\t\t{"],
|
||||
self::SOURCE
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
SourceFingerprint::fromSource(self::SOURCE, 'et_demo_save')?->hash,
|
||||
SourceFingerprint::fromSource($reformatted, 'et_demo_save')?->hash
|
||||
);
|
||||
}
|
||||
|
||||
public function testACodeChangeChangesTheHash(): void
|
||||
{
|
||||
$changed = str_replace("'_et_demo'", "'_et_demo_v2'", self::SOURCE);
|
||||
|
||||
self::assertNotSame(
|
||||
SourceFingerprint::fromSource(self::SOURCE, 'et_demo_save')?->hash,
|
||||
SourceFingerprint::fromSource($changed, 'et_demo_save')?->hash
|
||||
);
|
||||
}
|
||||
|
||||
public function testOfReadsTheFileAndThrowsForMissingFunctions(): void
|
||||
{
|
||||
$file = (string) tempnam(sys_get_temp_dir(), 'lit');
|
||||
file_put_contents($file, self::SOURCE);
|
||||
|
||||
try {
|
||||
self::assertSame(
|
||||
SourceFingerprint::fromSource(self::SOURCE, 'et_demo_save')?->hash,
|
||||
SourceFingerprint::of($file, 'et_demo_save')->hash
|
||||
);
|
||||
try {
|
||||
SourceFingerprint::of($file, 'update', 'Missing');
|
||||
self::fail('a missing method must throw');
|
||||
} catch (RuntimeException $e) {
|
||||
self::assertStringContainsString('Missing::update() not found', $e->getMessage());
|
||||
}
|
||||
} finally {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
public function testOfThrowsForAnUnreadableFile(): void
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('is not readable');
|
||||
|
||||
SourceFingerprint::of('/nonexistent/lit-divi.php', 'et_demo_save');
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Compatibility\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseGate;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseState;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseStatus;
|
||||
use LIT\MCP\Integrations\Divi\Release\WriteProbe;
|
||||
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
||||
|
||||
@@ -6,10 +6,10 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Schema;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\ConstantRequirement;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Compatibility\ConstantRequirement;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
|
||||
@@ -19,8 +19,8 @@ final class DiviModulesTest extends TestCase
|
||||
{
|
||||
self::assertContains(DiviModules::class, DiviAdapters::CLASSES);
|
||||
self::assertContains(DynamicContentMap::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::CATALOG, DiviModules::manifest()->area);
|
||||
self::assertSame(Manifest::CATALOG, DynamicContentMap::manifest()->area);
|
||||
self::assertSame(DiviAreas::CATALOG, DiviModules::manifest()->area);
|
||||
self::assertSame(DiviAreas::CATALOG, DynamicContentMap::manifest()->area);
|
||||
}
|
||||
|
||||
public function testManifestListsModuleRegistrationAndTheBuilderSwitch(): void
|
||||
|
||||
@@ -7,9 +7,9 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\ThemeBuilder;
|
||||
use Brain\Monkey\Actions;
|
||||
use Brain\Monkey\Filters;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Compatibility\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAreas;
|
||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\InsertedBeforeFailure;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
@@ -25,7 +25,7 @@ final class DiviThemeBuilderTest extends TestCase
|
||||
$manifest = DiviThemeBuilder::manifest();
|
||||
|
||||
self::assertContains(DiviThemeBuilder::class, DiviAdapters::CLASSES);
|
||||
self::assertSame(Manifest::THEME_BUILDER, $manifest->area);
|
||||
self::assertSame(DiviAreas::THEME_BUILDER, $manifest->area);
|
||||
self::assertSame(DiviThemeBuilder::postTypes(), $manifest->postTypes);
|
||||
self::assertSame(
|
||||
['tb-api-save', 'tb-store-template', 'tb-load-setting-options'],
|
||||
|
||||
Reference in New Issue
Block a user