249 lines
11 KiB
PHP
249 lines
11 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\EvidenceSnapshot;
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\OperationRun;
|
|
use App\Models\User;
|
|
use App\Support\Evidence\EvidenceCompletenessState;
|
|
use App\Support\Evidence\EvidenceSnapshotStatus;
|
|
use App\Support\OperationRunLinks;
|
|
use App\Support\OperationRunOutcome;
|
|
use App\Support\OperationRunStatus;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
|
|
pest()->browser()->timeout(60_000);
|
|
|
|
it('Spec403 smokes Evidence Overview canonical operation proof currentness labels', function (): void {
|
|
$environment = ManagedEnvironment::factory()->active()->create([
|
|
'name' => 'Spec403 Failed Proof Environment',
|
|
]);
|
|
[$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'manager');
|
|
$foreignEnvironment = ManagedEnvironment::factory()->active()->create([
|
|
'name' => 'Spec403 Foreign Evidence Environment',
|
|
]);
|
|
$expiredEnvironment = spec403BrowserEnvironmentFor($user, $environment, 'Spec403 Expired Evidence Environment');
|
|
$staleDimensionEnvironment = spec403BrowserEnvironmentFor($user, $environment, 'Spec403 Stale Dimension Environment');
|
|
$missingDimensionEnvironment = spec403BrowserEnvironmentFor($user, $environment, 'Spec403 Missing Dimension Environment');
|
|
|
|
$run = OperationRun::factory()->forTenant($environment)->create([
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => OperationRunOutcome::Failed->value,
|
|
'started_at' => now()->subMinutes(10),
|
|
'completed_at' => now()->subMinutes(9),
|
|
'initiator_name' => 'Spec403 Browser Operator',
|
|
'context' => [
|
|
'raw_payload' => 'raw payload should stay hidden',
|
|
'provider_response' => 'provider response should stay hidden',
|
|
'stack_trace' => 'stack trace should stay hidden',
|
|
],
|
|
]);
|
|
|
|
EvidenceSnapshot::query()->create([
|
|
'managed_environment_id' => (int) $environment->getKey(),
|
|
'workspace_id' => (int) $environment->workspace_id,
|
|
'operation_run_id' => (int) $run->getKey(),
|
|
'status' => EvidenceSnapshotStatus::Active->value,
|
|
'completeness_state' => EvidenceCompletenessState::Complete->value,
|
|
'summary' => [
|
|
'dimension_count' => 2,
|
|
'missing_dimensions' => 0,
|
|
'stale_dimensions' => 0,
|
|
'raw_payload' => 'raw payload should stay hidden',
|
|
'provider_response' => 'provider response should stay hidden',
|
|
],
|
|
'generated_at' => now()->subMinutes(8),
|
|
'expires_at' => now()->addDay(),
|
|
]);
|
|
|
|
EvidenceSnapshot::query()->create([
|
|
'managed_environment_id' => (int) $expiredEnvironment->getKey(),
|
|
'workspace_id' => (int) $expiredEnvironment->workspace_id,
|
|
'status' => EvidenceSnapshotStatus::Active->value,
|
|
'completeness_state' => EvidenceCompletenessState::Complete->value,
|
|
'summary' => [
|
|
'dimension_count' => 2,
|
|
'missing_dimensions' => 0,
|
|
'stale_dimensions' => 0,
|
|
],
|
|
'generated_at' => now()->subDays(2),
|
|
'expires_at' => now()->subMinute(),
|
|
]);
|
|
|
|
EvidenceSnapshot::query()->create([
|
|
'managed_environment_id' => (int) $staleDimensionEnvironment->getKey(),
|
|
'workspace_id' => (int) $staleDimensionEnvironment->workspace_id,
|
|
'status' => EvidenceSnapshotStatus::Active->value,
|
|
'completeness_state' => EvidenceCompletenessState::Complete->value,
|
|
'summary' => [
|
|
'dimension_count' => 2,
|
|
'missing_dimensions' => 0,
|
|
'stale_dimensions' => 1,
|
|
],
|
|
'generated_at' => now()->subMinutes(6),
|
|
'expires_at' => now()->addDay(),
|
|
]);
|
|
|
|
EvidenceSnapshot::query()->create([
|
|
'managed_environment_id' => (int) $missingDimensionEnvironment->getKey(),
|
|
'workspace_id' => (int) $missingDimensionEnvironment->workspace_id,
|
|
'status' => EvidenceSnapshotStatus::Active->value,
|
|
'completeness_state' => EvidenceCompletenessState::Complete->value,
|
|
'summary' => [
|
|
'dimension_count' => 2,
|
|
'missing_dimensions' => 1,
|
|
'stale_dimensions' => 0,
|
|
],
|
|
'generated_at' => now()->subMinutes(5),
|
|
'expires_at' => now()->addDay(),
|
|
]);
|
|
|
|
spec403AuthenticateBrowser($this, $user, $environment);
|
|
|
|
$page = visit(route('admin.evidence.overview', [
|
|
'environment_id' => (int) $environment->getKey(),
|
|
]))
|
|
->resize(1366, 900)
|
|
->waitForText('Evidence proof workbench')
|
|
->assertSee('Spec403 Failed Proof Environment')
|
|
->assertSee('Operation proof')
|
|
->assertSee('Failed')
|
|
->assertSee('Spec403 Browser Operator')
|
|
->assertSee('Diagnostics')
|
|
->assertDontSee('Diagnostics - Collapsed')
|
|
->assertDontSee('Operation #')
|
|
->assertDontSee(OperationRunLinks::tenantlessView($run), false)
|
|
->assertDontSee('raw payload should stay hidden')
|
|
->assertDontSee('provider response should stay hidden')
|
|
->assertDontSee('stack trace should stay hidden')
|
|
->assertScript('(() => {
|
|
const item = document.querySelector("[data-proof-label=\"Operation proof\"]");
|
|
const badge = item?.querySelector("[data-testid=\"evidence-path-state-badge\"]");
|
|
|
|
return badge?.textContent.trim() === "Failed";
|
|
})()', true)
|
|
->assertScript('document.querySelector("[data-proof-label=\"Operation proof\"] a") === null', true)
|
|
->assertScript('(() => {
|
|
const legacyStates = ["Available", "Unavailable", "Not generated", "Not applicable", "Proof incomplete", "Empty", "Collapsed", "Unknown"];
|
|
const badges = Array.from(document.querySelectorAll("[data-testid=\"evidence-path-state-badge\"]"));
|
|
|
|
return badges.length > 0 && badges.every((badge) => !legacyStates.includes(badge.textContent.trim()));
|
|
})()', true)
|
|
->assertScript('document.querySelector("[data-testid=\"evidence-disclosure-diagnostics\"]")?.open === false', true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
|
|
$page->screenshot(true, 'spec403-evidence-currentness-operation-proof-failed');
|
|
spec403CopyBrowserScreenshot('spec403-evidence-currentness-operation-proof-failed');
|
|
|
|
visit(route('admin.evidence.overview', [
|
|
'environment_id' => (int) $expiredEnvironment->getKey(),
|
|
]))
|
|
->waitForText('Evidence snapshot required')
|
|
->assertSee('Spec403 Expired Evidence Environment')
|
|
->assertSee('Not configured')
|
|
->assertDontSee('View internal evidence details')
|
|
->assertScript('(() => {
|
|
const legacyStates = ["Available", "Unavailable", "Not generated", "Not applicable", "Proof incomplete", "Empty", "Collapsed", "Unknown"];
|
|
const badges = Array.from(document.querySelectorAll("[data-testid=\"evidence-path-state-badge\"]"));
|
|
|
|
return badges.length > 0 && badges.every((badge) => !legacyStates.includes(badge.textContent.trim()));
|
|
})()', true)
|
|
->assertScript('document.querySelector("[data-step-label=\"Evidence snapshot\"]")?.dataset.stepState === "Not configured"', true)
|
|
->assertScript('document.querySelector("[data-step-label=\"Evidence snapshot\"]")?.dataset.stepCurrentBlocker === "true"', true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
|
|
visit(route('admin.evidence.overview', [
|
|
'environment_id' => (int) $staleDimensionEnvironment->getKey(),
|
|
]))
|
|
->waitForText('Evidence snapshot required')
|
|
->assertSee('Spec403 Stale Dimension Environment')
|
|
->assertSee('Not configured')
|
|
->assertDontSee('View internal evidence details')
|
|
->assertScript('document.querySelector("[data-step-label=\"Evidence snapshot\"]")?.dataset.stepState === "Not configured"', true)
|
|
->assertScript('document.querySelector("[data-step-label=\"Evidence snapshot\"]")?.dataset.stepCurrentBlocker === "true"', true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
|
|
visit(route('admin.evidence.overview', [
|
|
'environment_id' => (int) $missingDimensionEnvironment->getKey(),
|
|
]))
|
|
->waitForText('Evidence snapshot required')
|
|
->assertSee('Spec403 Missing Dimension Environment')
|
|
->assertSee('Not configured')
|
|
->assertSee('Needs attention')
|
|
->assertSee('Refresh evidence before using this snapshot')
|
|
->assertDontSee('Partially complete')
|
|
->assertDontSee('Trustworthy artifact')
|
|
->assertDontSee('View internal evidence details')
|
|
->assertScript('document.querySelector("[data-step-label=\"Evidence snapshot\"]")?.dataset.stepState === "Not configured"', true)
|
|
->assertScript('document.querySelector("[data-step-label=\"Evidence snapshot\"]")?.dataset.stepCurrentBlocker === "true"', true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
|
|
visit(route('admin.evidence.overview', [
|
|
'environment_id' => (int) $foreignEnvironment->getKey(),
|
|
]))
|
|
->assertSee('404')
|
|
->assertDontSee('Spec403 Foreign Evidence Environment')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
});
|
|
|
|
function spec403BrowserEnvironmentFor(User $user, ManagedEnvironment $baseEnvironment, string $name): ManagedEnvironment
|
|
{
|
|
$environment = ManagedEnvironment::factory()->active()->create([
|
|
'workspace_id' => (int) $baseEnvironment->workspace_id,
|
|
'name' => $name,
|
|
]);
|
|
|
|
createUserWithTenant(tenant: $environment, user: $user, role: 'owner', workspaceRole: 'manager');
|
|
|
|
return $environment;
|
|
}
|
|
|
|
function spec403AuthenticateBrowser(mixed $test, User $user, ManagedEnvironment $environment): void
|
|
{
|
|
$workspaceId = (int) $environment->workspace_id;
|
|
$session = [
|
|
WorkspaceContext::SESSION_KEY => $workspaceId,
|
|
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
|
|
(string) $workspaceId => (int) $environment->getKey(),
|
|
],
|
|
];
|
|
|
|
$test->actingAs($user)->withSession($session);
|
|
|
|
foreach ($session as $key => $value) {
|
|
session()->put($key, $value);
|
|
}
|
|
|
|
setAdminPanelContext($environment);
|
|
}
|
|
|
|
function spec403CopyBrowserScreenshot(string $name): void
|
|
{
|
|
$filename = $name.'.png';
|
|
$source = base_path('tests/Browser/Screenshots/'.$filename);
|
|
$targetDirectory = repo_path('specs/403-evidence-anchor-currentness-runtime-closure/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.$filename);
|
|
}
|
|
}
|