TenantAtlas/apps/platform/tests/Feature/PortfolioCompare/CrossTenantPromotionExecutionAuditTest.php
Ahmed Darrazi 983abb18a1
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 3m22s
chore: commit workspace changes (automated)
2026-05-02 16:36:21 +02:00

156 lines
6.3 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\CrossTenantComparePage;
use App\Jobs\Operations\CrossTenantPromotionExecutionJob;
use App\Models\AuditLog;
use App\Models\BackupSet;
use App\Models\OperationRun;
use App\Models\PolicyVersion;
use App\Models\RestoreRun;
use App\Services\Audit\WorkspaceAuditLogger;
use App\Services\Intune\RestoreService;
use App\Services\OperationRunService;
use App\Services\Operations\TargetScopeConcurrencyLimiter;
use App\Support\Audit\AuditActionId;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;
use Tests\Feature\Concerns\BuildsPortfolioCompareFixtures;
uses(RefreshDatabase::class, BuildsPortfolioCompareFixtures::class);
it('audits queued promotion execution without creating restore-side writes before the worker starts', function (): void {
Queue::fake();
$fixture = $this->makeCrossTenantCompareFixture();
$this->createPortfolioCompareSubject(
tenant: $fixture['sourceTenant'],
displayName: 'Audit Queue Policy',
snapshot: ['settings' => [['key' => 'audit-queue', 'value' => 1]]],
);
$this->setAdminWorkspaceContext($fixture['user'], $fixture['workspace']);
$policyVersionCount = PolicyVersion::query()->count();
Livewire::withQueryParams([
'source_tenant_id' => (int) $fixture['sourceTenant']->getKey(),
'target_tenant_id' => (int) $fixture['targetTenant']->getKey(),
'policy_type' => ['deviceConfiguration'],
])
->actingAs($fixture['user'])
->test(CrossTenantComparePage::class)
->call('generatePromotionPreflight')
->mountAction('executePromotion')
->callMountedAction()
->assertHasNoActionErrors();
$run = OperationRun::query()->latest('id')->first();
$audit = AuditLog::query()
->where('workspace_id', (int) $fixture['workspace']->getKey())
->where('action', AuditActionId::CrossTenantPromotionExecutionQueued->value)
->latest('id')
->first();
expect($run)->not->toBeNull()
->and($audit)->not->toBeNull()
->and($audit?->status)->toBe('info')
->and($audit?->resource_type)->toBe('operation_run')
->and((int) ($audit?->operation_run_id ?? 0))->toBe((int) $run?->getKey())
->and(data_get($audit?->metadata, 'source_tenant_id'))->toBe((int) $fixture['sourceTenant']->getKey())
->and(data_get($audit?->metadata, 'target_tenant_id'))->toBe((int) $fixture['targetTenant']->getKey())
->and(data_get($audit?->metadata, 'ready_count'))->toBe(1)
->and(data_get($audit?->metadata, 'excluded_count'))->toBe(0)
->and(BackupSet::query()->count())->toBe(0)
->and(RestoreRun::query()->count())->toBe(0)
->and(PolicyVersion::query()->count())->toBe($policyVersionCount);
});
it('audits terminal promotion execution truth after the queued worker completes', function (): void {
Queue::fake();
$fixture = $this->makeCrossTenantCompareFixture();
$this->createPortfolioCompareSubject(
tenant: $fixture['sourceTenant'],
displayName: 'Audit Completion Policy',
snapshot: ['settings' => [['key' => 'audit-complete', 'value' => 1]]],
);
$this->setAdminWorkspaceContext($fixture['user'], $fixture['workspace']);
Livewire::withQueryParams([
'source_tenant_id' => (int) $fixture['sourceTenant']->getKey(),
'target_tenant_id' => (int) $fixture['targetTenant']->getKey(),
'policy_type' => ['deviceConfiguration'],
])
->actingAs($fixture['user'])
->test(CrossTenantComparePage::class)
->call('generatePromotionPreflight')
->mountAction('executePromotion')
->callMountedAction()
->assertHasNoActionErrors();
$run = OperationRun::query()->latest('id')->firstOrFail();
$restoreService = \Mockery::mock(RestoreService::class);
$restoreService->shouldReceive('execute')
->once()
->andReturnUsing(function ($tenant, $backupSet, array $selectedItemIds) {
return RestoreRun::factory()->create([
'tenant_id' => (int) $tenant->getKey(),
'backup_set_id' => (int) $backupSet->getKey(),
'requested_items' => $selectedItemIds,
'results' => [
'items' => [[
'status' => 'applied',
'policy_identifier' => 'audit-complete-policy',
]],
],
'metadata' => [
'succeeded' => count($selectedItemIds),
'failed' => 0,
'partial' => 0,
'skipped' => 0,
],
]);
});
app()->instance(RestoreService::class, $restoreService);
$job = new CrossTenantPromotionExecutionJob($run);
$job->handle(
app(OperationRunService::class),
$restoreService,
app(TargetScopeConcurrencyLimiter::class),
app(WorkspaceAuditLogger::class),
);
$completedAudit = AuditLog::query()
->where('workspace_id', (int) $fixture['workspace']->getKey())
->where('action', AuditActionId::CrossTenantPromotionExecutionCompleted->value)
->latest('id')
->first();
$completedRun = $run->fresh();
$restoreRun = RestoreRun::query()->latest('id')->first();
expect($completedRun)->not->toBeNull()
->and($completedRun?->status)->toBe('completed')
->and($completedRun?->outcome)->toBe('succeeded')
->and($completedAudit)->not->toBeNull()
->and($completedAudit?->status)->toBe('success')
->and($completedAudit?->resource_type)->toBe('operation_run')
->and((int) ($completedAudit?->operation_run_id ?? 0))->toBe((int) $completedRun?->getKey())
->and(data_get($completedAudit?->metadata, 'source_tenant_id'))->toBe((int) $fixture['sourceTenant']->getKey())
->and(data_get($completedAudit?->metadata, 'target_tenant_id'))->toBe((int) $fixture['targetTenant']->getKey())
->and(data_get($completedAudit?->metadata, 'summary_counts.created'))->toBe(1)
->and(data_get($completedAudit?->metadata, 'summary_counts.succeeded'))->toBe(1)
->and(data_get($completedAudit?->metadata, 'restore_run_id'))->toBe((int) $restoreRun?->getKey())
->and(BackupSet::query()->count())->toBe(1)
->and(RestoreRun::query()->count())->toBe(1);
});