## Summary - finalize the restore create wizard productization across safety, validation, preview, and confirmation steps - refine the restore presenter output and Blade component rendering for clearer proof, scope, resolver, and execution-readiness states - add and update feature and browser coverage plus Spec 333 artifacts and screenshots ## Testing - Not run as part of this commit/PR task Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #403
206 lines
7.3 KiB
PHP
206 lines
7.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Resources\RestoreRunResource\Presenters\RestoreRunCreatePresenter;
|
|
use App\Models\BackupItem;
|
|
use App\Models\BackupSet;
|
|
use App\Models\Policy;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('recomputes the restore create presenter contract from current database state', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
$this->actingAs($user);
|
|
ensureDefaultProviderConnection($tenant, 'microsoft');
|
|
|
|
$policy = Policy::create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'external_id' => 'spec332-presenter-policy',
|
|
'policy_type' => 'deviceConfiguration',
|
|
'display_name' => 'Spec332 Presenter Policy',
|
|
'platform' => 'windows',
|
|
'metadata' => [],
|
|
]);
|
|
|
|
$backupSet = BackupSet::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'name' => 'Spec332 Presenter Backup',
|
|
'status' => 'completed',
|
|
'item_count' => 1,
|
|
]);
|
|
|
|
$backupItem = 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,
|
|
'payload' => [],
|
|
'assignments' => [],
|
|
'metadata' => [
|
|
'displayName' => 'Spec332 Metadata Only Policy',
|
|
'snapshot_source' => 'metadata_only',
|
|
'warnings' => ['metadata only fallback'],
|
|
],
|
|
]);
|
|
|
|
$wizardData = [
|
|
'backup_set_id' => (int) $backupSet->getKey(),
|
|
'scope_mode' => 'all',
|
|
'backup_item_ids' => [],
|
|
'group_mapping' => [],
|
|
];
|
|
|
|
$first = RestoreRunCreatePresenter::contract(
|
|
data: $wizardData,
|
|
currentStep: 1,
|
|
compactFlow: false,
|
|
tenant: $tenant,
|
|
user: $user,
|
|
);
|
|
|
|
$firstSummary = data_get($first, 'processFlow.steps.0.summary');
|
|
|
|
expect($firstSummary)
|
|
->toBeString()
|
|
->toContain('does not contain a usable captured item yet')
|
|
->and(data_get($first, 'decisionCard.status'))->toBe('Source not usable')
|
|
->and(data_get($first, 'decisionCard.nextAction'))->toBe('Select another backup set.');
|
|
|
|
$backupItem->update([
|
|
'payload' => [
|
|
'id' => 'spec332-presenter-policy',
|
|
'displayName' => 'Spec332 Presenter Policy',
|
|
'settings' => ['foo' => 'bar'],
|
|
],
|
|
'metadata' => [
|
|
'displayName' => 'Spec332 Presenter Policy',
|
|
],
|
|
]);
|
|
|
|
$second = RestoreRunCreatePresenter::contract(
|
|
data: $wizardData,
|
|
currentStep: 1,
|
|
compactFlow: false,
|
|
tenant: $tenant,
|
|
user: $user,
|
|
);
|
|
|
|
$secondSummary = data_get($second, 'processFlow.steps.0.summary');
|
|
|
|
expect($secondSummary)
|
|
->toBeString()
|
|
->toContain('A usable source backup is selected for this restore draft.')
|
|
->not->toContain('does not contain a usable captured item yet')
|
|
->and(data_get($second, 'decisionCard.status'))->toBe('Source selected')
|
|
->and(data_get($second, 'decisionCard.reason'))->toBe('A usable source backup is selected.')
|
|
->and(data_get($second, 'decisionCard.impact'))->toBe('Scope, validation, and preview must still prove this draft before confirmation or real execution.')
|
|
->and(data_get($second, 'decisionCard.tone'))->toBe('success')
|
|
->and(data_get($second, 'decisionCard.nextAction'))->toBe('Continue to scope.')
|
|
->and(data_get($second, 'backupQualityCard.status'))->toBe('Available')
|
|
->and(data_get($second, 'backupQualityCard.tone'))->toBe('success')
|
|
->and(data_get($second, 'backupQualityCard.summary'))->toBe('No degradations were detected across 1 captured item.');
|
|
});
|
|
|
|
it('does not leak presenter state between independent restore draft contracts', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
$this->actingAs($user);
|
|
ensureDefaultProviderConnection($tenant, 'microsoft');
|
|
|
|
$policy = Policy::create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'external_id' => 'spec332-presenter-policy-b',
|
|
'policy_type' => 'deviceConfiguration',
|
|
'display_name' => 'Spec332 Presenter Policy B',
|
|
'platform' => 'windows',
|
|
'metadata' => [],
|
|
]);
|
|
|
|
$metadataOnlyBackup = BackupSet::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'name' => 'Spec332 Presenter Metadata Backup',
|
|
'status' => 'completed',
|
|
'item_count' => 1,
|
|
]);
|
|
|
|
BackupItem::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'backup_set_id' => (int) $metadataOnlyBackup->getKey(),
|
|
'policy_id' => (int) $policy->getKey(),
|
|
'policy_identifier' => $policy->external_id,
|
|
'policy_type' => $policy->policy_type,
|
|
'platform' => $policy->platform,
|
|
'payload' => [],
|
|
'assignments' => [],
|
|
'metadata' => [
|
|
'displayName' => 'Spec332 Metadata Only Policy',
|
|
'snapshot_source' => 'metadata_only',
|
|
],
|
|
]);
|
|
|
|
$first = RestoreRunCreatePresenter::contract(
|
|
data: [
|
|
'backup_set_id' => (int) $metadataOnlyBackup->getKey(),
|
|
'scope_mode' => 'all',
|
|
'backup_item_ids' => [],
|
|
'group_mapping' => [],
|
|
],
|
|
currentStep: 1,
|
|
compactFlow: false,
|
|
tenant: $tenant,
|
|
user: $user,
|
|
);
|
|
|
|
expect(data_get($first, 'processFlow.steps.0.summary'))
|
|
->toBeString()
|
|
->toContain('does not contain a usable captured item yet')
|
|
->and(data_get($first, 'decisionCard.status'))->toBe('Source not usable');
|
|
|
|
$usableBackup = BackupSet::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'name' => 'Spec332 Presenter Usable Backup',
|
|
'status' => 'completed',
|
|
'item_count' => 1,
|
|
]);
|
|
|
|
BackupItem::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'backup_set_id' => (int) $usableBackup->getKey(),
|
|
'policy_id' => (int) $policy->getKey(),
|
|
'policy_identifier' => $policy->external_id,
|
|
'policy_type' => $policy->policy_type,
|
|
'platform' => $policy->platform,
|
|
'payload' => [
|
|
'id' => 'spec332-presenter-policy-b',
|
|
'displayName' => 'Spec332 Presenter Policy B',
|
|
'settings' => ['foo' => 'bar'],
|
|
],
|
|
'assignments' => [],
|
|
'metadata' => [
|
|
'displayName' => 'Spec332 Presenter Policy B',
|
|
],
|
|
]);
|
|
|
|
$second = RestoreRunCreatePresenter::contract(
|
|
data: [
|
|
'backup_set_id' => (int) $usableBackup->getKey(),
|
|
'scope_mode' => 'all',
|
|
'backup_item_ids' => [],
|
|
'group_mapping' => [],
|
|
],
|
|
currentStep: 1,
|
|
compactFlow: false,
|
|
tenant: $tenant,
|
|
user: $user,
|
|
);
|
|
|
|
expect(data_get($second, 'processFlow.steps.0.summary'))
|
|
->toBeString()
|
|
->toContain('A usable source backup is selected for this restore draft.')
|
|
->not->toContain('does not contain a usable captured item yet')
|
|
->and(data_get($second, 'decisionCard.status'))->toBe('Source selected');
|
|
});
|