Some checks failed
Main Confidence / confidence (push) Failing after 56s
Automated PR: merge branch 248-private-ai-policy-foundation into dev (created by Copilot) Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #288
110 lines
3.9 KiB
PHP
110 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\System\Pages\Ops\Controls;
|
|
use App\Models\AuditLog;
|
|
use App\Models\OperationalControlActivation;
|
|
use App\Models\PlatformUser;
|
|
use App\Models\Tenant;
|
|
use App\Models\Workspace;
|
|
use App\Support\Audit\AuditActionId;
|
|
use App\Support\Auth\PlatformCapabilities;
|
|
use Filament\Actions\Action;
|
|
use Filament\Facades\Filament;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function (): void {
|
|
Filament::setCurrentPanel('system');
|
|
Filament::bootCurrentPanel();
|
|
});
|
|
|
|
function makeAiControlsManager(): PlatformUser
|
|
{
|
|
return PlatformUser::factory()->create([
|
|
'capabilities' => [
|
|
PlatformCapabilities::ACCESS_SYSTEM_PANEL,
|
|
PlatformCapabilities::OPS_CONTROLS_MANAGE,
|
|
],
|
|
'is_active' => true,
|
|
]);
|
|
}
|
|
|
|
it('pauses and resumes ai execution through the global-only controls card', function (): void {
|
|
$workspaceA = Workspace::factory()->create(['name' => 'Acme']);
|
|
$workspaceB = Workspace::factory()->create(['name' => 'Bravo']);
|
|
|
|
Tenant::factory()->count(2)->create(['workspace_id' => (int) $workspaceA->getKey()]);
|
|
Tenant::factory()->count(1)->create(['workspace_id' => (int) $workspaceB->getKey()]);
|
|
|
|
$user = makeAiControlsManager();
|
|
$this->actingAs($user, 'platform');
|
|
|
|
$this->get(Controls::getUrl(panel: 'system'))
|
|
->assertSuccessful()
|
|
->assertSee("mountAction('pause_ai_execution')", escape: false);
|
|
|
|
$component = Livewire::test(Controls::class)
|
|
->assertActionExists('pause_ai_execution', fn (Action $action): bool => $action->isConfirmationRequired())
|
|
->assertActionExists('resume_ai_execution', fn (Action $action): bool => $action->isConfirmationRequired())
|
|
->assertActionExists('view_history_ai_execution', fn (Action $action): bool => $action->getLabel() === 'View AI execution history');
|
|
|
|
$summary = $component->instance()->controlSummary('ai.execution');
|
|
$preview = $component->instance()->scopeImpactPreview('ai.execution', 'global', null);
|
|
|
|
expect($summary['label'])->toBe('AI execution')
|
|
->and($summary['supported_scopes'])->toBe(['global'])
|
|
->and($summary['effective_state'])->toBe('enabled')
|
|
->and($preview['summary'])->toContain('AI execution')
|
|
->and($preview['workspace_count'])->toBe(2)
|
|
->and($preview['tenant_count'])->toBe(3);
|
|
|
|
$component
|
|
->callAction('pause_ai_execution', data: [
|
|
'scope_type' => 'global',
|
|
'reason_text' => 'Paused for AI rollout review.',
|
|
'expires_at' => now()->addDay()->toDateTimeString(),
|
|
])
|
|
->assertNotified('AI execution paused');
|
|
|
|
$activation = OperationalControlActivation::query()
|
|
->forControl('ai.execution')
|
|
->forGlobalScope()
|
|
->first();
|
|
|
|
expect($activation)->not->toBeNull()
|
|
->and($activation?->reason_text)->toBe('Paused for AI rollout review.');
|
|
|
|
$pausedSummary = $component->instance()->controlSummary('ai.execution');
|
|
|
|
expect($pausedSummary['effective_state'])->toBe('paused')
|
|
->and($pausedSummary['state_label'])->toBe('Paused globally');
|
|
|
|
$component
|
|
->callAction('resume_ai_execution', data: [
|
|
'scope_type' => 'global',
|
|
])
|
|
->assertNotified('AI execution resumed');
|
|
|
|
expect(OperationalControlActivation::query()
|
|
->forControl('ai.execution')
|
|
->forGlobalScope()
|
|
->count())->toBe(0);
|
|
|
|
$audits = AuditLog::query()
|
|
->whereIn('action', [
|
|
AuditActionId::OperationalControlPaused->value,
|
|
AuditActionId::OperationalControlResumed->value,
|
|
])
|
|
->where('metadata->control_key', 'ai.execution')
|
|
->orderBy('id')
|
|
->get();
|
|
|
|
expect($audits)->toHaveCount(2)
|
|
->and($audits[0]->workspace_id)->toBeNull()
|
|
->and($audits[1]->workspace_id)->toBeNull();
|
|
});
|