TenantAtlas/apps/platform/tests/Feature/Monitoring/MonitoringPageStateContractTest.php

200 lines
10 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\BaselineCompareLanding;
use App\Filament\Pages\BaselineCompareMatrix;
use App\Filament\Pages\Monitoring\AuditLog;
use App\Filament\Pages\Monitoring\EvidenceOverview;
use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
use App\Filament\Pages\Monitoring\Operations;
use App\Models\AuditLog as AuditLogModel;
use App\Models\FindingException;
function monitoringPageStateFieldSummary(array $contract): array
{
return collect($contract['stateFields'])
->mapWithKeys(static fn (array $field): array => [
(string) $field['stateKey'] => [
'stateClass' => $field['stateClass'],
'queryRole' => $field['queryRole'],
'shareable' => $field['shareable'],
'restorableOnRefresh' => $field['restorableOnRefresh'],
],
])
->all();
}
it('declares the bounded page-state contract for each monitoring surface', function (string $pageClass, array $expected): void {
$contract = $pageClass::monitoringPageStateContract();
expect($contract['surfaceKey'])->toBe($expected['surfaceKey'])
->and($contract['surfaceType'])->toBe($expected['surfaceType'])
->and($contract['shareableStateKeys'])->toBe($expected['shareableStateKeys'])
->and($contract['localOnlyStateKeys'])->toBe($expected['localOnlyStateKeys'])
->and($contract['inspectContract'])->toMatchArray($expected['inspectContract'])
->and(monitoringPageStateFieldSummary($contract))->toEqual($expected['stateFields']);
})->with([
'operations' => [
Operations::class,
[
'surfaceKey' => 'operations',
'surfaceType' => 'simple_monitoring',
'shareableStateKeys' => ['tenant_id', 'tenant_scope', 'problemClass', 'activeTab'],
'localOnlyStateKeys' => [],
'inspectContract' => [
'primaryModel' => 'none',
'selectedStateKey' => null,
'presentation' => 'none',
'shareable' => false,
],
'stateFields' => [
'tenant_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'tenant_scope' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'problemClass' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'scoped_deeplink', 'shareable' => true, 'restorableOnRefresh' => true],
'activeTab' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'tableFilters' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
],
],
],
'audit log' => [
AuditLog::class,
[
'surfaceKey' => 'audit_log',
'surfaceType' => 'selected_record_monitoring',
'shareableStateKeys' => ['event'],
'localOnlyStateKeys' => [],
'inspectContract' => [
'primaryModel' => AuditLogModel::class,
'selectedStateKey' => 'selectedAuditLogId',
'presentation' => 'inline_detail',
'shareable' => true,
],
'stateFields' => [
'event' => ['stateClass' => 'inspect', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'tenant_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => false, 'restorableOnRefresh' => true],
'tableSearch' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
],
],
],
'finding exceptions queue' => [
FindingExceptionsQueue::class,
[
'surfaceKey' => 'finding_exceptions_queue',
'surfaceType' => 'selected_record_monitoring',
'shareableStateKeys' => ['tenant', 'exception'],
'localOnlyStateKeys' => [],
'inspectContract' => [
'primaryModel' => FindingException::class,
'selectedStateKey' => 'selectedFindingExceptionId',
'presentation' => 'summary_plus_related_actions',
'shareable' => true,
],
'stateFields' => [
'exception' => ['stateClass' => 'inspect', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'tenant' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'tableFilters' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
'tableSearch' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
],
],
],
'evidence overview' => [
EvidenceOverview::class,
[
'surfaceKey' => 'evidence_overview',
'surfaceType' => 'simple_monitoring',
'shareableStateKeys' => ['tenant_id', 'search'],
'localOnlyStateKeys' => [],
'inspectContract' => [
'primaryModel' => 'none',
'selectedStateKey' => null,
'presentation' => 'navigate_to_canonical_detail',
'shareable' => false,
],
'stateFields' => [
'tenant_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'search' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'tableFilters' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
'tableSort' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
],
],
],
'baseline compare landing' => [
BaselineCompareLanding::class,
[
'surfaceKey' => 'baseline_compare_landing',
'surfaceType' => 'launch_context_support',
'shareableStateKeys' => ['baseline_profile_id', 'subject_key', 'nav'],
'localOnlyStateKeys' => [],
'inspectContract' => [
'primaryModel' => 'none',
'selectedStateKey' => null,
'presentation' => 'none',
'shareable' => true,
],
'stateFields' => [
'baseline_profile_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'scoped_deeplink', 'shareable' => true, 'restorableOnRefresh' => true],
'subject_key' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'scoped_deeplink', 'shareable' => true, 'restorableOnRefresh' => true],
'nav' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
],
],
],
'baseline compare matrix' => [
BaselineCompareMatrix::class,
[
'surfaceKey' => 'baseline_compare_matrix',
'surfaceType' => 'draft_apply_analysis',
'shareableStateKeys' => ['mode', 'policy_type', 'state', 'severity', 'tenant_sort', 'subject_sort', 'subject_key'],
'localOnlyStateKeys' => [
'draftSelectedPolicyTypes',
'draftSelectedStates',
'draftSelectedSeverities',
'draftTenantSort',
'draftSubjectSort',
],
'inspectContract' => [
'primaryModel' => 'baseline_subject',
'selectedStateKey' => 'focusedSubjectKey',
'presentation' => 'focused_matrix',
'shareable' => true,
],
'stateFields' => [
'mode' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'policy_type' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'state' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'severity' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'tenant_sort' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'subject_sort' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
'subject_key' => ['stateClass' => 'inspect', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
],
],
],
]);
it('keeps the selected-record monitoring surfaces on a single inspect identifier', function (): void {
$contracts = [
AuditLog::monitoringPageStateContract(),
FindingExceptionsQueue::monitoringPageStateContract(),
];
expect(collect($contracts)->pluck('inspectContract.selectedStateKey')->all())
->toEqual(['selectedAuditLogId', 'selectedFindingExceptionId'])
->and(collect($contracts)->pluck('inspectContract.shareable')->unique()->all())
->toEqual([true]);
});
it('keeps compare matrix draft state local while applied filters stay query-driven', function (): void {
$contract = BaselineCompareMatrix::monitoringPageStateContract();
expect($contract['surfaceType'])->toBe('draft_apply_analysis')
->and($contract['localOnlyStateKeys'])->toEqual([
'draftSelectedPolicyTypes',
'draftSelectedStates',
'draftSelectedSeverities',
'draftTenantSort',
'draftSubjectSort',
])
->and(collect($contract['shareableStateKeys'])->contains('subject_key'))->toBeTrue()
->and($contract['inspectContract']['presentation'])->toBe('focused_matrix');
});