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

75 lines
2.5 KiB
PHP
Raw Normal View History

<?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)
);
}
}