TenantAtlas/apps/platform/tests/Feature/Filament/Spec399DashboardInboxTableContractTest.php
Ahmed Darrazi ed66591f2e
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m18s
feat: migrate dashboard inbox table contracts to productized flow
2026-06-22 23:04:26 +02:00

215 lines
8.8 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\Findings\FindingsIntakeQueue;
use App\Filament\Pages\Findings\MyFindingsInbox;
use App\Filament\Pages\Governance\GovernanceInbox;
use App\Filament\Resources\FindingResource;
use App\Filament\Resources\FindingResource\Pages\ListFindings;
use App\Filament\Widgets\Dashboard\RecentOperations;
use App\Models\Finding;
use App\Models\OperationRun;
use App\Support\Filament\TablePaginationProfiles;
use App\Support\ManagedEnvironmentLinks;
use App\Support\OperationRunLinks;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\OperationRunType;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;
uses(RefreshDatabase::class);
function spec399ActingTenantContext(): array
{
[$user, $tenant] = createUserWithTenant(role: 'owner', workspaceRole: 'owner');
test()->actingAs($user);
setAdminPanelContext($tenant);
session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
return [$user, $tenant];
}
function spec399Table(Testable $component): \Filament\Tables\Table
{
return $component->instance()->getTable();
}
it('caps the recent operations dashboard table and removes default operation detail links', function (): void {
[$user, $tenant] = spec399ActingTenantContext();
$operation = OperationRun::factory()->create([
'managed_environment_id' => (int) $tenant->getKey(),
'workspace_id' => (int) $tenant->workspace_id,
'type' => OperationRunType::InventorySync->value,
'status' => OperationRunStatus::Queued->value,
'outcome' => OperationRunOutcome::Pending->value,
]);
$table = spec399Table(Livewire::actingAs($user)->test(RecentOperations::class));
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface())
->and($table->getRecordUrl($operation))->toBeNull()
->and(array_keys($table->getVisibleColumns()))->toBe(['type', 'outcome', 'created_at']);
});
it('renders dashboard, governance, and operations defaults without raw operation proof language', function (): void {
[$user, $tenant] = spec399ActingTenantContext();
OperationRun::factory()->forTenant($tenant)->create([
'type' => OperationRunType::InventorySync->value,
'status' => OperationRunStatus::Completed->value,
'outcome' => OperationRunOutcome::Blocked->value,
'context' => [
'raw_payload' => 'spec399 feature raw payload should stay hidden',
],
'completed_at' => now(),
]);
Finding::factory()->for($tenant)->create([
'workspace_id' => (int) $tenant->workspace_id,
'status' => Finding::STATUS_NEW,
'severity' => Finding::SEVERITY_HIGH,
'owner_user_id' => null,
'assignee_user_id' => null,
'subject_external_id' => 'spec399-feature-source-key',
'evidence_jsonb' => [
'display_name' => 'Spec399 Feature Governance Finding',
],
]);
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
->get(route('admin.workspace.home', ['workspace' => $tenant->workspace]))
->assertOk()
->assertSee('Review recent workspace activity')
->assertSee('data-testid="workspace-recent-operations-disclosure"', false)
->assertDontSee('spec399 feature raw payload should stay hidden');
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
->get(ManagedEnvironmentLinks::viewUrl($tenant))
->assertOk()
->assertDontSee('spec399 feature raw payload should stay hidden');
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
->get(GovernanceInbox::getUrl(panel: 'admin'))
->assertOk()
->assertSee('Governance Inbox')
->assertSee('Primary inbox lanes')
->assertSee('Needs triage')
->assertDontSee('spec399-feature-source-key')
->assertDontSee('spec399 feature raw payload should stay hidden');
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
->get(OperationRunLinks::index($tenant))
->assertOk()
->assertSee('Detail path')
->assertSee('Technical detail available')
->assertSee('Recent operations')
->assertDontSee('Operation #')
->assertDontSee('OperationRuns')
->assertDontSee('Operation detail available')
->assertDontSee('spec399 feature raw payload should stay hidden');
});
it('proves touched findings tables cap product rows before secondary pages', function (): void {
[$user, $tenant] = spec399ActingTenantContext();
$assignedFindings = collect(range(1, 10))
->map(fn (int $index): Finding => Finding::factory()->for($tenant)->create([
'workspace_id' => (int) $tenant->workspace_id,
'status' => Finding::STATUS_NEW,
'owner_user_id' => (int) $user->getKey(),
'assignee_user_id' => (int) $user->getKey(),
'subject_external_id' => sprintf('spec399-assigned-source-%02d', $index),
'created_at' => now()->subMinutes($index),
]));
$intakeFindings = collect(range(1, 10))
->map(fn (int $index): Finding => Finding::factory()->for($tenant)->create([
'workspace_id' => (int) $tenant->workspace_id,
'status' => Finding::STATUS_REOPENED,
'owner_user_id' => null,
'assignee_user_id' => null,
'subject_external_id' => sprintf('spec399-intake-source-%02d', $index),
'created_at' => now()->subMinutes($index + 20),
]));
$environmentList = Livewire::actingAs($user)->test(ListFindings::class);
$environmentList
->assertCanSeeTableRecords($assignedFindings->take(8))
->assertCanNotSeeTableRecords($assignedFindings->slice(8));
$assignedInboxOrder = $assignedFindings
->sortByDesc(fn (Finding $finding): int => (int) $finding->getKey())
->values();
$myFindings = Livewire::actingAs($user)->test(MyFindingsInbox::class);
$myFindings
->assertCanSeeTableRecords($assignedInboxOrder->take(8))
->assertCanNotSeeTableRecords($assignedInboxOrder->slice(8));
setAdminPanelContext();
$intakeInboxOrder = $intakeFindings
->sortByDesc(fn (Finding $finding): int => (int) $finding->getKey())
->values();
$intake = Livewire::actingAs($user)->test(FindingsIntakeQueue::class);
$intake
->assertCanSeeTableRecords($intakeInboxOrder->take(8))
->assertCanNotSeeTableRecords($intakeInboxOrder->slice(8));
});
it('keeps findings list inspection on row click and groups row actions under more', function (): void {
[$user, $tenant] = spec399ActingTenantContext();
$finding = Finding::factory()->for($tenant)->create([
'workspace_id' => (int) $tenant->workspace_id,
]);
$table = spec399Table(Livewire::actingAs($user)->test(ListFindings::class));
$actions = collect($table->getActions());
$topLevelActionNames = $actions
->reject(static fn ($action): bool => $action instanceof ActionGroup)
->map(static fn ($action): ?string => $action instanceof Action ? $action->getName() : null)
->filter()
->values()
->all();
$moreGroup = $actions->first(static fn ($action): bool => $action instanceof ActionGroup);
$moreActionNames = collect($moreGroup?->getActions() ?? [])
->map(static fn ($action): ?string => $action instanceof Action ? $action->getName() : null)
->filter()
->values()
->all();
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface())
->and($table->getRecordUrl($finding))->toBe(FindingResource::getUrl('view', ['record' => $finding], tenant: $tenant))
->and($topLevelActionNames)->toBe([])
->and($moreGroup)->toBeInstanceOf(ActionGroup::class)
->and($moreActionNames)->toContain('primary_drill_down', 'triage', 'assign', 'request_exception');
});
it('caps findings inbox tables and keeps managed environment labels human readable', function (): void {
[$user] = spec399ActingTenantContext();
foreach ([MyFindingsInbox::class, FindingsIntakeQueue::class] as $pageClass) {
setAdminPanelContext();
$table = spec399Table(Livewire::actingAs($user)->test($pageClass));
expect($table->getPaginationPageOptions())->toBe(TablePaginationProfiles::productSurface())
->and($table->getColumn('tenant.name')?->getLabel())->toBe('Managed environment')
->and($table->getFilter('managed_environment_id')?->getLabel())->toBe('Managed environment');
}
});