Renames ManagedEnvironment context badge to Environment context as requested. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #431
168 lines
6.4 KiB
PHP
168 lines
6.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\EnvironmentReview;
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\OperationRun;
|
|
use App\Models\User;
|
|
use App\Services\OperationRunService;
|
|
use App\Support\EnvironmentReviewStatus;
|
|
use App\Support\OperationRunLinks;
|
|
use App\Support\OperationRunOutcome;
|
|
use App\Support\OperationRunStatus;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
pest()->browser()->timeout(60_000);
|
|
|
|
it('Spec360 smokes canonical review reconciliation drill-through on the existing operations surfaces', function (): void {
|
|
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
|
|
|
|
spec360AuthenticateBrowser($this, $user, $environment);
|
|
|
|
$review = spec360BrowserCreatePublishedMatchingReview($environment, $user, 'spec360-browser-reused');
|
|
$run = spec360BrowserCreateCanonicalReconciledReviewComposeRun($environment, $user, $review);
|
|
|
|
visit(OperationRunLinks::index($environment))
|
|
->resize(1440, 1100)
|
|
->waitForText('Operations Hub')
|
|
->assertSee('Automatically reconciled')
|
|
->assertSee('A matching review was already available.')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
|
|
visit(OperationRunLinks::tenantlessView($run))
|
|
->waitForText('Monitoring detail')
|
|
->assertSee('A matching review was already available.')
|
|
->assertSee('No action needed. A matching review was already available.')
|
|
->click('Open')
|
|
->assertSee('ManagedEnvironment Review')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
});
|
|
|
|
it('Spec360 smokes stale queued lifecycle guidance separately from canonical reconciliation', function (): void {
|
|
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
|
|
|
|
spec360AuthenticateBrowser($this, $user, $environment);
|
|
|
|
$staleRun = OperationRun::factory()->forTenant($environment)->create([
|
|
'user_id' => (int) $user->getKey(),
|
|
'initiator_name' => $user->name,
|
|
'type' => 'inventory.sync',
|
|
'status' => OperationRunStatus::Queued->value,
|
|
'outcome' => OperationRunOutcome::Pending->value,
|
|
'created_at' => now()->subWeeks(2),
|
|
]);
|
|
|
|
visit(OperationRunLinks::index($environment))
|
|
->resize(1440, 1100)
|
|
->waitForText('Operations Hub')
|
|
->assertSee('Likely stale')
|
|
->assertSee('Past the lifecycle window. Review worker health and logs before retrying.')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
|
|
visit(OperationRunLinks::tenantlessView($staleRun))
|
|
->waitForText('Monitoring detail')
|
|
->assertSee('Likely stale operation')
|
|
->assertDontSee('No action needed yet. The operation is currently in progress.')
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
});
|
|
|
|
function spec360AuthenticateBrowser(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 spec360BrowserCreatePublishedMatchingReview(
|
|
ManagedEnvironment $environment,
|
|
User $user,
|
|
string $fingerprint,
|
|
): EnvironmentReview {
|
|
$snapshot = seedEnvironmentReviewEvidence($environment, operationRunCount: 1);
|
|
|
|
$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()->published()->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,
|
|
'status' => EnvironmentReviewStatus::Published->value,
|
|
'published_by_user_id' => (int) $user->getKey(),
|
|
]);
|
|
}
|
|
|
|
function spec360BrowserCreateCanonicalReconciledReviewComposeRun(
|
|
ManagedEnvironment $environment,
|
|
User $user,
|
|
EnvironmentReview $relatedReview,
|
|
): OperationRun {
|
|
$run = 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,
|
|
'context' => [
|
|
'workspace_id' => (int) $environment->workspace_id,
|
|
'managed_environment_id' => (int) $environment->getKey(),
|
|
'review_fingerprint' => (string) $relatedReview->fingerprint,
|
|
],
|
|
]);
|
|
|
|
return app(OperationRunService::class)->updateRunWithReconciliation(
|
|
run: $run,
|
|
status: OperationRunStatus::Completed->value,
|
|
outcome: OperationRunOutcome::Succeeded->value,
|
|
summaryCounts: ['finding_count' => 2],
|
|
failures: [],
|
|
reasonCode: 'run.adapter_out_of_sync',
|
|
reasonMessage: 'A matching review was already available for this run.',
|
|
source: 'adapter_reconciler',
|
|
evidence: [
|
|
'fingerprint' => (string) $relatedReview->fingerprint,
|
|
],
|
|
adapter: 'environment_review_compose',
|
|
decision: 'reconciled_succeeded',
|
|
related: [
|
|
'type' => 'environment_review',
|
|
'id' => (int) $relatedReview->getKey(),
|
|
'status' => (string) $relatedReview->status,
|
|
],
|
|
)->fresh();
|
|
}
|