first commit
This commit is contained in:
90
tests/Architecture/SupportGovernanceTest.php
Normal file
90
tests/Architecture/SupportGovernanceTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Architecture;
|
||||
|
||||
use Tests\Architecture\Support\ArchitectureTestCase;
|
||||
|
||||
final class SupportGovernanceTest extends ArchitectureTestCase
|
||||
{
|
||||
/** @var list<string> */
|
||||
private const APPROVED_SUPPORT_TOP_LEVEL_ENTRIES = [
|
||||
'Exception',
|
||||
'Util',
|
||||
];
|
||||
|
||||
/** @var list<string> */
|
||||
private const APPROVED_SUPPORT_FILES = [
|
||||
'Exception/NotFoundException.php',
|
||||
'Util/DateParser.php',
|
||||
'Util/SlugHelper.php',
|
||||
];
|
||||
|
||||
public function testSupportUsesOnlyApprovedTopLevelEntries(): void
|
||||
{
|
||||
$supportPath = $this->projectPath('src/Kernel/Support');
|
||||
self::assertDirectoryExists($supportPath);
|
||||
|
||||
$entries = array_values(array_filter(scandir($supportPath) ?: [], static fn (string $entry): bool => !in_array($entry, ['.', '..'], true)));
|
||||
sort($entries);
|
||||
|
||||
self::assertSame(
|
||||
self::APPROVED_SUPPORT_TOP_LEVEL_ENTRIES,
|
||||
$entries,
|
||||
'Kernel/Support is frozen by default: only explicitly approved subdirectories may exist.',
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportContainsOnlyExplicitlyApprovedFiles(): void
|
||||
{
|
||||
$supportPath = $this->projectPath('src/Kernel/Support');
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($supportPath, \FilesystemIterator::SKIP_DOTS),
|
||||
);
|
||||
|
||||
$files = [];
|
||||
foreach ($iterator as $fileInfo) {
|
||||
if (!$fileInfo->isFile() || $fileInfo->getExtension() !== 'php') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$files[] = substr($fileInfo->getPathname(), strlen($supportPath) + 1);
|
||||
}
|
||||
|
||||
sort($files);
|
||||
|
||||
self::assertSame(
|
||||
self::APPROVED_SUPPORT_FILES,
|
||||
$files,
|
||||
'Any new file under Kernel/Support must be a deliberate architectural decision: update the allow list, tests and documentation together.',
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportStaysIndependentFromFeatureModulesAndFrameworks(): void
|
||||
{
|
||||
$this->assertFilesDoNotReferenceFragments(
|
||||
$this->phpFilesUnder('src/Kernel/Support'),
|
||||
array_merge(
|
||||
self::APPLICATION_NAMESPACES,
|
||||
self::INFRASTRUCTURE_NAMESPACES,
|
||||
self::UI_NAMESPACES,
|
||||
self::FRAMEWORK_NAMESPACE_FRAGMENTS,
|
||||
self::HTTP_MESSAGE_DEPENDENCIES,
|
||||
),
|
||||
'Kernel/Support must stay pure, transverse and framework-agnostic',
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportClassesAreFinal(): void
|
||||
{
|
||||
foreach ($this->phpFilesUnder('src/Kernel/Support') as $file) {
|
||||
$code = $this->normalizedCode($file);
|
||||
|
||||
self::assertTrue(
|
||||
str_contains($code, 'finalclass'),
|
||||
$this->fileRuleMessage('Kernel/Support classes must be final to avoid becoming extension points by accident', $file),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user