first commit
This commit is contained in:
112
tests/Architecture/ModuleBoundaryGovernanceTest.php
Normal file
112
tests/Architecture/ModuleBoundaryGovernanceTest.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Architecture;
|
||||
|
||||
use Tests\Architecture\Support\ArchitectureTestCase;
|
||||
|
||||
final class ModuleBoundaryGovernanceTest extends ArchitectureTestCase
|
||||
{
|
||||
public function testKernelDoesNotImportFeatureModules(): void
|
||||
{
|
||||
$violations = [];
|
||||
$featurePrefixes = [
|
||||
'Netig\\Netslim\\Identity\\',
|
||||
'Netig\\Netslim\\Settings\\',
|
||||
'Netig\\Netslim\\AuditLog\\',
|
||||
'Netig\\Netslim\\Notifications\\',
|
||||
'Netig\\Netslim\\Taxonomy\\',
|
||||
'Netig\\Netslim\\Media\\',
|
||||
];
|
||||
|
||||
foreach ($this->phpFilesUnder('src/Kernel') as $file) {
|
||||
foreach ($this->importedClasses($file) as $import) {
|
||||
$importsFeatureModule = false;
|
||||
foreach ($featurePrefixes as $prefix) {
|
||||
if (str_starts_with($import, $prefix)) {
|
||||
$importsFeatureModule = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$importsFeatureModule) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$violations[] = $this->relativePath($file) . ' -> ' . $import;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertNoArchitectureViolations(
|
||||
$violations,
|
||||
'Kernel must not import feature modules directly',
|
||||
);
|
||||
}
|
||||
|
||||
public function testApplicationDomainAndInfrastructureUseOnlyApprovedCrossModuleContracts(): void
|
||||
{
|
||||
$violations = [];
|
||||
$allowedExternalImports = [
|
||||
'Identity' => [],
|
||||
'Settings' => [],
|
||||
'AuditLog' => [],
|
||||
'Notifications' => [],
|
||||
'Taxonomy' => [],
|
||||
'Media' => [],
|
||||
];
|
||||
|
||||
foreach (self::FEATURE_MODULES as $module) {
|
||||
$directories = [
|
||||
$this->projectPath('src/' . $module . '/Application'),
|
||||
$this->projectPath('src/' . $module . '/Domain'),
|
||||
$this->projectPath('src/' . $module . '/Infrastructure'),
|
||||
];
|
||||
|
||||
foreach ($directories as $directory) {
|
||||
if (!is_dir($directory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory));
|
||||
foreach ($iterator as $fileInfo) {
|
||||
if (!$fileInfo->isFile() || $fileInfo->getExtension() !== 'php') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$file = $fileInfo->getPathname();
|
||||
$imports = $this->importedClasses($file);
|
||||
|
||||
foreach ($imports as $import) {
|
||||
if (!str_starts_with($import, 'Netig\\Netslim\\')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_starts_with($import, 'Netig\\Netslim\\Kernel\\') || str_starts_with($import, 'Netig\\Netslim\\' . $module . '\\')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isAllowed = false;
|
||||
foreach ($allowedExternalImports[$module] as $allowedPrefix) {
|
||||
if (str_starts_with($import, $allowedPrefix)) {
|
||||
$isAllowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isAllowed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$violations[] = $this->relativePath($file) . ' -> ' . $import;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertNoArchitectureViolations(
|
||||
$violations,
|
||||
'Application, Domain and Infrastructure layers must only cross module boundaries through approved public contracts',
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user