TenantAtlas/apps/platform/tests/Browser/Spec332RestoreRunWizardProductProcessFlowScreenshotsTest.php
Ahmed Darrazi 5773ad582c
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 4m5s
feat: finalize restore create ux productization
2026-05-28 23:58:31 +02:00

388 lines
13 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Resources\RestoreRunResource;
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\EntraGroup;
use App\Models\ManagedEnvironment;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\User;
pest()->browser()->timeout(60_000);
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
function spec332RestoreWizardScreenshot(string $name): string
{
return 'spec332-restore-create-'.$name;
}
function spec332CopyBrowserScreenshot(string $name, ?string $targetFilename = null): void
{
$filename = spec332RestoreWizardScreenshot($name).'.png';
$source = base_path('tests/Browser/Screenshots/'.$filename);
$targetDirectory = repo_path('specs/332-product-process-flow-system-v1/artifacts/screenshots');
$targetFilename ??= $filename;
if (is_dir($targetDirectory) && ! is_writable($targetDirectory)) {
return;
}
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.$targetFilename);
}
}
function spec332RestoreWizardScreenshotsLoginUrl(User $user, ManagedEnvironment $tenant, string $redirect = ''): string
{
return route('admin.local.smoke-login', array_filter([
'email' => $user->email,
'tenant' => $tenant->external_id,
'workspace' => $tenant->workspace->slug,
'redirect' => $redirect,
], static fn (?string $value): bool => filled($value)));
}
function spec332ScreenshotsTenant(): array
{
$tenant = ManagedEnvironment::factory()->create([
'rbac_status' => 'ok',
'rbac_last_checked_at' => now(),
]);
[$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');
ensureDefaultProviderConnection($tenant, 'microsoft');
bindFailHardGraphClient();
return [$user, $tenant];
}
function spec332ScreenshotsRedirect(ManagedEnvironment $tenant): string
{
$redirectBase = RestoreRunResource::getUrl('create', panel: 'admin', tenant: $tenant);
return parse_url($redirectBase, PHP_URL_PATH) ?: '/admin';
}
function spec332ScreenshotsSelectBackupSet($page, BackupSet $backupSet): void
{
$selected = $page->script(<<<JS
(() => {
const select = document.getElementById('form.backup_set_id');
if (! select) {
return false;
}
select.value = '{$backupSet->getKey()}';
select.dispatchEvent(new Event('input', { bubbles: true }));
select.dispatchEvent(new Event('change', { bubbles: true }));
return true;
})()
JS);
expect($selected)->toBeTrue();
}
function spec332ScreenshotsWizardNext($page): void
{
$clicked = $page->script(<<<'JS'
(() => {
const footer = document.querySelector('.fi-sc-wizard-footer');
if (! footer) {
return false;
}
const nextTrigger = footer.querySelector('div[x-on\\:click*="requestNextStep"]');
if (! nextTrigger) {
return false;
}
if (nextTrigger.classList.contains('fi-hidden')) {
return false;
}
nextTrigger.scrollIntoView({ block: 'center' });
nextTrigger.click();
return true;
})()
JS);
expect($clicked)->toBeTrue();
}
function spec332ScreenshotsUsableBackupFixture(ManagedEnvironment $tenant): BackupSet
{
$policy = Policy::create([
'managed_environment_id' => (int) $tenant->getKey(),
'external_id' => 'spec332-screenshots-policy-usable',
'policy_type' => 'deviceConfiguration',
'display_name' => 'Spec332 Screenshots Policy',
'platform' => 'windows',
]);
PolicyVersion::create([
'managed_environment_id' => (int) $tenant->getKey(),
'policy_id' => (int) $policy->getKey(),
'version_number' => 1,
'policy_type' => $policy->policy_type,
'platform' => $policy->platform,
'captured_at' => now(),
'snapshot' => [
'foo' => 'current',
],
'metadata' => [],
'assignments' => [],
'scope_tags' => [],
]);
$backupSet = BackupSet::factory()->create([
'managed_environment_id' => (int) $tenant->getKey(),
'name' => 'Spec332 Screenshots Usable Backup',
'status' => 'completed',
'item_count' => 1,
]);
BackupItem::factory()->create([
'managed_environment_id' => (int) $tenant->getKey(),
'backup_set_id' => (int) $backupSet->getKey(),
'policy_id' => (int) $policy->getKey(),
'policy_identifier' => $policy->external_id,
'policy_type' => $policy->policy_type,
'platform' => $policy->platform,
'captured_at' => now(),
'payload' => [
'foo' => 'backup',
'displayName' => 'Spec332 Screenshots Policy',
],
'assignments' => [],
'metadata' => [
'displayName' => 'Spec332 Screenshots Policy',
],
]);
return $backupSet;
}
function spec332ScreenshotsUnresolvedGroupBackupFixture(ManagedEnvironment $tenant): BackupSet
{
$policy = Policy::create([
'managed_environment_id' => (int) $tenant->getKey(),
'external_id' => 'spec332-screenshots-policy-group',
'policy_type' => 'deviceConfiguration',
'display_name' => 'Spec332 Screenshots Group Mapping Policy',
'platform' => 'windows',
]);
$backupSet = BackupSet::factory()->create([
'managed_environment_id' => (int) $tenant->getKey(),
'name' => 'Spec332 Screenshots Group Backup',
'status' => 'completed',
'item_count' => 1,
]);
BackupItem::factory()->create([
'managed_environment_id' => (int) $tenant->getKey(),
'backup_set_id' => (int) $backupSet->getKey(),
'policy_id' => (int) $policy->getKey(),
'policy_identifier' => $policy->external_id,
'policy_type' => $policy->policy_type,
'platform' => $policy->platform,
'captured_at' => now(),
'payload' => [
'foo' => 'backup',
'displayName' => 'Spec332 Screenshots Group Mapping Policy',
],
'assignments' => [[
'target' => [
'@odata.type' => '#microsoft.graph.groupAssignmentTarget',
'groupId' => '11111111-1111-1111-1111-111111111111',
'group_display_name' => 'Spec332 Missing Group',
],
]],
'metadata' => [
'displayName' => 'Spec332 Screenshots Group Mapping Policy',
],
]);
return $backupSet;
}
function spec332ScreenshotsMetadataOnlyFixture(ManagedEnvironment $tenant): BackupSet
{
$policy = Policy::create([
'managed_environment_id' => (int) $tenant->getKey(),
'external_id' => 'spec332-screenshots-policy-metadata-only',
'policy_type' => 'deviceConfiguration',
'display_name' => 'Spec332 Screenshots Metadata Only Policy',
'platform' => 'windows',
]);
$backupSet = BackupSet::factory()->create([
'managed_environment_id' => (int) $tenant->getKey(),
'name' => 'Spec332 Screenshots Metadata-only Backup',
'status' => 'completed',
'item_count' => 1,
]);
BackupItem::factory()->create([
'managed_environment_id' => (int) $tenant->getKey(),
'backup_set_id' => (int) $backupSet->getKey(),
'policy_id' => (int) $policy->getKey(),
'policy_identifier' => $policy->external_id,
'policy_type' => $policy->policy_type,
'platform' => $policy->platform,
'captured_at' => now(),
'payload' => [],
'assignments' => [],
'metadata' => [
'displayName' => 'Spec332 Screenshots Metadata Only Policy',
'snapshot_source' => 'metadata_only',
'warnings' => ['metadata only fallback'],
],
]);
return $backupSet;
}
it('captures step 1 screenshot with a degraded backup selected', function (): void {
[$user, $tenant] = spec332ScreenshotsTenant();
$backupSet = spec332ScreenshotsMetadataOnlyFixture($tenant);
$page = visit(spec332RestoreWizardScreenshotsLoginUrl($user, $tenant, spec332ScreenshotsRedirect($tenant)));
$page->resize(1920, 1200)
->waitForText('Select Backup Set');
spec332ScreenshotsSelectBackupSet($page, $backupSet);
$page->waitForText('Source not usable');
$page->script('window.scrollTo(0, 0);');
$page->screenshot(true, spec332RestoreWizardScreenshot('step-1-backup-selected'));
spec332CopyBrowserScreenshot('step-1-backup-selected', 'step-1-backup-selected.png');
});
it('captures step 2 screenshots for mapping summary + resolver expansion', function (): void {
[$user, $tenant] = spec332ScreenshotsTenant();
$backupSet = spec332ScreenshotsUnresolvedGroupBackupFixture($tenant);
EntraGroup::factory()->for($tenant)->create([
'entra_id' => 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
'display_name' => 'Spec332 Cached Target Group',
'last_seen_at' => now(),
]);
$page = visit(spec332RestoreWizardScreenshotsLoginUrl($user, $tenant, spec332ScreenshotsRedirect($tenant)));
$page->resize(1920, 1200)
->waitForText('Select Backup Set');
spec332ScreenshotsSelectBackupSet($page, $backupSet);
$page->waitForText('Continue to scope and resolve required mappings.');
spec332ScreenshotsWizardNext($page);
$page->waitForText('Resolve target mappings');
$page->script('window.scrollTo(0, 0);');
$page->screenshot(true, spec332RestoreWizardScreenshot('step-2-scope-default'));
spec332CopyBrowserScreenshot('step-2-scope-default', 'step-2-scope-default.png');
$page->script(<<<'JS'
(() => {
const section = document.querySelector('[data-testid="restore-run-mapping-resolver-section"]');
section?.querySelector('.fi-section-header')?.click();
})()
JS);
$page->waitForText('Hide mapping details');
$page->script('window.scrollTo(0, 0);');
$page->screenshot(true, spec332RestoreWizardScreenshot('step-2-resolver-expanded'));
spec332CopyBrowserScreenshot('step-2-resolver-expanded', 'step-2-resolver-expanded.png');
});
it('captures step 3 screenshot when validation is blocked', function (): void {
[$user, $tenant] = spec332ScreenshotsTenant();
$backupSet = spec332ScreenshotsMetadataOnlyFixture($tenant);
$page = visit(spec332RestoreWizardScreenshotsLoginUrl($user, $tenant, spec332ScreenshotsRedirect($tenant)));
$page->resize(1920, 1200)
->waitForText('Select Backup Set');
spec332ScreenshotsSelectBackupSet($page, $backupSet);
$page->waitForText('Source not usable');
spec332ScreenshotsWizardNext($page);
$page->waitForText('Define Restore Scope');
spec332ScreenshotsWizardNext($page);
$page->waitForText('Safety & Conflict Checks');
$page->waitForText('Run checks')
->click('Run checks')
->waitForText('Snapshot completeness');
spec332ScreenshotsWizardNext($page);
$page->waitForText('Validation blocked');
$page->script('window.scrollTo(0, 0);');
$page->screenshot(true, spec332RestoreWizardScreenshot('step-3-validation-blocked'));
spec332CopyBrowserScreenshot('step-3-validation-blocked', 'step-3-validation-blocked.png');
});
it('captures step 4 and 5 screenshots after preview generation', function (): void {
[$user, $tenant] = spec332ScreenshotsTenant();
$backupSet = spec332ScreenshotsUsableBackupFixture($tenant);
$page = visit(spec332RestoreWizardScreenshotsLoginUrl($user, $tenant, spec332ScreenshotsRedirect($tenant)));
$page->resize(1920, 1200)
->waitForText('Select Backup Set');
spec332ScreenshotsSelectBackupSet($page, $backupSet);
$page->waitForText('Source selected');
spec332ScreenshotsWizardNext($page);
$page->waitForText('Define Restore Scope');
spec332ScreenshotsWizardNext($page);
$page->waitForText('Safety & Conflict Checks');
$page->waitForText('Run checks')
->click('Run checks')
->waitForText('Validation passed');
spec332ScreenshotsWizardNext($page);
$page->waitForText('Generate preview')
->click('Generate preview')
->waitForText('Preview details');
$page->script('window.scrollTo(0, 0);');
$page->screenshot(true, spec332RestoreWizardScreenshot('step-4-preview-generated'));
spec332CopyBrowserScreenshot('step-4-preview-generated', 'step-4-preview-generated.png');
spec332ScreenshotsWizardNext($page);
$page->waitForText('Confirm & Execute');
$page->script('window.scrollTo(0, 0);');
$page->screenshot(true, spec332RestoreWizardScreenshot('step-5-confirm-ready'));
spec332CopyBrowserScreenshot('step-5-confirm-ready', 'step-5-confirm-ready.png');
});