1
0
Files
breadcrumb-the-shire/tests/Architecture/AssetVersioningContractTest.php
fs be8bf496cb 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>
2026-03-22 14:15:41 +01:00

75 lines
2.5 KiB
PHP

<?php
namespace MintyPHP\Tests\Architecture;
use PHPUnit\Framework\TestCase;
/**
* All CSS and JS asset references in templates and views must use
* assetVersion() for cache-busting. Bare paths without assetVersion()
* risk serving stale cached assets after deploys.
*
* Excluded: inline scripts, data URIs, external CDN URLs, and empty src attributes.
*/
class AssetVersioningContractTest extends TestCase
{
use ProjectFileAssertionSupport;
/**
* Matches src="..." or href="..." pointing to local .js/.css files
* that are NOT wrapped in assetVersion().
*
* The negative lookbehind ensures we don't flag assetVersion() usages.
* Excludes external URLs (http://, https://, //) and empty attributes.
*/
private const BARE_JS_PATTERN = '/src=["\'](?!https?:\/\/|\/\/)(?!<?php\s+e\(assetVersion)[^"\']*\.js["\']/';
private const BARE_CSS_PATTERN = '/href=["\'](?!https?:\/\/|\/\/)(?!<?php\s+e\(assetVersion)[^"\']*\.css["\']/';
public function testTemplateAssetReferencesUseAssetVersion(): void
{
$this->assertAssetVersionUsed('templates');
}
public function testCorePageAssetReferencesUseAssetVersion(): void
{
$this->assertAssetVersionUsed('pages');
}
public function testModulePageAssetReferencesUseAssetVersion(): void
{
$root = $this->projectRootPath();
$modulesDir = $root . '/modules';
if (!is_dir($modulesDir)) {
self::markTestSkipped('modules/ directory missing.');
}
foreach (scandir($modulesDir) ?: [] as $entry) {
if ($entry === '.' || $entry === '..' || !is_dir($modulesDir . '/' . $entry)) {
continue;
}
foreach (['pages', 'templates'] as $subdir) {
$rel = 'modules/' . $entry . '/' . $subdir;
if (is_dir($root . '/' . $rel)) {
$this->assertAssetVersionUsed($rel);
}
}
}
}
private function assertAssetVersionUsed(string $relativeDirectory): void
{
$jsViolations = $this->findPatternMatchesInFiles($relativeDirectory, self::BARE_JS_PATTERN, ['phtml']);
$cssViolations = $this->findPatternMatchesInFiles($relativeDirectory, self::BARE_CSS_PATTERN, ['phtml']);
$violations = array_unique(array_merge($jsViolations, $cssViolations));
sort($violations);
self::assertSame(
[],
$violations,
"Asset references must use assetVersion() for cache-busting. Violations:\n" . implode("\n", $violations)
);
}
}