TenantAtlas/apps/platform/tests/Feature/Guards/UiBloatRegressionGuardTest.php
Ahmed Darrazi 780ed0391a
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m11s
feat(guard): implement ui bloat regression guard
Added UiBloatRegressionGuardTest to enforce known UI bloat and customer/auditor safety regression patterns across configured runtime UI source paths as defined in Spec 375. Registered the test in Pest.php and added to TestLaneManifest.
2026-06-13 11:02:28 +02:00

180 lines
7.8 KiB
PHP

<?php
declare(strict_types=1);
use Tests\Support\TestLaneManifest;
use Tests\Support\UiBloat\UiBloatScanner;
function spec375AllowlistEntry(array $overrides = []): array
{
return array_merge([
'rule_id' => 'UIBLOAT_CUSTOMER_RAW_ID',
'file' => 'apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php',
'pattern' => 'operation id',
'reason' => 'Appears only inside collapsed technical details.',
'surface_type' => 'customer-auditor',
'audience' => 'operator-support',
'review_marker' => 'manual-review-required',
'expires_or_review_after' => '2026-09-01',
'owner_spec' => 'specs/375-ui-bloat-regression-guard',
], $overrides);
}
it('keeps the ui bloat guard in surface-guard heavy-governance ownership', function (): void {
$family = TestLaneManifest::family('ui-bloat-regression-guard');
expect($family['classificationId'])->toBe('surface-guard')
->and($family['targetLaneId'])->toBe('heavy-governance')
->and($family['hotspotFiles'])->toContain('tests/Feature/Guards/UiBloatRegressionGuardTest.php');
});
it('supports report warn and fail strictness semantics', function (): void {
$file = 'apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php';
$source = '<section>Customer review output <p>Operation context</p></section>';
$report = UiBloatScanner::scanSource($file, $source, UiBloatScanner::STRICTNESS_REPORT);
$warn = UiBloatScanner::scanSource($file, $source, UiBloatScanner::STRICTNESS_WARN);
$fail = UiBloatScanner::scanSource(
'apps/platform/app/Filament/Pages/Operations.php',
'<x-filament-panels::page><p>0 alerts</p></x-filament-panels::page>',
UiBloatScanner::STRICTNESS_FAIL,
);
expect($report['blocking_failures'])->toBeEmpty()
->and($warn['blocking_failures'])->not->toBeEmpty()
->and($fail['blocking_failures'])->not->toBeEmpty();
});
it('hard-fails customer raw id labels unless allowlisted', function (): void {
$file = 'apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php';
$source = '<section>Customer review output <p>Operation ID</p></section>';
$result = UiBloatScanner::scanSource($file, $source);
$allowlisted = UiBloatScanner::scanSource($file, $source, UiBloatScanner::STRICTNESS_WARN, [
spec375AllowlistEntry(),
]);
expect($result['blocking_failures'])->toHaveCount(1)
->and($result['blocking_failures'][0]['rule_id'])->toBe('UIBLOAT_CUSTOMER_RAW_ID')
->and($allowlisted['blocking_failures'])->toBeEmpty()
->and($allowlisted['findings'][0]['result'])->toBe('allowlisted');
});
it('hard-fails customer internal provider or debug terms unless allowlisted', function (): void {
$file = 'apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php';
$source = '<section>Customer review output <p>Raw Graph payload</p></section>';
$result = UiBloatScanner::scanSource($file, $source);
$allowlisted = UiBloatScanner::scanSource($file, $source, UiBloatScanner::STRICTNESS_WARN, [
spec375AllowlistEntry([
'rule_id' => 'UIBLOAT_CUSTOMER_INTERNAL_TERM',
'pattern' => 'raw graph payload',
'reason' => 'Fixture proves scoped exception behavior.',
]),
]);
expect($result['blocking_failures'])->toHaveCount(1)
->and($result['blocking_failures'][0]['rule_id'])->toBe('UIBLOAT_CUSTOMER_INTERNAL_TERM')
->and($allowlisted['blocking_failures'])->toBeEmpty();
});
it('keeps zero metrics and repeated status as non-blocking review findings in warn mode', function (): void {
$source = str_repeat('Status ready lifecycle completed. ', 18).'<p>0 findings</p>';
$result = UiBloatScanner::scanSource('apps/platform/app/Filament/Pages/EnvironmentDashboard.php', $source);
expect($result['blocking_failures'])->toBeEmpty()
->and(array_keys($result['summary_by_rule']))->toContain('UIBLOAT_ZERO_METRIC_CARD', 'UIBLOAT_REPEATED_STATUS')
->and($result['summary_by_result'])->toHaveKey('warning')
->and($result['summary_by_result'])->toHaveKey('manual-review-required');
});
it('reports decision hierarchy action overload evidence diagnostic mixing and metadata findings as manual review', function (): void {
$pageSource = <<<'PHP'
<?php
final class ExamplePage
{
protected function getHeaderActions(): array
{
return [
Action::make('one'),
Action::make('two'),
Action::make('three'),
Action::make('four'),
Action::make('five'),
];
}
}
// Evidence diagnostics
PHP;
$pageResult = UiBloatScanner::scanSource('apps/platform/app/Filament/Pages/ExamplePage.php', $pageSource);
$metadataResult = UiBloatScanner::scanSource(
'apps/platform/app/Filament/Resources/ExampleResource.php',
'<?php // Normalization lineage',
);
$ruleIds = array_unique(array_merge(
array_keys($pageResult['summary_by_rule']),
array_keys($metadataResult['summary_by_rule']),
));
expect($ruleIds)->toContain(
'UIBLOAT_MISSING_PRIMARY_QUESTION',
'UIBLOAT_HEADER_ACTION_OVERLOAD',
'UIBLOAT_EVIDENCE_DIAGNOSTICS_MIXED',
'UIBLOAT_TECH_METADATA_MAIN',
)
->and($pageResult['blocking_failures'])->toBeEmpty()
->and($metadataResult['blocking_failures'])->toBeEmpty();
});
it('reports diagnostic guidance and ambiguous entrypoint drift as manual review', function (): void {
$source = <<<'BLADE'
<x-filament-panels::page>
<h1>Diagnostics hub</h1>
<p>Raw payload provider context debug trace operation id diagnostic details.</p>
</x-filament-panels::page>
BLADE;
$result = UiBloatScanner::scanSource('apps/platform/app/Filament/Pages/EnvironmentDiagnostics.php', $source);
expect(array_keys($result['summary_by_rule']))->toContain(
'UIBLOAT_DIAGNOSTIC_GUIDANCE_MISSING',
'UIBLOAT_DIAGNOSTIC_ENTRYPOINT_AMBIGUOUS',
)
->and($result['blocking_failures'])->toBeEmpty();
});
it('validates allowlist entry shape and rejects blanket entries', function (): void {
$errors = UiBloatScanner::validateAllowlist([
[
'rule_id' => 'UIBLOAT_CUSTOMER_RAW_ID',
'file' => 'apps/platform/app/Filament',
],
]);
expect($errors)->not->toBeEmpty()
->and(implode("\n", $errors))->toContain('reason')
->and(implode("\n", $errors))->toContain('forbidden blanket file pattern');
});
it('excludes non-runtime paths from ui findings by default', function (): void {
expect(UiBloatScanner::isRuntimeUiPath('apps/platform/routes/web.php'))->toBeFalse()
->and(UiBloatScanner::isRuntimeUiPath('apps/platform/app/Models/User.php'))->toBeFalse()
->and(UiBloatScanner::isRuntimeUiPath('specs/375-ui-bloat-regression-guard/spec.md'))->toBeFalse()
->and(UiBloatScanner::isRuntimeUiPath('apps/platform/tests/Feature/Guards/UiBloatRegressionGuardTest.php'))->toBeFalse()
->and(UiBloatScanner::isRuntimeUiPath('apps/platform/app/Filament/Pages/ExamplePage.php'))->toBeTrue();
});
it('scans the configured runtime ui paths without unallowlisted customer safety blockers', function (): void {
$result = UiBloatScanner::scanConfiguredPaths(repo_path(), UiBloatScanner::STRICTNESS_WARN);
expect($result['files_scanned'])->toBeGreaterThan(0)
->and($result['config_errors'])->toBeEmpty()
->and($result['blocking_failures'])->toBeEmpty(
"Unexpected customer/auditor blocking UI bloat findings:\n".UiBloatScanner::formatFindings($result['blocking_failures']),
)
->and($result['absent_candidate_paths']['apps/platform/resources/views/components'])->toBe('not available')
->and($result['absent_candidate_paths']['apps/platform/app/View'])->toBe('not available');
});