TenantAtlas/apps/platform/tests/Browser/Spec352EnvironmentDashboardGuidanceSmokeTest.php
ahmido 9a564d6bf2 feat: environment dashboard operator guidance consolidation (spec 352) (#423)
Implemented the consolidated operator guidance panel for the environment dashboard. Updated EnvironmentDashboardSummaryBuilder to prioritize and select guidance based on the operator guidance contract. Added comprehensive unit, feature, and browser tests to verify the guidance selection logic and UI rendering.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #423
2026-06-04 12:56:02 +00:00

211 lines
8.9 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\EnvironmentDashboard;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentPermission;
use App\Models\ProviderConnection;
use App\Models\ReviewPack;
use App\Models\User;
use App\Services\EnvironmentReviews\EnvironmentReviewLifecycleService;
use App\Support\EnvironmentReviewStatus;
use App\Support\Workspaces\WorkspaceContext;
pest()->browser()->timeout(20_000);
function spec352BrowserScreenshotName(string $name): string
{
return 'spec352-environment-dashboard-'.$name;
}
/**
* @return array{
* review:\App\Models\EnvironmentReview,
* successor:\App\Models\EnvironmentReview|null,
* reviewPack:ReviewPack,
* }
*/
function spec352BrowserSeedBlockedReviewOutput(ManagedEnvironment $environment, User $user, bool $withSuccessorDraft = false): array
{
$snapshot = seedPartialEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0, operationRunCount: 0);
$review = composeEnvironmentReviewForTest($environment, $user, $snapshot);
$review->forceFill([
'status' => EnvironmentReviewStatus::Published->value,
'published_at' => now()->subHour(),
'published_by_user_id' => (int) $user->getKey(),
'summary' => array_replace_recursive(is_array($review->summary) ? $review->summary : [], [
'publish_blockers' => ['Operator approval note is still missing.'],
]),
])->save();
$reviewPack = 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' => 'review-packs/spec352-browser.zip',
'file_disk' => 'exports',
'generated_at' => now()->subMinutes(10),
'options' => [
'include_pii' => false,
'include_operations' => true,
],
]);
$review->forceFill([
'current_export_review_pack_id' => (int) $reviewPack->getKey(),
])->save();
$successor = null;
if ($withSuccessorDraft) {
$successor = app(EnvironmentReviewLifecycleService::class)->createNextReview($review->fresh(), $user, $snapshot);
}
return [
'review' => $review->fresh(),
'successor' => $successor?->fresh(),
'reviewPack' => $reviewPack->fresh(),
];
}
function spec352BrowserApplicationPermissionKey(): string
{
$permission = collect(spec283ConfiguredPermissionRows())
->first(static fn (mixed $row): bool => is_array($row) && ($row['type'] ?? null) === 'application');
expect($permission)->not->toBeNull();
return (string) $permission['key'];
}
function spec352BrowserSeedPermissionRows(
ManagedEnvironment $environment,
array $missingKeys = [],
array $errorKeys = [],
): void {
foreach (spec283ConfiguredPermissionRows() as $permission) {
if (! is_array($permission)) {
continue;
}
$permissionKey = (string) ($permission['key'] ?? '');
if ($permissionKey === '') {
continue;
}
ManagedEnvironmentPermission::query()->updateOrCreate(
[
'managed_environment_id' => (int) $environment->getKey(),
'permission_key' => $permissionKey,
'workspace_id' => (int) $environment->workspace_id,
],
[
'status' => in_array($permissionKey, $errorKeys, true)
? 'error'
: (in_array($permissionKey, $missingKeys, true) ? 'missing' : 'granted'),
'details' => ['source' => 'spec352-browser-test'],
'last_checked_at' => now(),
],
);
}
}
function spec352BrowserActAs(User $user, ManagedEnvironment $environment): void
{
test()->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id,
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $environment->workspace_id => (int) $environment->getKey(),
],
]);
}
it('smokes provider-blocker guidance as the dominant dashboard case', function (): void {
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
ProviderConnection::factory()->platform()->consentGranted()->create([
'managed_environment_id' => (int) $environment->getKey(),
'workspace_id' => (int) $environment->workspace_id,
'is_default' => true,
]);
spec352BrowserSeedBlockedReviewOutput($environment, $user, withSuccessorDraft: true);
$missingPermissionKey = spec352BrowserApplicationPermissionKey();
spec352BrowserSeedPermissionRows($environment, missingKeys: [$missingPermissionKey]);
spec352BrowserActAs($user, $environment);
visit(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $environment))
->waitForText('Provider readiness blocks evidence refresh')
->assertSee('Recommended next action')
->assertSee('Review permissions')
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-primary-next-action\"]')?.textContent?.includes('Review permissions') ?? false", true)
->assertScript("Array.from(document.querySelectorAll('a')).filter((node) => node.textContent?.trim().includes('Review permissions')).length === 1", true)
->assertScript("document.querySelectorAll('[data-testid=\"tenant-dashboard-operator-guidance-secondary-action\"]').length === 0", true)
->assertDontSee('No single repo-real follow-up is currently available.')
->assertNoJavaScriptErrors()
->assertNoConsoleLogs()
->screenshot(true, spec352BrowserScreenshotName('provider-blocker'));
});
it('smokes review-output guidance with subordinate secondary links when provider blockers are absent', function (): void {
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
ProviderConnection::factory()->platform()->consentGranted()->create([
'managed_environment_id' => (int) $environment->getKey(),
'workspace_id' => (int) $environment->workspace_id,
'is_default' => true,
]);
spec352BrowserSeedBlockedReviewOutput($environment, $user, withSuccessorDraft: true);
spec352BrowserSeedPermissionRows($environment);
spec352BrowserActAs($user, $environment);
visit(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $environment))
->waitForText('Draft review exists')
->assertSee('Open draft review')
->assertSee('Additional follow-ups')
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-primary-next-action\"]')?.textContent?.includes('Open draft review') ?? false", true)
->assertScript("Array.from(document.querySelectorAll('a')).filter((node) => node.textContent?.trim().includes('Open draft review')).length === 1", true)
->assertScript("document.querySelectorAll('[data-testid=\"tenant-dashboard-operator-guidance-secondary-action\"]').length >= 1", true)
->assertScript("document.querySelector('[data-recommended-actions-style=\"compact\"]') !== null", true)
->assertDontSee('No single repo-real follow-up is currently available.')
->assertNoJavaScriptErrors()
->assertNoConsoleLogs()
->screenshot(true, spec352BrowserScreenshotName('review-output'));
});
it('smokes the no-urgent-action dashboard state with preserved secondary proof surfaces', function (): void {
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
ProviderConnection::factory()->platform()->consentGranted()->create([
'managed_environment_id' => (int) $environment->getKey(),
'workspace_id' => (int) $environment->workspace_id,
'is_default' => true,
]);
spec352BrowserSeedPermissionRows($environment);
workspaceOverviewSeedQuietTenantTruth($environment);
$backupSet = workspaceOverviewSeedHealthyBackup($environment);
workspaceOverviewSeedRestoreHistory($environment, $backupSet, 'completed');
spec352BrowserActAs($user, $environment);
visit(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $environment))
->waitForText('No urgent operator action')
->assertSee('Review environment')
->assertSee('Readiness proof')
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-recommended-actions-empty\"]') !== null", true)
->assertScript("Array.from(document.querySelectorAll('a')).filter((node) => node.textContent?.trim().includes('Review environment')).length === 1", true)
->assertDontSee('No single repo-real follow-up is currently available.')
->assertNoJavaScriptErrors()
->assertNoConsoleLogs()
->screenshot(true, spec352BrowserScreenshotName('no-urgent-action'));
});