html(); $html = preg_replace('/]*>.*?<\/script>/is', '', $html) ?? $html; $html = preg_replace('/]*>.*?<\/style>/is', '', $html) ?? $html; $html = preg_replace('/\s+wire:snapshot="[^"]*"/', '', $html) ?? $html; $html = preg_replace('/\s+wire:effects="[^"]*"/', '', $html) ?? $html; return trim((string) preg_replace('/\s+/', ' ', strip_tags($html))); } function governanceRunViewer(TestCase $testCase, $user, Tenant $tenant, OperationRun $run): Testable { Filament::setTenant(null, true); $testCase->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]); session([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]); return Livewire::actingAs($user) ->test(TenantlessOperationRunViewer::class, ['run' => $run]); } it('renders a summary-first hierarchy for zero-output baseline compare runs', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner'); $run = OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'baseline_compare', 'status' => 'completed', 'outcome' => 'partially_succeeded', 'context' => [ 'baseline_compare' => [ 'reason_code' => 'coverage_unproven', 'coverage' => [ 'proof' => false, ], ], ], 'summary_counts' => [ 'total' => 0, 'processed' => 0, 'errors_recorded' => 1, ], 'completed_at' => now(), ]); $component = governanceRunViewer($this, $user, $tenant, $run) ->assertSee('Decision') ->assertSee('Artifact impact') ->assertSee('Dominant cause') ->assertSee('Primary next step') ->assertSee('The compare finished, but no decision-grade result is available yet.') ->assertSee('Artifact truth details') ->assertSee('Monitoring detail'); $pageText = governanceVisibleText($component); expect(mb_strpos($pageText, 'Decision'))->toBeLessThan(mb_strpos($pageText, 'Artifact truth details')) ->and(mb_strpos($pageText, 'Decision'))->toBeLessThan(mb_strpos($pageText, 'Monitoring detail')) ->and($pageText)->toContain('no decision-grade result is available yet'); }); it('keeps blocked baseline capture summaries ahead of diagnostics without adding new run-detail actions', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner'); $run = OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'baseline_capture', 'status' => 'completed', 'outcome' => 'blocked', 'context' => [ 'reason_code' => 'missing_capability', 'baseline_capture' => [ 'subjects_total' => 0, 'gaps' => [ 'count' => 0, ], ], ], 'failure_summary' => [[ 'reason_code' => 'missing_capability', 'message' => 'A required capability is missing for this run.', ]], 'completed_at' => now(), ]); $component = governanceRunViewer($this, $user, $tenant, $run) ->assertActionVisible('operate_hub_back_to_operations') ->assertActionVisible('refresh') ->assertSee('Blocked by prerequisite') ->assertSee('No baseline was captured') ->assertSee('Artifact impact') ->assertSee('Dominant cause'); $pageText = governanceVisibleText($component); expect(mb_substr_count($pageText, 'No baseline was captured'))->toBe(1) ->and(mb_strpos($pageText, 'No baseline was captured'))->toBeLessThan(mb_strpos($pageText, 'Artifact truth details')); }); it('shows processing outcome separately from artifact impact for stale evidence snapshot runs', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner'); $run = $this->makeArtifactTruthRun($tenant, 'tenant.evidence.snapshot.generate'); $this->makeStaleArtifactTruthEvidenceSnapshot( tenant: $tenant, snapshotOverrides: [ 'operation_run_id' => (int) $run->getKey(), ], ); governanceRunViewer($this, $user, $tenant, $run) ->assertSee('Outcome') ->assertSee('Artifact impact') ->assertSee('Completed successfully') ->assertSee('The snapshot finished processing, but its evidence basis is already stale.') ->assertSee('Result trust'); }); it('preserves a dominant cause plus secondary causes for degraded review composition runs', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner'); $run = $this->makeArtifactTruthRun($tenant, 'tenant.review.compose'); $snapshot = $this->makeStaleArtifactTruthEvidenceSnapshot($tenant); $this->makeArtifactTruthReview( tenant: $tenant, user: $user, snapshot: $snapshot, reviewOverrides: [ 'operation_run_id' => (int) $run->getKey(), 'completeness_state' => 'partial', ], summaryOverrides: [ 'section_state_counts' => [ 'complete' => 4, 'partial' => 1, 'missing' => 1, 'stale' => 0, ], ], ); $component = governanceRunViewer($this, $user, $tenant, $run) ->assertSee('Dominant cause') ->assertSee('Missing sections') ->assertSee('Secondary causes') ->assertSee('Stale evidence basis'); $pageText = governanceVisibleText($component); expect(mb_strpos($pageText, 'Missing sections'))->toBeLessThan(mb_strpos($pageText, 'Secondary causes')) ->and($pageText)->toContain('stale evidence'); });