Files
breadcrumb-the-shire/tests/Architecture/ProjectFileAssertionSupport.php
fs f403a6704f feat(tests): automate 5 remaining guards as contract tests
Extract findPatternMatchesIn*Files() to ProjectFileAssertionSupport
trait for reuse. Add contract tests for:
- GR-SEC-005: Encryption centralized in Crypto.php
- GR-SEC-006: File storage in storage/, not web/
- GR-SEC-002: No PII in error_log() calls
- GR-CORE-012: POST-Redirect-GET pattern enforcement
- GR-UI-015: i18n key completeness de ↔ en

Brings automated guard coverage from 24 to 29 test files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 21:20:08 +01:00

69 lines
2.0 KiB
PHP

<?php
namespace MintyPHP\Tests\Architecture;
trait ProjectFileAssertionSupport
{
private function projectRootPath(): string
{
$root = realpath(__DIR__ . '/../..');
$this->assertNotFalse($root, 'Project root not found.');
return $root;
}
private function readProjectFile(string $path): string
{
$root = $this->projectRootPath();
$fullPath = $root . '/' . $path;
$this->assertFileExists($fullPath, 'File not found: ' . $path);
$content = file_get_contents($fullPath);
$this->assertNotFalse($content, 'Could not read file: ' . $path);
return $content;
}
/**
* @return list<string>
*/
private function findPatternMatchesInPhpFiles(string $relativeDirectory, string $pattern): array
{
return $this->findPatternMatchesInFiles($relativeDirectory, $pattern, ['php']);
}
/**
* @param list<string> $extensions
* @return list<string>
*/
private function findPatternMatchesInFiles(string $relativeDirectory, string $pattern, array $extensions): array
{
$root = $this->projectRootPath();
$basePath = $root . '/' . $relativeDirectory;
$this->assertDirectoryExists($basePath, 'Directory not found: ' . $relativeDirectory);
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($basePath));
$violations = [];
/** @var \SplFileInfo $file */
foreach ($iterator as $file) {
if (!$file->isFile() || !in_array($file->getExtension(), $extensions, true)) {
continue;
}
$content = file_get_contents($file->getPathname());
$this->assertNotFalse($content, 'Could not read file: ' . $file->getPathname());
if (!preg_match($pattern, $content)) {
continue;
}
$relativePath = str_replace($root . '/', '', $file->getPathname());
$violations[] = $relativePath;
}
sort($violations);
return $violations;
}
}