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

158 lines
6.6 KiB
PHP
Raw Permalink Normal View History

2026-03-04 15:56:58 +01:00
<?php
namespace MintyPHP\Tests\Architecture;
use PHPUnit\Framework\TestCase;
class CoreStarterkitContractTest extends TestCase
{
use ProjectFileAssertionSupport;
public function testPagesDoNotInstantiateServicesRepositoriesOrGatewaysDirectly(): void
{
$violations = $this->findPatternMatchesInPhpFiles('pages', '/\bnew\s+[\\\\A-Za-z0-9_]+(?:Service|Gateway|Repository)\s*\(/');
$this->assertSame([], $violations, "Direct service/repository/gateway instantiation found in pages/:\n" . implode("\n", $violations));
}
public function testPagesDoNotUseDatabaseFacadeDirectly(): void
{
$violations = $this->findPatternMatchesInPhpFiles('pages', '/\bDB::/');
$this->assertSame([], $violations, "Direct DB facade usage found in pages/:\n" . implode("\n", $violations));
}
public function testAdminPagesDoNotUseFactoryCreateChains(): void
{
$violations = $this->findPatternMatchesInPhpFiles('pages/admin', '/app\([^\n]*Factory::class\)->create/');
$this->assertSame([], $violations, "Factory create-chain usage found in pages/admin/:\n" . implode("\n", $violations));
}
public function testAdminPagesDoNotReferenceFactoryClasses(): void
{
$violations = $this->findPatternMatchesInPhpFiles('pages/admin', '/Factory::class/');
$this->assertSame([], $violations, "Factory class usage found in pages/admin/:\n" . implode("\n", $violations));
}
public function testPagesUseRequestInputInsteadOfSuperglobals(): void
{
$patterns = [
'/\$_POST/' => '$_POST',
'/\$_GET/' => '$_GET',
'/\$_FILES/' => '$_FILES',
'/REQUEST_METHOD/' => 'REQUEST_METHOD',
2026-03-06 00:44:52 +01:00
'/\$_SESSION/' => '$_SESSION',
'/\$_SERVER/' => '$_SERVER',
'/\$_COOKIE/' => '$_COOKIE',
2026-03-04 15:56:58 +01:00
];
foreach ($patterns as $pattern => $label) {
$violations = $this->findPatternMatchesInPhpFiles('pages', $pattern);
$this->assertSame([], $violations, "Superglobal {$label} usage found in pages/:\n" . implode("\n", $violations));
}
}
2026-03-06 00:44:52 +01:00
public function testServicesDoNotUseSuperglobals(): void
2026-03-04 15:56:58 +01:00
{
2026-03-06 00:44:52 +01:00
$patterns = [
'/\$_POST/' => '$_POST',
'/\$_GET/' => '$_GET',
'/\$_FILES/' => '$_FILES',
'/\$_SERVER/' => '$_SERVER',
'/\$_COOKIE/' => '$_COOKIE',
'/\$_SESSION/' => '$_SESSION',
'/\$_REQUEST/' => '$_REQUEST',
];
foreach ($patterns as $pattern => $label) {
$violations = $this->findPatternMatchesInPhpFiles('core/Service', $pattern);
$this->assertSame([], $violations, "Superglobal {$label} usage found in core/Service/:\n" . implode("\n", $violations));
2026-03-06 00:44:52 +01:00
}
2026-03-04 15:56:58 +01:00
}
2026-03-06 00:44:52 +01:00
public function testApiPagesDoNotReadJsonBodyDirectly(): void
2026-03-05 08:26:51 +01:00
{
2026-03-06 00:44:52 +01:00
$violations = $this->findPatternMatchesInPhpFiles('pages/api/v1', '/ApiResponse::readJsonBody\s*\(/');
$this->assertSame([], $violations, "ApiResponse::readJsonBody usage found in pages/api/v1/:\n" . implode("\n", $violations));
2026-03-05 08:26:51 +01:00
}
public function testTemplatesDoNotUseLegacyFilterToggleMarkup(): void
{
$pattern = '/data-(?:toolbar-toggle|filter-overflow|filter-toggle)/';
$violations = array_merge(
$this->findPatternMatchesInFiles('templates', $pattern, ['phtml']),
$this->findPatternMatchesInFiles('pages', $pattern, ['phtml'])
);
sort($violations);
$this->assertSame([], $violations, "Legacy filter toggle markup found in templates/pages:\n" . implode("\n", $violations));
}
public function testPagesAndTemplatesDoNotUseInlineModuleScripts(): void
{
$pattern = '/<script\b(?=[^>]*\btype=["\']module["\'])(?![^>]*\bsrc=)[^>]*>/i';
$violations = array_merge(
$this->findPatternMatchesInFiles('templates', $pattern, ['phtml']),
$this->findPatternMatchesInFiles('pages', $pattern, ['phtml'])
);
sort($violations);
$this->assertSame([], $violations, "Inline module scripts found in templates/pages:\n" . implode("\n", $violations));
}
public function testPagesAndTemplatesUseAssetVersionForJsUrls(): void
{
$pattern = '/asset\(\s*[\'"][^\'"]+\.js/i';
$violations = array_merge(
$this->findPatternMatchesInFiles('templates', $pattern, ['phtml']),
$this->findPatternMatchesInFiles('pages', $pattern, ['phtml'])
);
sort($violations);
$this->assertSame([], $violations, "asset(...) JS URLs found in templates/pages:\n" . implode("\n", $violations));
}
2026-03-13 14:38:58 +01:00
public function testTemplatesDoNotUseDatabaseFacadeDirectly(): void
{
$violations = $this->findPatternMatchesInFiles('templates', '/\bDB::/', ['phtml']);
$this->assertSame([], $violations, "Direct DB facade usage found in templates/:\n" . implode("\n", $violations));
}
public function testTemplatesDoNotResolveServiceGatewayOrRepositoryViaDI(): void
{
$violations = $this->findPatternMatchesInFiles(
'templates',
'/app\(\s*[\\\\A-Za-z0-9_]*(?:Service|Gateway|Repository)::class\s*\)/',
['phtml']
);
$this->assertSame([], $violations, "DI resolution of Service/Gateway/Repository found in templates/:\n" . implode("\n", $violations));
}
2026-03-06 00:44:52 +01:00
public function testNoLegacySettingsGatewayOrServiceReferencesExist(): void
{
$patterns = [
'/\bSettingService::class\b/' => 'SettingService::class',
'/\bSettingGateway::class\b/' => 'SettingGateway::class',
'/\bnew\s+SettingService\s*\(/' => 'new SettingService(...)',
'/\bnew\s+SettingGateway\s*\(/' => 'new SettingGateway(...)',
'/use\s+[^;]*\\\\SettingService;/' => 'use ...\\SettingService',
'/use\s+[^;]*\\\\SettingGateway;/' => 'use ...\\SettingGateway',
];
foreach ($patterns as $pattern => $label) {
$violations = array_merge(
$this->findPatternMatchesInPhpFiles('core', $pattern),
2026-03-06 00:44:52 +01:00
$this->findPatternMatchesInPhpFiles('pages', $pattern),
$this->findPatternMatchesInPhpFiles('tests', $pattern),
);
$violations = array_values(array_filter(
$violations,
static fn (string $path): bool => $path !== 'tests/Architecture/CoreStarterkitContractTest.php'
));
$violations = array_values(array_unique($violations));
sort($violations);
$this->assertSame([], $violations, "Legacy settings reference {$label} found:\n" . implode("\n", $violations));
}
}
2026-03-04 15:56:58 +01:00
}