browser()->timeout(60_000); function spec336BrowserScreenshotName(string $name): string { return 'spec336-baseline-compare-'.$name; } function spec336CopyBrowserScreenshot(string $name): void { $filename = spec336BrowserScreenshotName($name).'.png'; $source = base_path('tests/Browser/Screenshots/'.$filename); $targetDirectory = repo_path('specs/336-baseline-compare-product-process-flow-alignment/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'); } } function spec336AuthenticateBrowser(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 spec336EnvironmentFor(User $user, ManagedEnvironment $baseEnvironment, string $name): ManagedEnvironment { $environment = ManagedEnvironment::factory()->create([ 'workspace_id' => (int) $baseEnvironment->workspace_id, 'name' => $name, ]); createUserWithTenant(tenant: $environment, user: $user, role: 'owner', workspaceRole: 'manager'); return $environment; } it('Spec336 smokes Baseline Compare product process flow states', function (): void { [$user, $noBaselineEnvironment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager'); createInventorySyncOperationRunWithCoverage($noBaselineEnvironment, ['deviceConfiguration' => 'succeeded']); $snapshotMissingEnvironment = spec336EnvironmentFor($user, $noBaselineEnvironment, 'Spec336 Snapshot Missing'); $missingProfile = BaselineProfile::factory()->active()->create([ 'workspace_id' => (int) $snapshotMissingEnvironment->workspace_id, ]); BaselineTenantAssignment::factory()->create([ 'workspace_id' => (int) $snapshotMissingEnvironment->workspace_id, 'managed_environment_id' => (int) $snapshotMissingEnvironment->getKey(), 'baseline_profile_id' => (int) $missingProfile->getKey(), ]); $compareRequiredEnvironment = spec336EnvironmentFor($user, $noBaselineEnvironment, 'Spec336 Compare Required'); seedActiveBaselineForTenant($compareRequiredEnvironment); createInventorySyncOperationRunWithCoverage($compareRequiredEnvironment, ['deviceConfiguration' => 'succeeded']); $compareAvailableEnvironment = spec336EnvironmentFor($user, $noBaselineEnvironment, 'Spec336 Compare Available'); [$availableProfile, $availableSnapshot] = seedActiveBaselineForTenant($compareAvailableEnvironment); $availableRun = seedBaselineCompareRun($compareAvailableEnvironment, $availableProfile, $availableSnapshot, [ 'reason_code' => BaselineCompareReasonCode::OverdueFindingsRemain->value, 'coverage' => [ 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], 'proof' => true, ], ]); Finding::factory()->create([ 'managed_environment_id' => (int) $compareAvailableEnvironment->getKey(), 'workspace_id' => (int) $compareAvailableEnvironment->workspace_id, 'finding_type' => Finding::FINDING_TYPE_DRIFT, 'scope_key' => 'baseline_profile:'.$availableProfile->getKey(), 'severity' => Finding::SEVERITY_HIGH, 'status' => Finding::STATUS_NEW, 'source' => OperationRunType::BaselineCompare->value, 'baseline_operation_run_id' => (int) $availableRun->getKey(), ]); $evidenceUnavailableEnvironment = spec336EnvironmentFor($user, $noBaselineEnvironment, 'Spec336 Evidence Unavailable'); [$evidenceProfile, $evidenceSnapshot] = seedActiveBaselineForTenant($evidenceUnavailableEnvironment); $evidenceRun = seedBaselineCompareRun($evidenceUnavailableEnvironment, $evidenceProfile, $evidenceSnapshot, [ 'reason_code' => BaselineCompareReasonCode::EvidenceCaptureIncomplete->value, 'coverage' => [ 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], 'proof' => true, ], 'evidence_gaps' => [ 'count' => 1, 'by_reason' => [ 'inventory_record_missing' => 1, ], ], ], OperationRunStatus::Completed->value, OperationRunOutcome::PartiallySucceeded->value); Finding::factory()->create([ 'managed_environment_id' => (int) $evidenceUnavailableEnvironment->getKey(), 'workspace_id' => (int) $evidenceUnavailableEnvironment->workspace_id, 'finding_type' => Finding::FINDING_TYPE_DRIFT, 'scope_key' => 'baseline_profile:'.$evidenceProfile->getKey(), 'severity' => Finding::SEVERITY_MEDIUM, 'status' => Finding::STATUS_NEW, 'source' => OperationRunType::BaselineCompare->value, 'baseline_operation_run_id' => (int) $evidenceRun->getKey(), ]); spec336AuthenticateBrowser($this, $user, $noBaselineEnvironment); $page = visit(ManagedEnvironmentLinks::baselineCompareUrl($noBaselineEnvironment)) ->waitForText('Which baseline drift requires action?') ->assertSee('Baseline not assigned') ->assertSee('Open baseline profiles') ->assertSee('Compare readiness flow') ->assertSee('Available inputs') ->assertScript('document.querySelectorAll("[data-testid=\"baseline-compare-readiness-step\"]").length === 5', true) ->assertScript('document.querySelector("[data-step-label=\"Baseline assigned\"]")?.dataset.stepState === "Missing"', true) ->assertScript('document.querySelector("[data-testid=\"baseline-compare-diagnostics\"]")?.open === false', true) ->assertDontSee('raw diff') ->assertDontSee('raw payload') ->assertNoJavaScriptErrors() ->assertNoConsoleLogs(); $page->screenshot(true, spec336BrowserScreenshotName('01-no-baseline-assigned')); spec336CopyBrowserScreenshot('01-no-baseline-assigned'); $page = visit(ManagedEnvironmentLinks::baselineCompareUrl($snapshotMissingEnvironment)) ->waitForText('Baseline snapshot required') ->assertSee('Open baseline profile') ->assertSee('No usable baseline snapshot input is linked.') ->assertScript('document.querySelector("[data-step-label=\"Baseline snapshot\"]")?.dataset.stepState === "Missing"', true) ->assertScript('document.querySelector("[data-step-label=\"Baseline snapshot\"]")?.dataset.stepCurrentBlocker === "true"', true) ->assertDontSee('raw diff') ->assertNoJavaScriptErrors() ->assertNoConsoleLogs(); $page->screenshot(true, spec336BrowserScreenshotName('02-baseline-snapshot-required')); spec336CopyBrowserScreenshot('02-baseline-snapshot-required'); $page = visit(ManagedEnvironmentLinks::baselineCompareUrl($compareRequiredEnvironment)) ->waitForText('Compare run required') ->assertSee('Compare now') ->assertScript('document.querySelector("[data-step-label=\"Compare run\"]")?.dataset.stepState === "Required"', true) ->assertScript('document.querySelector("[data-step-label=\"Compare run\"]")?.dataset.stepCurrentBlocker === "true"', true) ->assertScript('document.body.innerText.includes("Total Findings") === false', true) ->assertNoJavaScriptErrors() ->assertNoConsoleLogs(); $page->screenshot(true, spec336BrowserScreenshotName('03-compare-run-required')); spec336CopyBrowserScreenshot('03-compare-run-required'); $page = visit(ManagedEnvironmentLinks::baselineCompareUrl($compareAvailableEnvironment)) ->waitForText('Drift findings available') ->assertSee('Review drift findings') ->assertSee('OperationRun proof') ->assertScript('document.querySelector("[data-step-label=\"Compare run\"]")?.dataset.stepState === "Available"', true) ->assertScript('document.querySelector("[data-step-label=\"Decision output\"]")?.dataset.stepState === "Available"', true) ->assertScript('Array.from(document.querySelectorAll("[data-testid=\"baseline-compare-status-badge\"]")).every((badge) => !badge.innerText.includes("...") && getComputedStyle(badge).overflow !== "hidden" && getComputedStyle(badge).textOverflow !== "ellipsis")', true) ->assertDontSee('customer-safe') ->assertDontSee('raw diff') ->assertNoJavaScriptErrors() ->assertNoConsoleLogs(); $page->screenshot(true, spec336BrowserScreenshotName('04-compare-result-available')); spec336CopyBrowserScreenshot('04-compare-result-available'); $page = visit(ManagedEnvironmentLinks::baselineCompareUrl($evidenceUnavailableEnvironment)) ->waitForText('Evidence unavailable - Evidence gaps need review') ->assertSee('Compare result exists, but evidence output is not available.') ->assertScript('document.querySelector("[data-step-label=\"Decision output\"]")?.dataset.stepState === "Needs review"', true) ->assertScript('document.querySelector("[data-testid=\"baseline-compare-diagnostics\"]")?.open === false', true) ->assertDontSee('raw diff') ->assertDontSee('raw payload') ->assertNoJavaScriptErrors() ->assertNoConsoleLogs(); $page->screenshot(true, spec336BrowserScreenshotName('05-evidence-unavailable')); spec336CopyBrowserScreenshot('05-evidence-unavailable'); $page->screenshot(true, spec336BrowserScreenshotName('06-diagnostics-collapsed')); spec336CopyBrowserScreenshot('06-diagnostics-collapsed'); $page->script("document.documentElement.classList.add('dark');"); $page->script('window.scrollTo(0, 0);'); $page->assertScript('document.documentElement.classList.contains("dark")', true); $page->screenshot(true, spec336BrowserScreenshotName('07-dark-mode')); spec336CopyBrowserScreenshot('07-dark-mode'); });