215 lines
8.8 KiB
PHP
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');
|
|
}
|
|
});
|