test: add architecture contract tests for layering, sessions, and asset versioning
New contracts enforce repository layer isolation, no HTML in services, no DB calls in views, module session key prefixes, and asset versioning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
64
tests/Architecture/ModuleSessionKeyPrefixContractTest.php
Normal file
64
tests/Architecture/ModuleSessionKeyPrefixContractTest.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Tests\Architecture;
|
||||
|
||||
/**
|
||||
* Module code must prefix session keys with "module.<id>." to prevent
|
||||
* collisions between modules and with core session state.
|
||||
*/
|
||||
final class ModuleSessionKeyPrefixContractTest extends AbstractModuleStructureContractTestCase
|
||||
{
|
||||
/**
|
||||
* Pattern matches direct $_SESSION access with a string key that does NOT
|
||||
* start with "module.".
|
||||
*/
|
||||
private const SESSION_ACCESS_PATTERN = '/\$_SESSION\s*\[\s*[\'"](?!module\.)/';
|
||||
|
||||
public function testModulePhpFilesUseSessionPrefix(): void
|
||||
{
|
||||
$modulesDir = realpath(__DIR__ . '/../../modules');
|
||||
self::assertNotFalse($modulesDir);
|
||||
|
||||
$violations = [];
|
||||
|
||||
foreach (self::$modules as $module) {
|
||||
$moduleId = $module['id'];
|
||||
|
||||
foreach (['lib', 'pages'] as $subdir) {
|
||||
$dir = $module['path'] . '/' . $subdir;
|
||||
if (!is_dir($dir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
/** @var \SplFileInfo $file */
|
||||
$ext = $file->getExtension();
|
||||
if ($ext !== 'php' && $ext !== 'phtml') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = file_get_contents($file->getPathname());
|
||||
if ($content === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match(self::SESSION_ACCESS_PATTERN, $content)) {
|
||||
$relativePath = 'modules/' . $moduleId . '/' . $subdir . '/' . str_replace($dir . '/', '', $file->getPathname());
|
||||
$violations[] = $relativePath . " (module '{$moduleId}') — session keys must start with 'module.{$moduleId}.'";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self::assertSame(
|
||||
[],
|
||||
$violations,
|
||||
"Module session keys must be prefixed with 'module.<id>.':\n" . implode("\n", $violations)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user