TenantAtlas/apps/platform/tests/Feature/Filament/BaselineCompareMatrixPageTest.php
ahmido bef9020159 feat: implement spec 193 monitoring action hierarchy (#227)
## Summary
- codify Spec 193 as an explicit monitoring/workbench surface inventory with validator and guard coverage
- refactor the Finding Exceptions Queue, Operations landing, and tenantless operation viewer into clearer context, navigation, utility, drilldown, and focused-work lanes
- align Alerts, Audit Log, and Alert Deliveries with quiet origin-context handling while preserving calm reference surfaces and the explicit Tenant Diagnostics exception
- add focused feature coverage, guard coverage, browser smoke coverage, and the full spec artifacts for Spec 193

## Verification
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php tests/Feature/Guards/ActionSurfaceValidatorTest.php tests/Feature/Guards/Spec193MonitoringSurfaceHierarchyGuardTest.php tests/Feature/OpsUx/OperateHubShellTest.php tests/Feature/Operations/TenantlessOperationRunViewerTest.php tests/Feature/Monitoring/FindingExceptionsQueueHierarchyTest.php tests/Browser/Spec193MonitoringSurfaceHierarchySmokeTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- integrated-browser smoke pass over queue, operations, operation detail, alerts, audit log, and tenant diagnostics

## Notes
- Livewire v4 / Filament v5 stack unchanged
- no provider-registration changes; Laravel 11+ provider registration remains in `bootstrap/providers.php`
- no new global-search behavior was introduced
- destructive and governance-changing actions keep their existing confirmation and authorization semantics
- no new assets or migrations were added

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #227
2026-04-12 10:48:00 +00:00

282 lines
10 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\BaselineCompareMatrix;
use App\Filament\Resources\BaselineProfileResource;
use App\Models\User;
use App\Models\WorkspaceMembership;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\Feature\Concerns\BuildsBaselineCompareMatrixFixtures;
uses(RefreshDatabase::class, BuildsBaselineCompareMatrixFixtures::class);
it('renders dense auto mode with sticky subject behavior and compact support surfaces', function (): void {
$fixture = $this->makeBaselineCompareMatrixFixture();
$run = $this->makeBaselineCompareMatrixRun(
$fixture['visibleTenantTwo'],
$fixture['profile'],
$fixture['snapshot'],
);
$this->makeBaselineCompareMatrixRun(
$fixture['visibleTenant'],
$fixture['profile'],
$fixture['snapshot'],
);
$this->makeBaselineCompareMatrixFinding(
$fixture['visibleTenantTwo'],
$fixture['profile'],
$run,
'wifi-corp-profile',
);
$session = $this->setAdminWorkspaceContext($fixture['user'], $fixture['workspace'], $fixture['visibleTenant']);
$this->withSession($session)
->get(BaselineProfileResource::compareMatrixUrl($fixture['profile']))
->assertOk()
->assertSee('Visible-set baseline')
->assertSee('Requested: Auto mode. Resolved: Dense mode.')
->assertDontSee('Monitoring landing')
->assertDontSee('Focused review lane')
->assertDontSee('fonts/filament/filament/inter/inter-latin-wght-normal', false)
->assertDontSee('Passive auto-refresh every 5 seconds')
->assertSee('Grouped legend')
->assertSee('Apply filters')
->assertSee('Compact unlocks at one visible tenant')
->assertSee('Dense multi-tenant scan')
->assertSee('Open finding')
->assertSee('More follow-up')
->assertSee('data-testid="baseline-compare-matrix-dense-shell"', false)
->assertSee('sticky left-0', false);
});
it('stages heavy filter changes until apply and preserves mode and subject continuity in drilldown urls', function (): void {
$fixture = $this->makeBaselineCompareMatrixFixture();
$run = $this->makeBaselineCompareMatrixRun(
$fixture['visibleTenant'],
$fixture['profile'],
$fixture['snapshot'],
);
$finding = $this->makeBaselineCompareMatrixFinding(
$fixture['visibleTenant'],
$fixture['profile'],
$run,
'wifi-corp-profile',
);
$this->makeBaselineCompareMatrixRun(
$fixture['visibleTenantTwo'],
$fixture['profile'],
$fixture['snapshot'],
);
$this->setAdminWorkspaceContext($fixture['user'], $fixture['workspace'], $fixture['visibleTenant']);
$component = Livewire::withQueryParams([
'mode' => 'dense',
'policy_type' => ['deviceConfiguration'],
'state' => ['differ'],
'severity' => ['high'],
'subject_key' => 'wifi-corp-profile',
])
->actingAs($fixture['user'])
->test(BaselineCompareMatrix::class, ['record' => $fixture['profile']->getKey()])
->assertSet('requestedMode', 'dense')
->assertSee('Requested: Dense mode. Resolved: Dense mode.')
->assertSee('Focused subject')
->assertSee('wifi-corp-profile');
expect($component->instance()->hasStagedFilterChanges())->toBeFalse();
$component
->set('draftSelectedPolicyTypes', ['compliancePolicy'])
->set('draftSelectedStates', ['match'])
->set('draftSelectedSeverities', [])
->set('draftTenantSort', 'freshness_urgency')
->set('draftSubjectSort', 'display_name')
->assertSee('Draft filters are staged');
expect($component->instance()->hasStagedFilterChanges())->toBeTrue();
$component->call('applyFilters')->assertRedirect(
BaselineProfileResource::compareMatrixUrl($fixture['profile']).'?mode=dense&policy_type%5B0%5D=compliancePolicy&state%5B0%5D=match&tenant_sort=freshness_urgency&subject_sort=display_name&subject_key=wifi-corp-profile'
);
$applied = Livewire::withQueryParams([
'mode' => 'dense',
'policy_type' => ['compliancePolicy'],
'state' => ['match'],
'tenant_sort' => 'freshness_urgency',
'subject_sort' => 'display_name',
'subject_key' => 'wifi-corp-profile',
])
->actingAs($fixture['user'])
->test(BaselineCompareMatrix::class, ['record' => $fixture['profile']->getKey()]);
$tenantCompareUrl = $applied->instance()->tenantCompareUrl((int) $fixture['visibleTenant']->getKey(), 'wifi-corp-profile');
$findingUrl = $applied->instance()->findingUrl((int) $fixture['visibleTenant']->getKey(), (int) $finding->getKey(), 'wifi-corp-profile');
expect(urldecode((string) $tenantCompareUrl))->toContain('mode=dense')
->and(urldecode((string) $tenantCompareUrl))->toContain('subject_key=wifi-corp-profile')
->and(urldecode((string) $findingUrl))->toContain('mode=dense')
->and($findingUrl)->toContain('nav%5Bsource_surface%5D=baseline_compare_matrix');
$applied->call('resetFilters')->assertRedirect(
BaselineProfileResource::compareMatrixUrl($fixture['profile']).'?mode=dense'
);
});
it('resolves auto to compact for the visible-set-only single-tenant edge case and still allows dense override', function (): void {
$fixture = $this->makeBaselineCompareMatrixFixture();
$run = $this->makeBaselineCompareMatrixRun(
$fixture['visibleTenant'],
$fixture['profile'],
$fixture['snapshot'],
);
$this->makeBaselineCompareMatrixRun(
$fixture['visibleTenantTwo'],
$fixture['profile'],
$fixture['snapshot'],
);
$this->makeBaselineCompareMatrixFinding(
$fixture['visibleTenant'],
$fixture['profile'],
$run,
'wifi-corp-profile',
['severity' => 'critical'],
);
$viewer = User::factory()->create();
WorkspaceMembership::factory()->create([
'workspace_id' => (int) $fixture['workspace']->getKey(),
'user_id' => (int) $viewer->getKey(),
'role' => 'owner',
]);
$viewer->tenants()->syncWithoutDetaching([
(int) $fixture['visibleTenant']->getKey() => ['role' => 'owner'],
]);
$session = $this->setAdminWorkspaceContext($viewer, $fixture['workspace'], $fixture['visibleTenant']);
$this->withSession($session)
->get(BaselineProfileResource::compareMatrixUrl($fixture['profile']))
->assertOk()
->assertSee('Requested: Auto mode. Resolved: Compact mode.')
->assertSee('Compact compare results')
->assertSee('data-testid="baseline-compare-matrix-compact-shell"', false)
->assertDontSee('data-testid="baseline-compare-matrix-dense-shell"', false);
$this->withSession($session)
->get(BaselineProfileResource::compareMatrixUrl($fixture['profile']).'?mode=dense')
->assertOk()
->assertSee('Requested: Dense mode. Resolved: Dense mode.')
->assertSee('data-testid="baseline-compare-matrix-dense-shell"', false);
});
it('renders a blocked state when the baseline profile has no usable reference snapshot', function (): void {
$fixture = $this->makeBaselineCompareMatrixFixture();
$fixture['snapshot']->markIncomplete();
$session = $this->setAdminWorkspaceContext($fixture['user'], $fixture['workspace']);
$this->withSession($session)
->get(BaselineProfileResource::compareMatrixUrl($fixture['profile']))
->assertOk()
->assertSee('No usable reference snapshot')
->assertSee('Capture a complete baseline snapshot before using the compare matrix.');
});
it('renders an empty state when the baseline profile has no assigned tenants', function (): void {
$fixture = $this->makeBaselineCompareMatrixFixture();
$fixture['profile']->tenantAssignments()->delete();
$session = $this->setAdminWorkspaceContext($fixture['user'], $fixture['workspace']);
$this->withSession($session)
->get(BaselineProfileResource::compareMatrixUrl($fixture['profile']))
->assertOk()
->assertSee('No assigned tenants');
});
it('renders an empty state when the assigned set is not visible to the current actor', function (): void {
$fixture = $this->makeBaselineCompareMatrixFixture();
$viewer = User::factory()->create();
WorkspaceMembership::factory()->create([
'workspace_id' => (int) $fixture['workspace']->getKey(),
'user_id' => (int) $viewer->getKey(),
'role' => 'owner',
]);
$session = $this->setAdminWorkspaceContext($viewer, $fixture['workspace']);
$this->withSession($session)
->get(BaselineProfileResource::compareMatrixUrl($fixture['profile']))
->assertOk()
->assertSee('No visible assigned tenants');
});
it('renders a passive auto-refresh cue instead of a perpetual blocking state while compare runs remain active', function (): void {
$fixture = $this->makeBaselineCompareMatrixFixture();
$this->makeBaselineCompareMatrixRun(
$fixture['visibleTenant'],
$fixture['profile'],
$fixture['snapshot'],
attributes: [
'status' => \App\Support\OperationRunStatus::Queued->value,
'outcome' => \App\Support\OperationRunOutcome::Pending->value,
'completed_at' => null,
'started_at' => now(),
],
);
$session = $this->setAdminWorkspaceContext($fixture['user'], $fixture['workspace']);
$this->withSession($session)
->get(BaselineProfileResource::compareMatrixUrl($fixture['profile']))
->assertOk()
->assertSee('Passive auto-refresh every 5 seconds')
->assertSee('wire:poll.5s="pollMatrix"', false)
->assertSee('Refresh matrix');
});
it('renders a filtered zero-result state that preserves mode and offers reset filters as the primary cta', function (): void {
$fixture = $this->makeBaselineCompareMatrixFixture();
$this->makeBaselineCompareMatrixRun(
$fixture['visibleTenant'],
$fixture['profile'],
$fixture['snapshot'],
);
$this->makeBaselineCompareMatrixRun(
$fixture['visibleTenantTwo'],
$fixture['profile'],
$fixture['snapshot'],
);
$session = $this->setAdminWorkspaceContext($fixture['user'], $fixture['workspace']);
$this->withSession($session)
->get(BaselineProfileResource::compareMatrixUrl($fixture['profile']).'?mode=dense&state[]=missing')
->assertOk()
->assertSee('Requested: Dense mode. Resolved: Dense mode.')
->assertSee('No rows match the current filters')
->assertSee('Reset filters');
});