TenantAtlas/apps/platform/tests/Feature/Filament/Spec350CustomerReviewWorkspaceGuidanceIntegrationTest.php
Ahmed Darrazi 02cc12f73f
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 59s
feat: operator resolution guidance framework v1 (spec 350)
Implemented the first version of the operator resolution guidance framework. Added new foundation classes (ResolutionCase, ResolutionAction) and a ReviewPackOutputResolutionAdapter. Updated the Customer Review Workspace and Environment Review Resource to use the new adapter. Added extensive test coverage for the framework and UI integrations.
2026-06-03 15:36:33 +02:00

131 lines
6.0 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Models\Finding;
use App\Models\ManagedEnvironment;
use App\Models\ReviewPack;
use App\Models\User;
use App\Support\EnvironmentReviewStatus;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
uses(RefreshDatabase::class);
beforeEach(function (): void {
Storage::fake('exports');
});
it('renders the shared resolution case on the customer review workspace decision card', function (): void {
$environment = ManagedEnvironment::factory()->create(['name' => 'Spec350 Workspace Blocked']);
[$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'manager');
$snapshot = seedPartialEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0);
$review = composeEnvironmentReviewForTest($environment, $user, $snapshot);
$summary = array_replace_recursive(is_array($review->summary) ? $review->summary : [], [
'publish_blockers' => ['Operator approval note is still missing.'],
]);
$review->forceFill([
'status' => EnvironmentReviewStatus::Published->value,
'published_at' => now(),
'published_by_user_id' => (int) $user->getKey(),
'summary' => $summary,
])->save();
Storage::disk('exports')->put('review-packs/spec350-workspace-blocked.zip', 'PK-spec350-workspace-blocked');
$pack = ReviewPack::factory()->ready()->create([
'managed_environment_id' => (int) $environment->getKey(),
'workspace_id' => (int) $environment->workspace_id,
'environment_review_id' => (int) $review->getKey(),
'evidence_snapshot_id' => (int) $snapshot->getKey(),
'initiated_by_user_id' => (int) $user->getKey(),
'options' => [
'include_pii' => false,
'include_operations' => true,
],
'file_path' => 'review-packs/spec350-workspace-blocked.zip',
'file_disk' => 'exports',
'generated_at' => now()->subMinutes(3),
]);
$review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save();
$component = spec350WorkspaceComponent($user, $environment)
->assertSee('What is the current review pack output state?')
->assertSee('Output not customer-ready')
->assertSee('Inspect review blockers')
->assertSee('Review blockers are still recorded for this output.');
$payload = $component->instance()->latestReviewConsumptionPayload();
expect(data_get($payload, 'readiness.resolution_case.key'))->toBe('review_output.publication_blocked')
->and(data_get($payload, 'readiness.resolution_case.scope.source_surface'))->toBe(CustomerReviewWorkspace::SOURCE_SURFACE)
->and(data_get($payload, 'readiness.resolution_case.primary_action.key'))->toBe('resolve_review_blockers')
->and(data_get($payload, 'readiness.resolution_case.source_refs'))->toContainEqual(['type' => 'environment_review', 'id' => (int) $review->getKey()])
->and(data_get($payload, 'readiness.resolution_case.source_refs'))->toContainEqual(['type' => 'review_pack', 'id' => (int) $pack->getKey()])
->and(data_get($payload, 'readiness.resolution_case.evidence_refs'))->toHaveCount(1);
});
it('preserves findings follow-up overrides above the shared review-output case', function (): void {
$environment = ManagedEnvironment::factory()->create(['name' => 'Spec350 Workspace Findings']);
[$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'manager');
$snapshot = seedEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0);
$review = composeEnvironmentReviewForTest($environment, $user, $snapshot);
$review->forceFill([
'status' => EnvironmentReviewStatus::Published->value,
'published_at' => now(),
'published_by_user_id' => (int) $user->getKey(),
])->save();
$review = markEnvironmentReviewCustomerSafeReady($review);
Storage::disk('exports')->put('review-packs/spec350-workspace-findings.zip', 'PK-spec350-workspace-findings');
$pack = ReviewPack::factory()->ready()->create([
'managed_environment_id' => (int) $environment->getKey(),
'workspace_id' => (int) $environment->workspace_id,
'environment_review_id' => (int) $review->getKey(),
'evidence_snapshot_id' => (int) $snapshot->getKey(),
'initiated_by_user_id' => (int) $user->getKey(),
'options' => [
'include_pii' => false,
'include_operations' => true,
],
'file_path' => 'review-packs/spec350-workspace-findings.zip',
'file_disk' => 'exports',
'generated_at' => now()->subMinutes(3),
]);
$review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save();
Finding::factory()->create([
'managed_environment_id' => (int) $environment->getKey(),
'workspace_id' => (int) $environment->workspace_id,
'severity' => Finding::SEVERITY_HIGH,
'status' => Finding::STATUS_NEW,
]);
$component = spec350WorkspaceComponent($user, $environment)
->assertSee('Published with limitations')
->assertSee('Keep open findings visible before customer handoff.')
->assertSee('Open review');
$payload = $component->instance()->latestReviewConsumptionPayload();
expect(data_get($payload, 'readiness.resolution_case.key'))->toBe('customer_review_workspace.findings_follow_up_required')
->and(data_get($payload, 'readiness.resolution_case.primary_action.label'))->toBe('Open review')
->and(data_get($payload, 'readiness.output_guidance.label'))->toBe('Customer-safe review pack ready');
});
function spec350WorkspaceComponent(User $user, ManagedEnvironment $environment): mixed
{
session()->put(WorkspaceContext::SESSION_KEY, (int) $environment->workspace_id);
setAdminPanelContext();
return Livewire::actingAs($user)
->test(CustomerReviewWorkspace::class);
}