TenantAtlas/apps/platform/tests/Browser/Spec371BackupSetProductizationSmokeTest.php
ahmido 8713b35da5 feat(ui): implement core operator view surfaces productization for backup sets (#442)
Applied the decision-first global surface IA contract to BackupSet views. Includes decision summary header, usability status, and separation of technical metadata.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #442
2026-06-11 07:38:33 +00:00

183 lines
6.8 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Resources\BackupSetResource;
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\User;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\OperationRunType;
use Illuminate\Foundation\Testing\RefreshDatabase;
pest()->browser()->timeout(60_000);
uses(RefreshDatabase::class);
it('Spec371 smokes backup set list and detail decision hierarchy with screenshots', function (): void {
[$user, $tenant] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
$healthyBackupSet = spec371BrowserHealthyBackupSet($tenant, [
'name' => 'Spec 371 Browser Healthy Backup',
]);
BackupSet::factory()
->for($tenant)
->degradedCompleted()
->create([
'name' => 'Spec 371 Browser Degraded Backup',
]);
spec371BrowserSourceOperation($tenant, $user, $healthyBackupSet);
$listPath = spec371BrowserListPath($tenant);
$detailPath = spec371BrowserViewPath($tenant, $healthyBackupSet);
$page = visit(spec371BrowserLoginUrl($user, $tenant, $listPath))
->resize(1440, 1100)
->waitForText('Backup Sets')
->waitForText('Restore-point decision')
->assertSee('Spec 371 Browser Healthy Backup')
->assertSee('Usable for restore review')
->assertSee('Spec 371 Browser Degraded Backup')
->assertSee('Action needed before restore review')
->assertSee('Items captured')
->assertDontSee('No degradations detected across')
->assertScript("document.querySelector('a[href$=\"{$detailPath}\"]') !== null", true)
->assertNoJavaScriptErrors()
->assertNoConsoleLogs()
->screenshot(true, spec371BrowserScreenshotName('01-backup-sets-list'));
spec371BrowserCopyScreenshot('01-backup-sets-list');
$page = visit($detailPath)
->resize(1440, 1100)
->waitForText('Restore-point decision')
->assertSee('Spec 371 Browser Healthy Backup')
->assertSee('Usable for restore review')
->assertSee('Captured item inventory is available for operator review.')
->assertSee('Review included items below before starting any separate restore workflow.')
->assertSee('Included backup items')
->assertSee('Related operation and evidence')
->assertSee('Open operation')
->assertSee('Technical and lifecycle detail')
->assertDontSee('Item review state')
->assertDontSee('Backup quality, lifecycle status, and related operations stay ahead of raw backup metadata.')
->assertDontSee('This backup set has captured items ready for operator review before any separate restore workflow starts.')
->assertDontSee('Usable for review')
->assertScript("(() => { const firstSection = document.querySelector('section.fi-section'); return firstSection !== null && ! firstSection.textContent.includes('Usable for review') && ! firstSection.textContent.includes('Usability') && ! firstSection.textContent.includes('Active'); })()", true)
->assertScript("document.body.textContent.indexOf('Restore-point decision') < document.body.textContent.indexOf('Technical and lifecycle detail')", true)
->assertScript("document.body.textContent.indexOf('Technical and lifecycle detail') < document.body.textContent.indexOf('Included backup items')", true)
->assertNoJavaScriptErrors()
->assertNoConsoleLogs()
->screenshot(true, spec371BrowserScreenshotName('02-backup-set-detail'));
spec371BrowserCopyScreenshot('02-backup-set-detail');
$page
->resize(430, 900)
->assertScript('document.documentElement.scrollWidth <= window.innerWidth', true)
->assertNoJavaScriptErrors()
->screenshot(true, spec371BrowserScreenshotName('03-backup-set-detail-mobile'));
spec371BrowserCopyScreenshot('03-backup-set-detail-mobile');
});
function spec371BrowserLoginUrl(User $user, ManagedEnvironment $tenant, string $redirect): string
{
return route('admin.local.smoke-login', [
'email' => $user->email,
'tenant' => $tenant->external_id,
'workspace' => $tenant->workspace->slug,
'redirect' => $redirect,
]);
}
function spec371BrowserListPath(ManagedEnvironment $tenant): string
{
$url = BackupSetResource::getUrl('index', panel: 'admin', tenant: $tenant);
return parse_url($url, PHP_URL_PATH) ?: '/admin';
}
function spec371BrowserViewPath(ManagedEnvironment $tenant, BackupSet $backupSet): string
{
$url = BackupSetResource::getUrl('view', ['record' => $backupSet], panel: 'admin', tenant: $tenant);
return parse_url($url, PHP_URL_PATH) ?: '/admin';
}
/**
* @param array<string, mixed> $attributes
*/
function spec371BrowserHealthyBackupSet(ManagedEnvironment $tenant, array $attributes = []): BackupSet
{
$backupSet = BackupSet::factory()
->for($tenant)
->create(array_merge([
'name' => 'Spec 371 Browser Healthy Backup',
'status' => 'completed',
'item_count' => 1,
'completed_at' => now()->subMinutes(30),
'metadata' => [],
], $attributes));
BackupItem::factory()
->for($tenant)
->for($backupSet)
->create([
'payload' => ['id' => 'spec-371-browser-policy'],
'metadata' => [],
'assignments' => [],
]);
return $backupSet;
}
function spec371BrowserSourceOperation(ManagedEnvironment $tenant, User $user, BackupSet $backupSet): OperationRun
{
return OperationRun::factory()
->forTenant($tenant)
->withUser($user)
->create([
'type' => OperationRunType::BackupScheduleExecute->value,
'status' => OperationRunStatus::Completed->value,
'outcome' => OperationRunOutcome::Succeeded->value,
'completed_at' => now()->subMinutes(20),
'context' => [
'backup_set_id' => (int) $backupSet->getKey(),
],
]);
}
function spec371BrowserScreenshotName(string $name): string
{
return 'spec371-backup-set-productization-'.$name;
}
function spec371BrowserCopyScreenshot(string $name): void
{
$filename = spec371BrowserScreenshotName($name).'.png';
$source = base_path('tests/Browser/Screenshots/'.$filename);
$targetDirectory = repo_path('specs/371-core-operator-view-surfaces-productization/artifacts/screenshots');
if (! is_dir($targetDirectory)) {
@mkdir($targetDirectory, 0755, true);
}
if (! is_dir($targetDirectory) || ! is_writable($targetDirectory)) {
return;
}
if (! is_file($source)) {
$source = \Pest\Browser\Support\Screenshot::path($filename);
}
if (is_file($source)) {
@copy($source, $targetDirectory.DIRECTORY_SEPARATOR.$filename);
}
}