*/ private function taxonomyEnumFiles(): array { return [ 'lib/Domain/Taxonomy/SystemAuditOutcome.php', 'lib/Domain/Taxonomy/SystemAuditChannel.php', 'lib/Domain/Taxonomy/UserLifecycleAction.php', 'lib/Domain/Taxonomy/UserLifecycleTriggerType.php', 'lib/Domain/Taxonomy/UserLifecycleStatus.php', 'lib/Domain/Taxonomy/ImportAuditStatus.php', 'lib/Domain/Taxonomy/ScheduledJobStatus.php', 'lib/Domain/Taxonomy/ScheduledJobRunStatus.php', 'lib/Domain/Taxonomy/ScheduledJobTriggerType.php', 'lib/Domain/Taxonomy/MailLogStatus.php', 'lib/Domain/Taxonomy/TenantStatus.php', 'lib/Domain/Taxonomy/SchedulerRuntimeResult.php', ]; } /** * @return array> */ private function taxonomySchemaExpectations(): array { return [ 'pages/admin/system-audit/filter-schema.php' => [ 'SystemAuditOutcome::values()', 'SystemAuditChannel::values()', ], 'pages/admin/user-lifecycle-audit/filter-schema.php' => [ 'gridEnumSanitizer(UserLifecycleAction::class)', 'gridEnumSanitizer(UserLifecycleStatus::class)', 'gridEnumSanitizer(UserLifecycleTriggerType::class)', ], 'pages/admin/import-audit/filter-schema.php' => [ 'ImportAuditStatus::values()', ], 'pages/admin/scheduled-jobs/filter-schema.php' => [ 'ScheduledJobStatus::values()', ], 'pages/admin/scheduled-jobs/runs-filter-schema.php' => [ 'ScheduledJobRunStatus::values()', 'ScheduledJobTriggerType::values()', ], 'pages/admin/mail-log/filter-schema.php' => [ 'MailLogStatus::values()', ], ]; } /** * @return list */ private function taxonomyDataEndpointFiles(): array { return [ 'pages/admin/system-audit/data().php', 'pages/admin/user-lifecycle-audit/data().php', 'pages/admin/import-audit/data().php', 'pages/admin/scheduled-jobs/data().php', 'pages/admin/scheduled-jobs/runs-data($id).php', 'pages/admin/mail-log/data().php', 'pages/admin/tenants/data().php', ]; } /** * @return list */ private function taxonomyLiteralGuardFiles(): array { return [ 'lib/Service/Audit/SystemAuditService.php', 'lib/Repository/Audit/SystemAuditLogRepository.php', 'lib/Http/ApiSystemAuditReporter.php', 'lib/Service/Audit/UserLifecycleAuditService.php', 'lib/Repository/Audit/UserLifecycleAuditRepository.php', 'lib/Service/Audit/ImportAuditService.php', 'lib/Repository/Audit/ImportAuditRunRepository.php', 'lib/Service/Scheduler/SchedulerRunService.php', 'lib/Repository/Scheduler/ScheduledJobRepository.php', 'lib/Repository/Scheduler/ScheduledJobRunRepository.php', 'lib/Repository/Scheduler/SchedulerRuntimeRepository.php', 'lib/Service/Mail/MailService.php', 'lib/Repository/Mail/MailLogRepository.php', 'lib/Service/Tenant/TenantService.php', 'lib/Repository/Tenant/TenantRepository.php', 'lib/Repository/Stats/AdminStatsRepository.php', 'pages/admin/system-audit/data().php', 'pages/admin/user-lifecycle-audit/data().php', 'pages/admin/import-audit/data().php', 'pages/admin/scheduled-jobs/data().php', 'pages/admin/scheduled-jobs/runs-data($id).php', 'pages/admin/mail-log/data().php', 'pages/admin/tenants/data().php', 'pages/admin/system-audit/index().php', 'pages/admin/user-lifecycle-audit/index().php', 'pages/admin/import-audit/index().php', 'pages/admin/scheduled-jobs/index().php', 'pages/admin/mail-log/index().php', ]; } public function testTaxonomyEnumFilesUseSharedTraitAndRequiredMethods(): void { foreach ($this->taxonomyEnumFiles() as $file) { $content = $this->readProjectFile($file); $this->assertStringContainsString('enum ', $content, $file); $this->assertStringContainsString('use SupportsStringTaxonomy;', $content, $file); $this->assertStringContainsString('function labelToken()', $content, $file); $this->assertStringContainsString('function badgeVariant()', $content, $file); } } public function testFilterSchemasReadTaxonomyValuesFromEnums(): void { foreach ($this->taxonomySchemaExpectations() as $file => $snippets) { $content = $this->readProjectFile($file); foreach ($snippets as $snippet) { $this->assertStringContainsString($snippet, $content, $file); } } } public function testDataEndpointsUseEnumBasedBadgeAndLabelResolution(): void { foreach ($this->taxonomyDataEndpointFiles() as $file) { $content = $this->readProjectFile($file); $this->assertStringContainsString('->badgeVariant()', $content, $file); $this->assertStringContainsString('->labelToken()', $content, $file); } } public function testNoLegacyLiteralTaxonomyChecksRemainInMigratedFiles(): void { $forbiddenPatterns = [ "/\\bstatus\\s*=\\s*'(running|success|partial|failed|skipped|queued|sent|active|inactive)'/", "/\\boutcome\\s*=\\s*'(success|failed|denied)'/", "/\\bchannel\\s*=\\s*'(web|api|scheduler|cli)'/", "/\\btrigger_type\\s*=\\s*'(scheduler|manual|cron|system)'/", "/\\baction\\s*=\\s*'(deactivate|delete|restore)'/", "/['\\\"]statuses['\\\"]\\s*=>\\s*'failed,skipped'/", "/['\\\"]actions['\\\"]\\s*=>\\s*'restore'/", "/in_array\\([^\\n]*\\[(?:[^\\]]*'(?:success|failed|denied|running|partial|skipped|queued|sent|active|inactive|scheduler|manual|web|api|cli|deactivate|delete|restore|ok|lock_not_acquired|unexpected_error)')/", ]; foreach ($this->taxonomyLiteralGuardFiles() as $file) { $content = $this->readProjectFile($file); foreach ($forbiddenPatterns as $pattern) { $this->assertSame(0, preg_match($pattern, $content), $file . ' pattern=' . $pattern); } } } public function testImportAuditIndexTemplateDoesNotUseLegacyStatusMapper(): void { $content = $this->readProjectFile('pages/admin/import-audit/index(default).phtml'); $moduleContent = $this->readProjectFile('web/js/pages/admin-import-audit-index.js'); $this->assertStringNotContainsString('const statusLabel = (value) =>', $moduleContent); $this->assertStringNotContainsString("if (key === 'running')", $moduleContent); $this->assertStringContainsString('cell.label || \'-\'', $moduleContent); $this->assertStringContainsString("assetVersion('js/pages/admin-import-audit-index.js')", $content); } }