create(); $backupSet = BackupSet::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), ]); $backupItem = BackupItem::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'backup_set_id' => (int) $backupSet->getKey(), 'policy_type' => 'settingsCatalogPolicy', 'policy_identifier' => 'policy-fetch-summary', 'metadata' => [], ]); $operationRun = OperationRun::factory()->for($tenant)->create([ 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'assignments.fetch', 'status' => 'queued', 'outcome' => 'pending', 'summary_counts' => [ 'total' => 99, 'processed' => 99, 'failed' => 99, ], ]); $assignmentBackupService = \Mockery::mock(AssignmentBackupService::class); $assignmentBackupService->shouldReceive('enrichWithAssignments') ->once() ->andReturnUsing(function (BackupItem $item): BackupItem { $metadata = is_array($item->metadata) ? $item->metadata : []; $metadata['assignments_fetch_failed'] = false; $item->update([ 'metadata' => $metadata, 'assignments' => [ ['id' => 'assignment-1'], ], ]); return $item->refresh(); }); $job = new FetchAssignmentsJob( backupItemId: (int) $backupItem->getKey(), tenantExternalId: (string) $tenant->external_id, policyExternalId: (string) $backupItem->policy_identifier, policyPayload: ['id' => (string) $backupItem->policy_identifier], operationRun: $operationRun, ); $job->handle($assignmentBackupService, app(OperationRunService::class)); $operationRun->refresh(); expect($operationRun->status)->toBe('completed') ->and($operationRun->outcome)->toBe('succeeded') ->and($operationRun->summary_counts)->toMatchArray([ 'total' => 1, 'processed' => 1, 'failed' => 0, ]); }); test('restore assignment job persists terminal summary counts and overwrites previous values', function (): void { $tenant = Tenant::factory()->create(); $backupSet = BackupSet::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), ]); $restoreRun = RestoreRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'backup_set_id' => (int) $backupSet->getKey(), ]); $operationRun = OperationRun::factory()->for($tenant)->create([ 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'assignments.restore', 'status' => 'queued', 'outcome' => 'pending', 'summary_counts' => [ 'total' => 88, 'processed' => 88, 'failed' => 88, ], ]); $assignmentRestoreService = \Mockery::mock(AssignmentRestoreService::class); $assignmentRestoreService->shouldReceive('restore') ->once() ->andReturn([ 'outcomes' => [ ['status' => 'success'], ['status' => 'success'], ['status' => 'failed', 'reason' => 'Graph request failed'], ], 'summary' => [ 'success' => 2, 'failed' => 1, 'skipped' => 0, ], ]); $job = new RestoreAssignmentsJob( restoreRunId: (int) $restoreRun->getKey(), tenantId: (int) $tenant->getKey(), policyType: 'settingsCatalogPolicy', policyId: 'policy-restore-summary', assignments: [ ['id' => 'assignment-1'], ['id' => 'assignment-2'], ['id' => 'assignment-3'], ], groupMapping: [], foundationMapping: [], operationRun: $operationRun, ); $job->handle($assignmentRestoreService, app(OperationRunService::class)); $operationRun->refresh(); expect($operationRun->status)->toBe('completed') ->and($operationRun->outcome)->toBe('partially_succeeded') ->and($operationRun->summary_counts)->toMatchArray([ 'total' => 3, 'processed' => 3, 'failed' => 1, ]); });