Files
breadcrumb-the-shire/tests/Architecture/ModuleRegistryContractTest.php

128 lines
4.9 KiB
PHP
Raw Normal View History

<?php
namespace MintyPHP\Tests\Architecture;
use MintyPHP\App\Module\ModuleRegistry;
use PHPUnit\Framework\TestCase;
/**
* Architecture test: verifies module registry contract in both module-on and module-off modes.
*/
final class ModuleRegistryContractTest extends TestCase
{
public function testRegistryIsAvailableInContainer(): void
{
$registry = app(ModuleRegistry::class);
self::assertInstanceOf(ModuleRegistry::class, $registry);
}
public function testAddressBookModuleLoadsWhenEnabled(): void
{
$registry = app(ModuleRegistry::class);
// config/modules.php has addressbook enabled by default
self::assertTrue($registry->hasModule('addressbook'));
self::assertNotEmpty($registry->getSearchResources());
self::assertNotEmpty($registry->getLayoutContextProviders());
self::assertNotEmpty($registry->getSessionProviders());
}
public function testModuleOffModeReturnsEmptyRegistry(): void
{
$modulesDir = dirname(__DIR__, 2) . '/modules';
// Boot a fresh registry with no modules enabled (simulates APP_ENABLED_MODULES='')
$registry = ModuleRegistry::boot($modulesDir, []);
self::assertSame([], $registry->getModules());
self::assertSame([], $registry->getRoutes());
self::assertSame([], $registry->getPermissions());
self::assertSame([], $registry->getSearchResources());
self::assertSame([], $registry->getLayoutContextProviders());
self::assertSame([], $registry->getSessionProviders());
self::assertSame([], $registry->getSlotContributions('aside.tab_panel'));
}
public function testAddressBookModuleManifestIsValid(): void
{
$modulesDir = dirname(__DIR__, 2) . '/modules';
$manifestFile = $modulesDir . '/addressbook/module.php';
self::assertFileExists($manifestFile, 'Address book module manifest must exist');
$raw = require $manifestFile;
self::assertIsArray($raw);
self::assertSame('addressbook', $raw['id']);
// Permissions owned by Core PermissionService, not module
self::assertSame([], $raw['permissions']);
// Asset groups owned by config/assets.php, not module
self::assertSame([], $raw['asset_groups']);
self::assertNotEmpty($raw['search_resources']);
self::assertNotEmpty($raw['layout_context_providers']);
self::assertNotEmpty($raw['session_providers']);
self::assertArrayHasKey('aside.tab_panel', $raw['ui_slots']);
}
public function testModuleProviderClassesExist(): void
{
self::assertTrue(
class_exists(\MintyPHP\Module\AddressBook\Providers\AddressBookSearchProvider::class),
'AddressBookSearchProvider class must be autoloadable'
);
self::assertTrue(
class_exists(\MintyPHP\Module\AddressBook\Providers\AddressBookLayoutProvider::class),
'AddressBookLayoutProvider class must be autoloadable'
);
self::assertTrue(
class_exists(\MintyPHP\Module\AddressBook\Providers\AddressBookSessionProvider::class),
'AddressBookSessionProvider class must be autoloadable'
);
}
public function testProviderClassesImplementContracts(): void
{
self::assertInstanceOf(
\MintyPHP\App\Module\Contracts\SearchResourceProvider::class,
new \MintyPHP\Module\AddressBook\Providers\AddressBookSearchProvider()
);
self::assertInstanceOf(
\MintyPHP\App\Module\Contracts\LayoutContextProvider::class,
new \MintyPHP\Module\AddressBook\Providers\AddressBookLayoutProvider()
);
self::assertInstanceOf(
\MintyPHP\App\Module\Contracts\SessionProvider::class,
new \MintyPHP\Module\AddressBook\Providers\AddressBookSessionProvider()
);
}
public function testConflictDetectionIsStrict(): void
{
$fixturesDir = sys_get_temp_dir() . '/module-arch-test-' . uniqid();
mkdir($fixturesDir . '/mod-a', 0777, true);
mkdir($fixturesDir . '/mod-b', 0777, true);
file_put_contents($fixturesDir . '/mod-a/module.php', '<?php return ' . var_export([
'id' => 'mod-a',
'permissions' => ['shared.perm'],
], true) . ';');
file_put_contents($fixturesDir . '/mod-b/module.php', '<?php return ' . var_export([
'id' => 'mod-b',
'permissions' => ['shared.perm'],
], true) . ';');
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Permission conflict');
try {
ModuleRegistry::boot($fixturesDir, ['mod-a', 'mod-b']);
} finally {
array_map('unlink', glob($fixturesDir . '/mod-a/*') ?: []);
array_map('unlink', glob($fixturesDir . '/mod-b/*') ?: []);
rmdir($fixturesDir . '/mod-a');
rmdir($fixturesDir . '/mod-b');
rmdir($fixturesDir);
}
}
}