browser()->timeout(60_000); beforeEach(function (): void { Storage::fake('exports'); }); it('Spec326 smokes clean customer review workspace entry', function (): void { [$user, $environmentA, $environmentB] = spec326CustomerReviewWorkspaceFixture(); spec326AuthenticateCustomerReviewWorkspaceBrowser($this, $user, $environmentA); visit(CustomerReviewWorkspace::getUrl(panel: 'admin')) ->waitForText('Customer-safe review packages') ->assertDontSee('No environment selected') ->assertDontSee('Environment filter:') ->assertSee('What is the current review pack output state?') ->assertSee('Evidence path') ->assertSee('Review pack state') ->assertSee('Accepted risks') ->assertSee('Disclosure rule') ->assertSee('Diagnostics') ->assertSee('Collapsed') ->assertSee('Raw/support') ->assertSee('Review package index') ->assertSee('Decision trail') ->assertSee('Customer-safe follow-ups') ->assertScript('(() => { const decision = document.querySelector("[data-testid=\"customer-review-decision-card\"]"); const aside = document.querySelector("[data-testid=\"customer-review-evidence-aside\"]"); if (! decision || ! aside) { return false; } const decisionBox = decision.getBoundingClientRect(); const asideBox = aside.getBoundingClientRect(); return window.innerWidth < 768 || asideBox.left > decisionBox.left; })()', true) ->assertSee($environmentB->name) ->assertDontSee('entitled tenant') ->assertDontSee('tenant filter') ->assertDontSee('raw payload should stay hidden') ->assertDontSee('stack trace should stay hidden') ->assertDontSee('provider secret should stay hidden') ->assertDontSee('debug metadata should stay hidden') ->assertDontSee('source fingerprint should stay hidden') ->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === false', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--clean')); }); it('Spec326 smokes filtered customer review workspace clear and reload behavior', function (): void { [$user, $environmentA, $environmentB] = spec326CustomerReviewWorkspaceFixture(); $cleanPath = json_encode((string) parse_url(CustomerReviewWorkspace::getUrl(panel: 'admin'), PHP_URL_PATH), JSON_THROW_ON_ERROR); spec326AuthenticateCustomerReviewWorkspaceBrowser($this, $user, $environmentA); $page = visit(CustomerReviewWorkspace::environmentFilterUrl($environmentA)) ->waitForText('Environment filter:') ->assertSee($environmentA->name) ->assertDontSee($environmentB->name) ->assertSee('Environment filter: '.$environmentA->name) ->assertSee('What is the current review pack output state?') ->assertSee('Evidence path') ->assertSee('Review package index') ->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === false', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--filtered')); $page ->click('[data-testid="workspace-hub-environment-filter-clear"]') ->waitForText($environmentB->name) ->assertDontSee('Environment filter:') ->assertSee($environmentB->name) ->assertScript("window.location.pathname === {$cleanPath}", true) ->assertScript('! window.location.search.includes("environment_id=")', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--after-clear')); $page->script('window.location.reload();'); $page ->waitForText($environmentB->name) ->assertDontSee('Environment filter:') ->assertSee($environmentB->name) ->assertScript("window.location.pathname === {$cleanPath}", true) ->assertScript('! window.location.search.includes("environment_id=")', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--after-reload')); }); it('Spec326 smokes customer-safe diagnostics disclosure', function (): void { [$user, $environmentA] = spec326CustomerReviewWorkspaceFixture(); spec326AuthenticateCustomerReviewWorkspaceBrowser($this, $user, $environmentA); visit(CustomerReviewWorkspace::getUrl(panel: 'admin')) ->waitForText('Diagnostics') ->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === false', true) ->click('[data-testid="customer-review-diagnostics"] summary') ->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === true', true) ->assertSee('Support details stay on authorized diagnostic surfaces') ->assertDontSee('raw payload should stay hidden') ->assertDontSee('internal exception should stay hidden') ->assertDontSee('source fingerprint should stay hidden') ->assertNoJavaScriptErrors() ->assertNoConsoleLogs() ->screenshot(true, spec326CustomerReviewWorkspaceScreenshot('customer-review-workspace--diagnostics')); }); /** * @return array{0: User, 1: ManagedEnvironment, 2: ManagedEnvironment} */ function spec326CustomerReviewWorkspaceFixture(): array { $environmentA = ManagedEnvironment::factory()->active()->create([ 'name' => 'Spec326 Browser Environment A', 'external_id' => 'spec326-browser-environment-a', ]); [$user, $environmentA] = createUserWithTenant( tenant: $environmentA, role: 'owner', workspaceRole: 'manager', ); $environmentB = ManagedEnvironment::factory()->active()->create([ 'workspace_id' => (int) $environmentA->workspace_id, 'name' => 'Spec326 Browser Environment B', 'external_id' => 'spec326-browser-environment-b', ]); createUserWithTenant( tenant: $environmentB, user: $user, role: 'owner', workspaceRole: 'manager', ); spec326CreatePublishedReview($environmentA, $user, 'review-packs/spec326-browser-a.zip', now()); spec326CreatePublishedReview($environmentB, $user, 'review-packs/spec326-browser-b.zip', now()->subHour()); return [$user, $environmentA, $environmentB]; } function spec326AuthenticateCustomerReviewWorkspaceBrowser( 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(), ]); } function spec326CreatePublishedReview( ManagedEnvironment $environment, User $user, string $filePath, \Illuminate\Support\Carbon $publishedAt, ): void { $snapshot = seedEnvironmentReviewEvidence($environment); $review = composeEnvironmentReviewForTest($environment, $user, $snapshot); $summary = is_array($review->summary) ? $review->summary : []; $summary['debug_payload'] = 'raw payload should stay hidden'; $summary['stack_trace'] = 'stack trace should stay hidden'; $summary['provider_secret'] = 'provider secret should stay hidden'; $summary['debug_metadata'] = 'debug metadata should stay hidden'; $summary['internal_exception'] = 'internal exception should stay hidden'; $summary['source_fingerprint'] = 'source fingerprint should stay hidden'; $summary['control_interpretation']['version_key'] = ComplianceEvidenceMappingV1::VERSION_KEY; $summary['control_interpretation']['controls'] = [ [ 'control_key' => 'customer-handoff-readiness', 'title' => 'Customer handoff readiness', 'readiness_bucket' => 'evidence_on_record', 'readiness_label' => 'Evidence on record', 'primary_reason' => 'Evidence path is complete.', 'recommended_next_action' => 'Share the current review pack.', ], ]; $review->forceFill([ 'status' => EnvironmentReviewStatus::Published->value, 'summary' => $summary, 'generated_at' => $publishedAt, 'published_at' => $publishedAt, 'published_by_user_id' => (int) $user->getKey(), ])->save(); Storage::disk('exports')->put($filePath, 'PK-test'); $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(), 'file_path' => $filePath, 'file_disk' => 'exports', 'generated_at' => $publishedAt, ]); $review->forceFill(['current_export_review_pack_id' => (int) $pack->getKey()])->save(); } function spec326CustomerReviewWorkspaceScreenshot(string $name): string { return 'spec326-'.$name; }