178 lines
6.6 KiB
PHP
178 lines
6.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Pages\Operations\TenantlessOperationRunViewer;
|
|
use App\Models\OperationRun;
|
|
use App\Models\Tenant;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Filament\Facades\Filament;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Features\SupportTesting\Testable;
|
|
use Livewire\Livewire;
|
|
use Tests\Feature\Concerns\BuildsGovernanceArtifactTruthFixtures;
|
|
use Tests\TestCase;
|
|
|
|
uses(RefreshDatabase::class, BuildsGovernanceArtifactTruthFixtures::class);
|
|
|
|
function governanceVisibleText(Testable $component): string
|
|
{
|
|
$html = $component->html();
|
|
$html = preg_replace('/<script\b[^>]*>.*?<\/script>/is', '', $html) ?? $html;
|
|
$html = preg_replace('/<style\b[^>]*>.*?<\/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');
|
|
});
|