actingAs($user); $schedule = BackupSchedule::query()->create([ 'tenant_id' => $tenant->id, 'name' => 'Daily 10:00', 'is_enabled' => true, 'timezone' => 'UTC', 'frequency' => 'daily', 'time_of_day' => '10:00:00', 'days_of_week' => null, 'policy_types' => ['deviceConfiguration'], 'include_foundations' => true, 'retention_keep_last' => 30, 'next_run_at' => null, ]); $run = BackupScheduleRun::query()->create([ 'backup_schedule_id' => $schedule->id, 'tenant_id' => $tenant->id, 'scheduled_for' => CarbonImmutable::now('UTC')->startOfMinute(), 'status' => BackupScheduleRun::STATUS_RUNNING, ]); app()->bind(PolicySyncService::class, fn () => new class extends PolicySyncService { public function __construct() {} public function syncPoliciesWithReport($tenant, ?array $supportedTypes = null): array { return ['synced' => [], 'failures' => []]; } }); $backupSet = BackupSet::factory()->create([ 'tenant_id' => $tenant->id, 'status' => 'completed', 'item_count' => 0, ]); app()->bind(BackupService::class, fn () => new class($backupSet) extends BackupService { public function __construct(private readonly BackupSet $backupSet) {} public function createBackupSet($tenant, $policyIds, ?string $actorEmail = null, ?string $actorName = null, ?string $name = null, bool $includeAssignments = false, bool $includeScopeTags = false, bool $includeFoundations = false): BackupSet { return $this->backupSet; } }); Cache::flush(); (new RunBackupScheduleJob($run->id))->handle( app(PolicySyncService::class), app(BackupService::class), app(\App\Services\BackupScheduling\PolicyTypeResolver::class), app(\App\Services\BackupScheduling\ScheduleTimeService::class), app(\App\Services\Intune\AuditLogger::class), app(\App\Services\BackupScheduling\RunErrorMapper::class), app(BulkOperationService::class), ); $run->refresh(); expect($run->status)->toBe(BackupScheduleRun::STATUS_SUCCESS); expect($run->backup_set_id)->toBe($backupSet->id); }); it('skips runs when all policy types are unknown', function () { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 1, 5, 10, 0, 30, 'UTC')); [$user, $tenant] = createUserWithTenant(role: 'owner'); $this->actingAs($user); $schedule = BackupSchedule::query()->create([ 'tenant_id' => $tenant->id, 'name' => 'Daily 10:00', 'is_enabled' => true, 'timezone' => 'UTC', 'frequency' => 'daily', 'time_of_day' => '10:00:00', 'days_of_week' => null, 'policy_types' => ['definitelyNotARealPolicyType'], 'include_foundations' => true, 'retention_keep_last' => 30, 'next_run_at' => null, ]); $run = BackupScheduleRun::query()->create([ 'backup_schedule_id' => $schedule->id, 'tenant_id' => $tenant->id, 'scheduled_for' => CarbonImmutable::now('UTC')->startOfMinute(), 'status' => BackupScheduleRun::STATUS_RUNNING, ]); Cache::flush(); (new RunBackupScheduleJob($run->id))->handle( app(PolicySyncService::class), app(BackupService::class), app(\App\Services\BackupScheduling\PolicyTypeResolver::class), app(\App\Services\BackupScheduling\ScheduleTimeService::class), app(\App\Services\Intune\AuditLogger::class), app(\App\Services\BackupScheduling\RunErrorMapper::class), app(BulkOperationService::class), ); $run->refresh(); expect($run->status)->toBe(BackupScheduleRun::STATUS_SKIPPED); expect($run->error_code)->toBe('UNKNOWN_POLICY_TYPE'); expect($run->backup_set_id)->toBeNull(); });