Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 4m44s
Added BaselineReadinessGate, resolution propagation, and disclosure semantics logic per Spec 385. Integrated baseline unreadiness into Customer Review Workspace and Review Packs.
162 lines
5.7 KiB
PHP
162 lines
5.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\ReviewPack;
|
|
use App\Models\User;
|
|
use App\Support\Baselines\CompareSemantics\CompareResultReason;
|
|
use App\Support\EnvironmentReviewStatus;
|
|
use App\Support\OperationRunOutcome;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
pest()->browser()->timeout(60_000);
|
|
|
|
beforeEach(function (): void {
|
|
Storage::fake('exports');
|
|
});
|
|
|
|
it('Spec385 smokes baseline readiness blockers on the customer review workspace', function (): void {
|
|
$environment = ManagedEnvironment::factory()->create(['name' => 'Spec385 Browser Baseline']);
|
|
[$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'manager');
|
|
[$profile, $baselineSnapshot] = seedActiveBaselineForTenant($environment);
|
|
|
|
seedBaselineCompareRun(
|
|
tenant: $environment,
|
|
profile: $profile,
|
|
snapshot: $baselineSnapshot,
|
|
compareContext: spec385BrowserCompareContext([CompareResultReason::UnresolvedAmbiguousIdentity]),
|
|
outcome: OperationRunOutcome::PartiallySucceeded->value,
|
|
);
|
|
|
|
$snapshot = seedEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0);
|
|
$review = composeEnvironmentReviewForTest($environment, $user, $snapshot);
|
|
$filePath = 'review-packs/spec385-baseline-readiness.zip';
|
|
|
|
Storage::disk('exports')->put($filePath, 'PK-spec385-browser');
|
|
|
|
$review->forceFill([
|
|
'status' => EnvironmentReviewStatus::Published->value,
|
|
'published_at' => now(),
|
|
'published_by_user_id' => (int) $user->getKey(),
|
|
])->save();
|
|
|
|
$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' => $filePath,
|
|
'file_disk' => 'exports',
|
|
'generated_at' => now(),
|
|
]);
|
|
$review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save();
|
|
|
|
spec385AuthenticateBrowser($this, $user, $environment);
|
|
|
|
$page = visit(CustomerReviewWorkspace::environmentFilterUrl($environment))
|
|
->resize(1366, 920)
|
|
->waitForText('Output not customer-ready')
|
|
->assertSee('Review blockers are still recorded for this output.')
|
|
->assertScript('document.querySelector("[data-testid=\"customer-review-output-limitations\"]")?.open === false', true)
|
|
->click('[data-testid="customer-review-output-limitations"] summary')
|
|
->assertSee('Baseline readiness blocked')
|
|
->assertSee('Open baseline resolution')
|
|
->assertDontSee('baseline_identity_unresolved')
|
|
->assertDontSee('provider_resource_id')
|
|
->assertDontSee('canonical_subject_key')
|
|
->assertDontSee('internal_diagnostics')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
|
|
$page->screenshot(true, spec385BrowserScreenshotName('01-baseline-readiness-blocked'));
|
|
spec385CopyBrowserScreenshot('01-baseline-readiness-blocked');
|
|
});
|
|
|
|
function spec385AuthenticateBrowser(mixed $test, User $user, ManagedEnvironment $environment): void
|
|
{
|
|
$workspaceId = (int) $environment->workspace_id;
|
|
|
|
$test->actingAs($user)->withSession([
|
|
WorkspaceContext::SESSION_KEY => $workspaceId,
|
|
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
|
|
(string) $workspaceId => (int) $environment->getKey(),
|
|
],
|
|
]);
|
|
|
|
session()->put(WorkspaceContext::SESSION_KEY, $workspaceId);
|
|
session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
|
|
(string) $workspaceId => (int) $environment->getKey(),
|
|
]);
|
|
|
|
setAdminPanelContext($environment);
|
|
}
|
|
|
|
/**
|
|
* @param list<CompareResultReason> $reasons
|
|
* @return array<string, mixed>
|
|
*/
|
|
function spec385BrowserCompareContext(array $reasons): array
|
|
{
|
|
$byReason = [];
|
|
$byReadinessImpact = [];
|
|
|
|
foreach ($reasons as $reason) {
|
|
$byReason[$reason->value] = ($byReason[$reason->value] ?? 0) + 1;
|
|
|
|
$impact = $reason->readinessImpact()->value;
|
|
$byReadinessImpact[$impact] = ($byReadinessImpact[$impact] ?? 0) + 1;
|
|
}
|
|
|
|
return [
|
|
'result_semantics' => [
|
|
'version' => 'compare_semantics.v1',
|
|
'run_outcome' => 'partial',
|
|
'operation_outcome' => OperationRunOutcome::PartiallySucceeded->value,
|
|
'counts' => [
|
|
'by_reason' => $byReason,
|
|
'by_readiness_impact' => $byReadinessImpact,
|
|
],
|
|
],
|
|
];
|
|
}
|
|
|
|
function spec385BrowserScreenshotName(string $name): string
|
|
{
|
|
return 'spec385-evidence-review-readiness-'.$name;
|
|
}
|
|
|
|
function spec385CopyBrowserScreenshot(string $name): void
|
|
{
|
|
$filename = spec385BrowserScreenshotName($name).'.png';
|
|
$source = base_path('tests/Browser/Screenshots/'.$filename);
|
|
$targetDirectory = repo_path('specs/385-evidence-review-readiness/artifacts/screenshots');
|
|
|
|
if (! is_dir($targetDirectory)) {
|
|
@mkdir($targetDirectory, 0755, true);
|
|
}
|
|
|
|
if (! is_file($source)) {
|
|
$source = \Pest\Browser\Support\Screenshot::path($filename);
|
|
}
|
|
|
|
for ($attempt = 0; $attempt < 10 && ! is_file($source); $attempt++) {
|
|
usleep(100_000);
|
|
clearstatcache(true, $source);
|
|
}
|
|
|
|
if (is_file($source) && is_dir($targetDirectory) && is_writable($targetDirectory)) {
|
|
@copy($source, $targetDirectory.DIRECTORY_SEPARATOR.$name.'.png');
|
|
}
|
|
}
|