browser()->timeout(15_000); it('smokes dense multi-tenant scanning and finding drilldown continuity', 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' => Finding::SEVERITY_CRITICAL], ); $this->actingAs($fixture['user'])->withSession([ WorkspaceContext::SESSION_KEY => (int) $fixture['workspace']->getKey(), WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [ (string) $fixture['workspace']->getKey() => (int) $fixture['visibleTenant']->getKey(), ], ]); session()->put(WorkspaceContext::SESSION_KEY, (int) $fixture['workspace']->getKey()); $page = visit(BaselineProfileResource::compareMatrixUrl($fixture['profile'])); $page ->assertNoJavaScriptErrors() ->waitForText('Requested: Auto mode. Resolved: Dense mode.') ->assertSee('Dense multi-tenant scan') ->assertSee('Grouped legend') ->assertSee('Open finding') ->assertSee('More follow-up') ->click('Open finding') ->waitForText('Back to compare matrix') ->assertNoJavaScriptErrors() ->assertSee('Back to compare matrix'); }); it('smokes the compact single-tenant path when only one visible tenant remains', 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' => Finding::SEVERITY_HIGH], ); $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'], ]); $this->actingAs($viewer)->withSession([ WorkspaceContext::SESSION_KEY => (int) $fixture['workspace']->getKey(), WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [ (string) $fixture['workspace']->getKey() => (int) $fixture['visibleTenant']->getKey(), ], ]); session()->put(WorkspaceContext::SESSION_KEY, (int) $fixture['workspace']->getKey()); visit(BaselineProfileResource::compareMatrixUrl($fixture['profile'])) ->assertNoJavaScriptErrors() ->waitForText('Requested: Auto mode. Resolved: Compact mode.') ->assertSee('Compact compare results') ->assertSee('Open finding'); }); it('smokes filtered zero-results reset flow and passive refresh cues without losing the matrix route', 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(), ], ); $this->makeBaselineCompareMatrixRun( $fixture['visibleTenantTwo'], $fixture['profile'], $fixture['snapshot'], ); $this->actingAs($fixture['user'])->withSession([ WorkspaceContext::SESSION_KEY => (int) $fixture['workspace']->getKey(), WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [ (string) $fixture['workspace']->getKey() => (int) $fixture['visibleTenant']->getKey(), ], ]); session()->put(WorkspaceContext::SESSION_KEY, (int) $fixture['workspace']->getKey()); visit(BaselineProfileResource::compareMatrixUrl($fixture['profile']).'?mode=dense&state[]=missing') ->assertNoJavaScriptErrors() ->waitForText('No rows match the current filters') ->assertSee('Passive auto-refresh every 5 seconds') ->click('Reset filters') ->waitForText('Dense multi-tenant scan') ->assertSee('Requested: Dense mode. Resolved: Dense mode.') ->assertNoJavaScriptErrors(); });