122 lines
5.1 KiB
PHP
122 lines
5.1 KiB
PHP
<?php
|
|
|
|
use App\Filament\Resources\BackupScheduleResource;
|
|
use App\Filament\Resources\BackupScheduleResource\Pages\ListBackupSchedules;
|
|
use App\Jobs\RunBackupScheduleJob;
|
|
use App\Models\BackupSchedule;
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\OperationRun;
|
|
use Filament\Actions\Action;
|
|
use Filament\Facades\Filament;
|
|
use Filament\Tables\Filters\TrashedFilter;
|
|
use Illuminate\Support\Facades\Queue;
|
|
use Livewire\Livewire;
|
|
|
|
function spec401BackupSchedule(ManagedEnvironment $tenant, array $attributes = []): BackupSchedule
|
|
{
|
|
return BackupSchedule::query()->create(array_merge([
|
|
'managed_environment_id' => $tenant->id,
|
|
'name' => 'Spec 401 backup schedule',
|
|
'is_enabled' => true,
|
|
'timezone' => 'UTC',
|
|
'frequency' => 'daily',
|
|
'time_of_day' => '01:00:00',
|
|
'days_of_week' => null,
|
|
'policy_types' => ['deviceConfiguration'],
|
|
'include_foundations' => true,
|
|
'retention_keep_last' => 30,
|
|
], $attributes));
|
|
}
|
|
|
|
test('backup schedule high-impact row actions require confirmation before side effects', function () {
|
|
Queue::fake([RunBackupScheduleJob::class]);
|
|
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$activeSchedule = spec401BackupSchedule($tenant, ['name' => 'Spec 401 active schedule']);
|
|
$archivedSchedule = spec401BackupSchedule($tenant, [
|
|
'name' => 'Spec 401 archived schedule',
|
|
'is_enabled' => false,
|
|
]);
|
|
$archivedSchedule->delete();
|
|
|
|
$this->actingAs($user);
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$component = Livewire::test(ListBackupSchedules::class)
|
|
->assertTableActionExists('runNow', fn (Action $action): bool => $action->isConfirmationRequired(), $activeSchedule)
|
|
->mountTableAction('runNow', $activeSchedule);
|
|
|
|
expect($component->instance()->getMountedAction()?->getName())->toBe('runNow')
|
|
->and($component->instance()->getMountedAction()?->isConfirmationRequired())->toBeTrue();
|
|
expect(OperationRun::query()->where('managed_environment_id', $tenant->id)->count())->toBe(0);
|
|
Queue::assertNothingPushed();
|
|
|
|
$component->unmountTableAction();
|
|
|
|
$component
|
|
->assertTableActionExists('retry', fn (Action $action): bool => $action->isConfirmationRequired(), $activeSchedule)
|
|
->mountTableAction('retry', $activeSchedule);
|
|
|
|
expect($component->instance()->getMountedAction()?->getName())->toBe('retry')
|
|
->and($component->instance()->getMountedAction()?->isConfirmationRequired())->toBeTrue();
|
|
expect(OperationRun::query()->where('managed_environment_id', $tenant->id)->count())->toBe(0);
|
|
Queue::assertNothingPushed();
|
|
|
|
$component->unmountTableAction();
|
|
|
|
$trashedSchedule = BackupSchedule::withTrashed()->findOrFail($archivedSchedule->id);
|
|
|
|
$component = Livewire::test(ListBackupSchedules::class)
|
|
->filterTable(TrashedFilter::class, false)
|
|
->assertTableActionExists('restore', fn (Action $action): bool => $action->isConfirmationRequired(), $trashedSchedule)
|
|
->mountTableAction('restore', $trashedSchedule);
|
|
|
|
expect($component->instance()->getMountedAction()?->getName())->toBe('restore')
|
|
->and($component->instance()->getMountedAction()?->isConfirmationRequired())->toBeTrue();
|
|
expect(BackupSchedule::withTrashed()->findOrFail($archivedSchedule->id)->trashed())->toBeTrue();
|
|
|
|
$this->assertDatabaseMissing('audit_logs', [
|
|
'managed_environment_id' => $tenant->id,
|
|
'action' => 'backup_schedule.restored',
|
|
'resource_type' => 'backup_schedule',
|
|
'resource_id' => (string) $archivedSchedule->id,
|
|
]);
|
|
});
|
|
|
|
test('backup schedule high-impact bulk actions require confirmation before side effects', function () {
|
|
Queue::fake([RunBackupScheduleJob::class]);
|
|
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$scheduleA = spec401BackupSchedule($tenant, ['name' => 'Spec 401 bulk schedule A']);
|
|
$scheduleB = spec401BackupSchedule($tenant, ['name' => 'Spec 401 bulk schedule B']);
|
|
|
|
$this->actingAs($user);
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$component = Livewire::test(ListBackupSchedules::class)
|
|
->assertTableBulkActionExists('bulk_run_now')
|
|
->mountTableBulkAction('bulk_run_now', collect([$scheduleA, $scheduleB]))
|
|
->assertTableBulkActionMounted('bulk_run_now');
|
|
|
|
expect($component->instance()->getMountedAction()?->isConfirmationRequired())->toBeTrue();
|
|
expect(OperationRun::query()->where('managed_environment_id', $tenant->id)->count())->toBe(0);
|
|
Queue::assertNothingPushed();
|
|
|
|
$component->unmountAction();
|
|
|
|
$component = Livewire::test(ListBackupSchedules::class)
|
|
->assertTableBulkActionExists('bulk_retry')
|
|
->mountTableBulkAction('bulk_retry', collect([$scheduleA, $scheduleB]))
|
|
->assertTableBulkActionMounted('bulk_retry');
|
|
|
|
expect($component->instance()->getMountedAction()?->isConfirmationRequired())->toBeTrue();
|
|
expect(OperationRun::query()->where('managed_environment_id', $tenant->id)->count())->toBe(0);
|
|
Queue::assertNothingPushed();
|
|
});
|
|
|
|
test('backup schedules keep global search disabled for this proof pack', function () {
|
|
expect(BackupScheduleResource::canGloballySearch())->toBeFalse();
|
|
});
|