makeBaselineCompareMatrixFixture(); $visibleRun = $this->makeBaselineCompareMatrixRun( $fixture['visibleTenant'], $fixture['profile'], $fixture['snapshot'], ); $visibleRunTwo = $this->makeBaselineCompareMatrixRun( $fixture['visibleTenantTwo'], $fixture['profile'], $fixture['snapshot'], ); $hiddenRun = $this->makeBaselineCompareMatrixRun( $fixture['hiddenTenant'], $fixture['profile'], $fixture['snapshot'], ); $this->makeBaselineCompareMatrixFinding( $fixture['visibleTenantTwo'], $fixture['profile'], $visibleRunTwo, 'wifi-corp-profile', ); $this->makeBaselineCompareMatrixFinding( $fixture['hiddenTenant'], $fixture['profile'], $hiddenRun, 'wifi-corp-profile', ['severity' => 'critical'], ); $matrix = app(BaselineCompareMatrixBuilder::class)->build($fixture['profile'], $fixture['user']); $wifiRow = collect($matrix['denseRows'])->first( static fn (array $row): bool => ($row['subject']['subjectKey'] ?? null) === 'wifi-corp-profile', ); expect($matrix['reference']['assignedTenantCount'])->toBe(3) ->and($matrix['reference']['visibleTenantCount'])->toBe(2) ->and(collect($matrix['tenantSummaries'])->pluck('tenantName')->all())->toEqualCanonicalizing([ (string) $fixture['visibleTenant']->name, (string) $fixture['visibleTenantTwo']->name, ]) ->and($wifiRow)->not->toBeNull() ->and($wifiRow['subject']['deviationBreadth'])->toBe(1) ->and($wifiRow['subject']['attentionLevel'])->toBe('needs_attention') ->and(count($wifiRow['cells']))->toBe(2) ->and($matrix['denseRows'])->toHaveCount(2) ->and($matrix['compactResults'])->toBeEmpty() ->and($matrix['supportSurfaceState']['legendMode'])->toBe('grouped') ->and($matrix['supportSurfaceState']['showAutoRefreshHint'])->toBeFalse() ->and($matrix['lastUpdatedAt'])->not->toBeNull(); }); it('derives matrix cell precedence, freshness, attention, and reason summaries from compare truth', function (): void { $fixture = $this->makeBaselineCompareMatrixFixture(); $matchTenant = $fixture['visibleTenant']; $differTenant = $fixture['visibleTenantTwo']; $missingTenant = Tenant::factory()->create([ 'workspace_id' => (int) $fixture['workspace']->getKey(), 'name' => 'Contoso Missing', ]); $ambiguousTenant = Tenant::factory()->create([ 'workspace_id' => (int) $fixture['workspace']->getKey(), 'name' => 'Contoso Ambiguous', ]); $notComparedTenant = Tenant::factory()->create([ 'workspace_id' => (int) $fixture['workspace']->getKey(), 'name' => 'Contoso Uncovered', ]); $staleTenant = Tenant::factory()->create([ 'workspace_id' => (int) $fixture['workspace']->getKey(), 'name' => 'Contoso Stale', ]); $fixture['user']->tenants()->syncWithoutDetaching([ (int) $missingTenant->getKey() => ['role' => 'owner'], (int) $ambiguousTenant->getKey() => ['role' => 'owner'], (int) $notComparedTenant->getKey() => ['role' => 'owner'], (int) $staleTenant->getKey() => ['role' => 'owner'], ]); $this->assignTenantToBaselineProfile($fixture['profile'], $missingTenant); $this->assignTenantToBaselineProfile($fixture['profile'], $ambiguousTenant); $this->assignTenantToBaselineProfile($fixture['profile'], $notComparedTenant); $this->assignTenantToBaselineProfile($fixture['profile'], $staleTenant); $this->makeBaselineCompareMatrixRun($matchTenant, $fixture['profile'], $fixture['snapshot']); $differRun = $this->makeBaselineCompareMatrixRun($differTenant, $fixture['profile'], $fixture['snapshot']); $this->makeBaselineCompareMatrixFinding($differTenant, $fixture['profile'], $differRun, 'wifi-corp-profile', [ 'evidence_jsonb' => [ 'subject_key' => 'wifi-corp-profile', 'change_type' => 'different_version', ], ]); $missingRun = $this->makeBaselineCompareMatrixRun($missingTenant, $fixture['profile'], $fixture['snapshot']); $this->makeBaselineCompareMatrixFinding($missingTenant, $fixture['profile'], $missingRun, 'wifi-corp-profile', [ 'evidence_jsonb' => [ 'subject_key' => 'wifi-corp-profile', 'change_type' => 'missing_policy', ], ]); $ambiguousRun = $this->makeBaselineCompareMatrixRun( $ambiguousTenant, $fixture['profile'], $fixture['snapshot'], [ 'baseline_compare' => [ 'evidence_gaps' => [ 'count' => 1, 'by_reason' => ['ambiguous_match' => 1], 'subjects' => [ $this->baselineCompareMatrixGap('deviceConfiguration', 'wifi-corp-profile', [ 'reason_code' => 'ambiguous_match', 'resolution_outcome' => 'ambiguous_match', ]), ], ], ], ], ); $this->makeBaselineCompareMatrixFinding($ambiguousTenant, $fixture['profile'], $ambiguousRun, 'wifi-corp-profile', [ 'evidence_jsonb' => [ 'subject_key' => 'wifi-corp-profile', 'change_type' => 'missing_policy', ], ]); $this->makeBaselineCompareMatrixRun( $notComparedTenant, $fixture['profile'], $fixture['snapshot'], [ 'baseline_compare' => [ 'coverage' => [ 'proof' => true, 'effective_types' => ['deviceConfiguration'], 'covered_types' => [], 'uncovered_types' => ['deviceConfiguration'], ], ], ], ); $this->makeBaselineCompareMatrixRun( $staleTenant, $fixture['profile'], $fixture['snapshot'], [], [ 'completed_at' => $fixture['snapshot']->captured_at->copy()->subDay(), 'context' => [ 'baseline_profile_id' => (int) $fixture['profile']->getKey(), 'baseline_snapshot_id' => (int) $fixture['snapshot']->getKey() - 1, 'baseline_compare' => [ 'coverage' => [ 'proof' => true, 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], ], 'evidence_gaps' => [ 'count' => 0, 'by_reason' => [], 'subjects' => [], ], ], ], ], ); $matrix = app(BaselineCompareMatrixBuilder::class)->build($fixture['profile'], $fixture['user']); $wifiRow = collect($matrix['denseRows'])->first( static fn (array $row): bool => ($row['subject']['subjectKey'] ?? null) === 'wifi-corp-profile', ); $cellsByTenant = collect($wifiRow['cells'] ?? []) ->mapWithKeys(static fn (array $cell): array => [(int) $cell['tenantId'] => $cell]) ->all(); expect($cellsByTenant[(int) $matchTenant->getKey()]['state'] ?? null)->toBe('match') ->and($cellsByTenant[(int) $matchTenant->getKey()]['attentionLevel'] ?? null)->toBe('aligned') ->and($cellsByTenant[(int) $differTenant->getKey()]['state'] ?? null)->toBe('differ') ->and($cellsByTenant[(int) $differTenant->getKey()]['attentionLevel'] ?? null)->toBe('needs_attention') ->and($cellsByTenant[(int) $differTenant->getKey()]['reasonSummary'] ?? null)->toBe('A baseline compare finding exists for this subject.') ->and($cellsByTenant[(int) $missingTenant->getKey()]['state'] ?? null)->toBe('missing') ->and($cellsByTenant[(int) $missingTenant->getKey()]['attentionLevel'] ?? null)->toBe('needs_attention') ->and($cellsByTenant[(int) $ambiguousTenant->getKey()]['state'] ?? null)->toBe('ambiguous') ->and($cellsByTenant[(int) $ambiguousTenant->getKey()]['reasonSummary'] ?? null)->toBe('Ambiguous Match') ->and($cellsByTenant[(int) $notComparedTenant->getKey()]['state'] ?? null)->toBe('not_compared') ->and($cellsByTenant[(int) $notComparedTenant->getKey()]['attentionLevel'] ?? null)->toBe('refresh_recommended') ->and($cellsByTenant[(int) $notComparedTenant->getKey()]['reasonSummary'] ?? null)->toContain('Policy type coverage was not proven') ->and($cellsByTenant[(int) $staleTenant->getKey()]['state'] ?? null)->toBe('stale_result') ->and($cellsByTenant[(int) $staleTenant->getKey()]['freshnessState'] ?? null)->toBe('stale') ->and($cellsByTenant[(int) $staleTenant->getKey()]['trustLevel'] ?? null)->toBe('limited_confidence') ->and($cellsByTenant[(int) $staleTenant->getKey()]['attentionLevel'] ?? null)->toBe('refresh_recommended'); }); it('applies policy, state, severity, and subject-focus filters honestly without changing compare truth', function (): void { $fixture = $this->makeBaselineCompareMatrixFixture(); $visibleRun = $this->makeBaselineCompareMatrixRun( $fixture['visibleTenant'], $fixture['profile'], $fixture['snapshot'], ); $this->makeBaselineCompareMatrixRun( $fixture['visibleTenantTwo'], $fixture['profile'], $fixture['snapshot'], [], [ 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Failed->value, ], ); $this->makeBaselineCompareMatrixFinding( $fixture['visibleTenant'], $fixture['profile'], $visibleRun, 'wifi-corp-profile', ['severity' => 'critical'], ); $deviceOnly = app(BaselineCompareMatrixBuilder::class)->build($fixture['profile'], $fixture['user'], [ 'policyTypes' => ['deviceConfiguration'], ]); $driftOnly = app(BaselineCompareMatrixBuilder::class)->build($fixture['profile'], $fixture['user'], [ 'states' => ['differ'], 'severities' => ['critical'], ]); $subjectFocus = app(BaselineCompareMatrixBuilder::class)->build($fixture['profile'], $fixture['user'], [ 'focusedSubjectKey' => 'wifi-corp-profile', ]); expect(count($deviceOnly['denseRows']))->toBe(1) ->and($deviceOnly['denseRows'][0]['subject']['policyType'])->toBe('deviceConfiguration') ->and(count($driftOnly['denseRows']))->toBe(1) ->and($driftOnly['denseRows'][0]['subject']['subjectKey'])->toBe('wifi-corp-profile') ->and(count($subjectFocus['denseRows']))->toBe(1) ->and($subjectFocus['denseRows'][0]['subject']['subjectKey'])->toBe('wifi-corp-profile'); }); it('emits compact single-tenant results from the visible set only when one tenant remains in scope', function (): void { $fixture = $this->makeBaselineCompareMatrixFixture(); $run = $this->makeBaselineCompareMatrixRun( $fixture['visibleTenant'], $fixture['profile'], $fixture['snapshot'], ); $this->makeBaselineCompareMatrixFinding( $fixture['visibleTenant'], $fixture['profile'], $run, 'wifi-corp-profile', ['severity' => 'critical'], ); $this->makeBaselineCompareMatrixRun( $fixture['visibleTenantTwo'], $fixture['profile'], $fixture['snapshot'], ); $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'], ]); $matrix = app(BaselineCompareMatrixBuilder::class)->build($fixture['profile'], $viewer); expect($matrix['reference']['assignedTenantCount'])->toBe(3) ->and($matrix['reference']['visibleTenantCount'])->toBe(1) ->and($matrix['compactResults'])->toHaveCount(2) ->and(collect($matrix['compactResults'])->pluck('tenantId')->unique()->all())->toBe([(int) $fixture['visibleTenant']->getKey()]) ->and(collect($matrix['compactResults'])->firstWhere('subjectKey', 'wifi-corp-profile')['state'] ?? null)->toBe('differ') ->and(collect($matrix['compactResults'])->firstWhere('subjectKey', 'wifi-corp-profile')['attentionLevel'] ?? null)->toBe('needs_attention'); });