TenantAtlas/apps/platform/tests/Browser/Spec365OperationsUiOperatorActionsSmokeTest.php
Ahmed Darrazi 2a856d2693
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 3m44s
feat: implement operations UI operator actions regression gate
2026-06-08 03:19:34 +02:00

302 lines
11 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\BackupSet;
use App\Models\EnvironmentReview;
use App\Models\EvidenceSnapshot;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\RestoreRun;
use App\Models\ReviewPack;
use App\Models\User;
use App\Services\EnvironmentReviews\EnvironmentReviewFingerprint;
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\RestoreRunStatus;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
pest()->browser()->timeout(60_000);
it('Spec365 smokes confirmed review reconciliation guidance on operations surfaces', function (): void {
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
spec365BrowserAuthenticate($this, $user, $environment);
$snapshot = seedEnvironmentReviewEvidence($environment, operationRunCount: 0);
$fingerprint = app(EnvironmentReviewFingerprint::class)->forSnapshot($environment, $snapshot);
$run = spec365BrowserCreateStaleReviewRun($environment, $user, $fingerprint, $snapshot);
spec365BrowserCreateReadyReviewTruth($environment, $user, $snapshot, $fingerprint);
visit(OperationRunLinks::index($environment))
->resize(1440, 1100)
->waitForText('Operations Hub')
->assertSee('Reconcile run')
->assertSee('Existing repository proof may safely reconcile this stale run.')
->assertDontSee('SQLSTATE')
->assertDontSee('access token')
->assertDontSee('client secret')
->assertDontSee('serialized job')
->assertNoJavaScriptErrors()
->assertNoConsoleLogs();
visit(OperationRunLinks::tenantlessView($run))
->waitForText('Monitoring detail')
->assertSee('Reconcile run')
->click('Reconcile run')
->assertSee('Reconcile this operation run?')
->assertSee('This does not retry or change the Microsoft tenant.')
->assertDontSee('SQLSTATE')
->assertDontSee('environment_reviews_fingerprint_mutable_unique')
->assertNoJavaScriptErrors()
->assertNoConsoleLogs();
});
it('Spec365 smokes related proof actions across evidence report sync and backup states', function (): void {
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
spec365BrowserAuthenticate($this, $user, $environment);
spec365BrowserCreateEvidenceRun($environment, $user);
spec365BrowserCreateReviewPackRun($environment, $user);
spec365BrowserCreatePartialInventoryRun($environment, $user);
spec365BrowserCreateBlockedBackupRun($environment, $user);
visit(OperationRunLinks::index($environment))
->resize(1440, 1100)
->waitForText('Operations Hub')
->assertSee('View evidence')
->assertSee('View report')
->assertSee('View affected families')
->assertSee('View backup details')
->assertDontSee('SQLSTATE')
->assertDontSee('Guzzle')
->assertDontSee('stack trace')
->assertDontSee('access token')
->assertDontSee('client secret')
->assertNoJavaScriptErrors()
->assertNoConsoleLogs();
});
it('Spec365 smokes high-risk restore guidance without unsafe operator actions', function (): void {
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
spec365BrowserAuthenticate($this, $user, $environment);
$run = spec365BrowserCreateStaleRestoreRun($environment, $user);
visit(OperationRunLinks::tenantlessView($run))
->resize(1440, 1100)
->waitForText('Monitoring detail')
->assertSee('View restore details')
->assertSee('High-risk operations cannot be retried from this view.')
->assertDontSee('Retry restore')
->assertDontSee('Force complete')
->assertDontSee('Mark succeeded')
->assertDontSee('Delete run')
->assertDontSee('Purge run')
->assertDontSee('stack trace')
->assertDontSee('access token')
->assertDontSee('client secret')
->assertNoJavaScriptErrors()
->assertNoConsoleLogs();
});
function spec365BrowserAuthenticate(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);
}
function spec365BrowserCreateStaleReviewRun(
ManagedEnvironment $environment,
User $user,
string $fingerprint,
EvidenceSnapshot $snapshot,
): OperationRun {
return OperationRun::factory()->forTenant($environment)->create([
'user_id' => (int) $user->getKey(),
'initiator_name' => $user->name,
'type' => 'environment.review.compose',
'status' => OperationRunStatus::Queued->value,
'outcome' => OperationRunOutcome::Pending->value,
'created_at' => now()->subMinutes(10),
'context' => [
'workspace_id' => (int) $environment->workspace_id,
'managed_environment_id' => (int) $environment->getKey(),
'evidence_snapshot_id' => (int) $snapshot->getKey(),
'review_fingerprint' => $fingerprint,
],
]);
}
function spec365BrowserCreateReadyReviewTruth(
ManagedEnvironment $environment,
User $user,
EvidenceSnapshot $snapshot,
string $fingerprint,
): EnvironmentReview {
$publishedRun = OperationRun::factory()->forTenant($environment)->create([
'user_id' => (int) $user->getKey(),
'initiator_name' => $user->name,
'type' => 'environment.review.compose',
'status' => OperationRunStatus::Completed->value,
'outcome' => OperationRunOutcome::Succeeded->value,
'completed_at' => now()->subMinutes(5),
'context' => [
'workspace_id' => (int) $environment->workspace_id,
'managed_environment_id' => (int) $environment->getKey(),
'review_fingerprint' => $fingerprint,
],
]);
return EnvironmentReview::factory()->ready()->create([
'workspace_id' => (int) $environment->workspace_id,
'managed_environment_id' => (int) $environment->getKey(),
'evidence_snapshot_id' => (int) $snapshot->getKey(),
'initiated_by_user_id' => (int) $user->getKey(),
'operation_run_id' => (int) $publishedRun->getKey(),
'fingerprint' => $fingerprint,
'summary' => [
'finding_count' => 4,
'report_count' => 2,
'operation_count' => 1,
],
]);
}
function spec365BrowserCreateStaleRestoreRun(ManagedEnvironment $environment, User $user): OperationRun
{
$backupSet = BackupSet::factory()->for($environment)->create(['status' => 'completed']);
$run = OperationRun::factory()->forTenant($environment)->create([
'user_id' => (int) $user->getKey(),
'initiator_name' => $user->name,
'type' => 'restore.execute',
'status' => OperationRunStatus::Queued->value,
'outcome' => OperationRunOutcome::Pending->value,
'created_at' => now()->subMinutes(10),
]);
$restoreRun = RestoreRun::withoutEvents(fn (): RestoreRun => RestoreRun::factory()
->for($environment, 'tenant')
->for($backupSet)
->create([
'workspace_id' => (int) $environment->workspace_id,
'operation_run_id' => (int) $run->getKey(),
'status' => RestoreRunStatus::Completed->value,
'is_dry_run' => false,
]));
$run->forceFill([
'context' => [
'restore_run_id' => (int) $restoreRun->getKey(),
'backup_set_id' => (int) $backupSet->getKey(),
],
])->save();
return $run->fresh();
}
function spec365BrowserCreateEvidenceRun(ManagedEnvironment $environment, User $user): OperationRun
{
$run = OperationRun::factory()->forTenant($environment)->create([
'user_id' => (int) $user->getKey(),
'initiator_name' => $user->name,
'type' => 'tenant.evidence.snapshot.generate',
'status' => OperationRunStatus::Completed->value,
'outcome' => OperationRunOutcome::Succeeded->value,
'completed_at' => now()->subMinutes(3),
]);
EvidenceSnapshot::query()->create([
'workspace_id' => (int) $environment->workspace_id,
'managed_environment_id' => (int) $environment->getKey(),
'operation_run_id' => (int) $run->getKey(),
'initiated_by_user_id' => (int) $user->getKey(),
'fingerprint' => hash('sha256', 'spec365-browser-evidence-'.$run->getKey()),
'status' => EvidenceSnapshotStatus::Active->value,
'completeness_state' => EvidenceCompletenessState::Complete->value,
'summary' => ['source' => 'spec365-browser'],
'generated_at' => now()->subMinutes(3),
]);
return $run->fresh();
}
function spec365BrowserCreateReviewPackRun(ManagedEnvironment $environment, User $user): OperationRun
{
$run = OperationRun::factory()->forTenant($environment)->create([
'user_id' => (int) $user->getKey(),
'initiator_name' => $user->name,
'type' => 'environment.review_pack.generate',
'status' => OperationRunStatus::Completed->value,
'outcome' => OperationRunOutcome::Succeeded->value,
'completed_at' => now()->subMinutes(4),
]);
ReviewPack::factory()->ready()->create([
'workspace_id' => (int) $environment->workspace_id,
'managed_environment_id' => (int) $environment->getKey(),
'operation_run_id' => (int) $run->getKey(),
'initiated_by_user_id' => (int) $user->getKey(),
]);
return $run->fresh();
}
function spec365BrowserCreatePartialInventoryRun(ManagedEnvironment $environment, User $user): OperationRun
{
return OperationRun::factory()->forTenant($environment)->create([
'user_id' => (int) $user->getKey(),
'initiator_name' => $user->name,
'type' => 'inventory.sync',
'status' => OperationRunStatus::Completed->value,
'outcome' => OperationRunOutcome::PartiallySucceeded->value,
'completed_at' => now()->subMinutes(5),
'summary_counts' => [
'total' => 4,
'processed' => 4,
'succeeded' => 2,
'failed' => 1,
'skipped' => 1,
],
]);
}
function spec365BrowserCreateBlockedBackupRun(ManagedEnvironment $environment, User $user): OperationRun
{
$backupSet = BackupSet::factory()->for($environment)->create(['status' => 'completed']);
return OperationRun::factory()->forTenant($environment)->create([
'user_id' => (int) $user->getKey(),
'initiator_name' => $user->name,
'type' => 'backup.schedule.execute',
'status' => OperationRunStatus::Completed->value,
'outcome' => OperationRunOutcome::Blocked->value,
'completed_at' => now()->subMinutes(6),
'context' => [
'backup_set_id' => (int) $backupSet->getKey(),
'reason_code' => 'missing_provider_permission',
],
]);
}