Implemented the final operator workflow for the Governance Inbox. This includes refactoring the inbox page, updating finding resources, adding UI enforcement policies, updating related blade views, and adding comprehensive tests for operator workflow and scope contracts. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #418
112 lines
4.6 KiB
PHP
112 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
|
|
use App\Models\Finding;
|
|
use App\Models\FindingException;
|
|
use App\Services\Findings\FindingRiskGovernanceResolver;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Filament\Facades\Filament;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('shows only entitled tenants in the canonical queue and supports tenant and validity filters', function (): void {
|
|
[$approver, $tenantA] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
|
|
$tenantB = \App\Models\ManagedEnvironment::factory()->create([
|
|
'workspace_id' => (int) $tenantA->workspace_id,
|
|
]);
|
|
createUserWithTenant(tenant: $tenantB, user: $approver, role: 'owner', workspaceRole: 'manager');
|
|
|
|
$tenantC = \App\Models\ManagedEnvironment::factory()->create([
|
|
'workspace_id' => (int) $tenantA->workspace_id,
|
|
]);
|
|
|
|
$makeException = function (\App\Models\ManagedEnvironment $tenant, array $attributes): FindingException {
|
|
[$requester] = createUserWithTenant(tenant: $tenant, role: 'owner');
|
|
$finding = Finding::factory()->for($tenant)->create();
|
|
|
|
return FindingException::query()->create(array_merge([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'finding_id' => (int) $finding->getKey(),
|
|
'requested_by_user_id' => (int) $requester->getKey(),
|
|
'owner_user_id' => (int) $requester->getKey(),
|
|
'status' => FindingException::STATUS_PENDING,
|
|
'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT,
|
|
'request_reason' => 'Queue visibility test',
|
|
'requested_at' => now()->subDays(4),
|
|
'review_due_at' => now()->addDays(3),
|
|
'evidence_summary' => ['reference_count' => 0],
|
|
], $attributes));
|
|
};
|
|
|
|
$expiring = $makeException($tenantA, [
|
|
'status' => FindingException::STATUS_ACTIVE,
|
|
'current_validity_state' => FindingException::VALIDITY_VALID,
|
|
'effective_from' => now()->subDays(3),
|
|
'approved_at' => now()->subDays(3),
|
|
'expires_at' => now()->addDays(2),
|
|
]);
|
|
app(FindingRiskGovernanceResolver::class)->syncExceptionState($expiring);
|
|
|
|
$rejected = $makeException($tenantB, [
|
|
'status' => FindingException::STATUS_REJECTED,
|
|
'current_validity_state' => FindingException::VALIDITY_REJECTED,
|
|
'rejection_reason' => 'Rejected for queue test',
|
|
'rejected_at' => now()->subDay(),
|
|
]);
|
|
|
|
$unauthorized = $makeException($tenantC, []);
|
|
|
|
$this->actingAs($approver);
|
|
Filament::setCurrentPanel('admin');
|
|
Filament::setTenant(null, true);
|
|
Filament::bootCurrentPanel();
|
|
|
|
session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id);
|
|
|
|
Livewire::test(FindingExceptionsQueue::class)
|
|
->assertCanSeeTableRecords([$expiring, $rejected])
|
|
->assertCanNotSeeTableRecords([$unauthorized])
|
|
->filterTable('managed_environment_id', (string) $tenantB->getKey())
|
|
->assertCanSeeTableRecords([$rejected])
|
|
->assertCanNotSeeTableRecords([$expiring])
|
|
->filterTable('status', FindingException::STATUS_REJECTED)
|
|
->assertCanSeeTableRecords([$rejected]);
|
|
|
|
Livewire::withQueryParams([
|
|
'tenant' => (string) $tenantB->external_id,
|
|
])
|
|
->test(FindingExceptionsQueue::class)
|
|
->assertSet('tableFilters.managed_environment_id.value', null)
|
|
->assertActionHidden('view_tenant_register');
|
|
|
|
$filtersComponent = Livewire::test(FindingExceptionsQueue::class);
|
|
$queueInstance = $filtersComponent->instance();
|
|
session()->forget([
|
|
$queueInstance->getTableFiltersSessionKey(),
|
|
$queueInstance->getTableSearchSessionKey(),
|
|
$queueInstance->getTableSortSessionKey(),
|
|
]);
|
|
|
|
Livewire::withQueryParams([
|
|
'exception' => (int) $expiring->getKey(),
|
|
])
|
|
->test(FindingExceptionsQueue::class)
|
|
->assertSet('selectedFindingExceptionId', (int) $expiring->getKey())
|
|
->assertActionVisible('clear_selected_exception')
|
|
->assertActionVisible('open_selected_exception')
|
|
->assertActionVisible('open_selected_finding')
|
|
->assertSee('Queue visibility test')
|
|
->assertSee('Expiring')
|
|
->assertSee($tenantA->name)
|
|
->assertSee('Focused review lane')
|
|
->assertSee('Governance context')
|
|
->assertSee('This accepted-risk record is already active')
|
|
->assertSee('Open exception detail')
|
|
->assertDontSee('This exception is no longer decision-ready');
|
|
});
|