active()->create([ 'workspace_id' => (int) $tenant->workspace_id, ]); $snapshot = BaselineSnapshot::factory()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'baseline_profile_id' => (int) $profile->getKey(), ]); $profile->update(['active_snapshot_id' => (int) $snapshot->getKey()]); BaselineTenantAssignment::factory()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'tenant_id' => (int) $tenant->getKey(), 'baseline_profile_id' => (int) $profile->getKey(), ]); return [$user, $tenant, $profile, $snapshot]; } function makeBackupHealthScheduleForNeedsAttention(\App\Models\Tenant $tenant, array $attributes = []): BackupSchedule { return BackupSchedule::query()->create(array_merge([ 'tenant_id' => (int) $tenant->getKey(), 'name' => 'Needs Attention backup schedule', 'is_enabled' => true, 'timezone' => 'UTC', 'frequency' => 'daily', 'time_of_day' => '01:00:00', 'days_of_week' => null, 'policy_types' => ['deviceConfiguration'], 'include_foundations' => true, 'retention_keep_last' => 30, 'next_run_at' => now()->addHour(), ], $attributes)); } function makeHealthyBackupForRecoveryNeedsAttention(\App\Models\Tenant $tenant, array $attributes = []): BackupSet { $backupSet = BackupSet::factory()->for($tenant)->recentCompleted()->create(array_merge([ 'name' => 'Healthy recovery needs-attention backup', 'item_count' => 1, ], $attributes)); BackupItem::factory()->for($tenant)->for($backupSet)->create([ 'payload' => ['id' => 'healthy-recovery-policy'], 'metadata' => [], 'assignments' => [], ]); return $backupSet; } dataset('needs-attention-recovery-cases', [ 'failed history' => [ fn (\App\Models\Tenant $tenant, BackupSet $backupSet): RestoreRun => RestoreRun::factory() ->for($tenant) ->for($backupSet) ->failedOutcome() ->create([ 'completed_at' => now()->subMinutes(10), ]), 'Recent restore failed', 'The restore did not complete successfully. Follow-up is still required.', 'failed', ], 'partial history' => [ fn (\App\Models\Tenant $tenant, BackupSet $backupSet): RestoreRun => RestoreRun::factory() ->for($tenant) ->for($backupSet) ->partialOutcome() ->create([ 'completed_at' => now()->subMinutes(10), ]), 'Recent restore is partial', 'The restore reached a terminal state, but some items or assignments still need follow-up.', 'partial', ], 'follow-up history' => [ fn (\App\Models\Tenant $tenant, BackupSet $backupSet): RestoreRun => RestoreRun::factory() ->for($tenant) ->for($backupSet) ->completedWithFollowUp() ->create([ 'completed_at' => now()->subMinutes(10), ]), 'Recent restore needs follow-up', 'The restore completed, but follow-up remains for skipped or non-applied work.', RestoreResultAttention::STATE_COMPLETED_WITH_FOLLOW_UP, ], ]); afterEach(function (): void { CarbonImmutable::setTestNow(); }); it('shows a cautionary baseline posture in needs-attention when compare trust is limited', function (): void { [$user, $tenant, $profile, $snapshot] = createNeedsAttentionTenant(); $this->actingAs($user); OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => OperationRunType::BaselineCompare->value, 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::PartiallySucceeded->value, 'completed_at' => now(), 'context' => [ 'baseline_profile_id' => (int) $profile->getKey(), 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'baseline_compare' => [ 'reason_code' => BaselineCompareReasonCode::EvidenceCaptureIncomplete->value, 'coverage' => [ 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], 'proof' => true, ], 'evidence_gaps' => [ 'count' => 2, 'by_reason' => [ 'policy_record_missing' => 2, ], ], ], ], ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee('Needs Attention') ->assertSee('Baseline compare posture') ->assertSee('The last compare finished, but normal result output was suppressed.') ->assertSee('Open Baseline Compare') ->assertDontSee('Current governance and findings signals look trustworthy.'); expect($component->html())->toContain('href='); }); it('keeps needs-attention healthy only for trustworthy compare results', function (): void { [$user, $tenant, $profile, $snapshot] = createNeedsAttentionTenant(); $this->actingAs($user); $healthyBackup = BackupSet::factory()->for($tenant)->create([ 'name' => 'Healthy compare backup', 'item_count' => 1, 'completed_at' => now()->subMinutes(20), ]); BackupItem::factory()->for($tenant)->for($healthyBackup)->create([ 'payload' => ['id' => 'healthy-policy'], 'metadata' => [], 'assignments' => [], ]); RestoreRun::factory() ->for($tenant) ->for($healthyBackup) ->completedOutcome() ->create([ 'completed_at' => now()->subMinutes(10), ]); OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => OperationRunType::BaselineCompare->value, 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Succeeded->value, 'completed_at' => now()->subHour(), 'context' => [ 'baseline_profile_id' => (int) $profile->getKey(), 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'baseline_compare' => [ 'reason_code' => BaselineCompareReasonCode::NoDriftDetected->value, 'coverage' => [ 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], 'proof' => true, ], ], ], ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee('Current governance and findings signals look trustworthy.') ->assertSee('Baseline compare looks trustworthy') ->assertSee('No recent restore issues visible') ->assertSee('No confirmed drift in the latest baseline compare.') ->assertDontSee('Baseline compare posture'); expect($component->html())->not->toContain('href='); }); it('surfaces stale compare posture instead of a healthy fallback', function (): void { [$user, $tenant, $profile, $snapshot] = createNeedsAttentionTenant(); $this->actingAs($user); OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => OperationRunType::BaselineCompare->value, 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Succeeded->value, 'completed_at' => now()->subDays(10), 'context' => [ 'baseline_profile_id' => (int) $profile->getKey(), 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'baseline_compare' => [ 'reason_code' => BaselineCompareReasonCode::NoDriftDetected->value, 'coverage' => [ 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], 'proof' => true, ], ], ], ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); Livewire::test(NeedsAttention::class) ->assertSee('Baseline compare posture') ->assertSee('The latest baseline compare result is stale.') ->assertSee('Open Baseline Compare') ->assertDontSee('Current governance and findings signals look trustworthy.'); }); it('surfaces compare unavailability instead of a healthy fallback when no result exists yet', function (): void { [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); Livewire::test(NeedsAttention::class) ->assertSee('Baseline compare posture') ->assertSee('A current baseline compare result is not available yet.') ->assertSee('Open Baseline Compare') ->assertDontSee('Current governance and findings signals look trustworthy.'); }); it('surfaces overdue and lapsed-governance findings even when there are no new findings', function (): void { [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); Finding::factory()->for($tenant)->create([ 'status' => Finding::STATUS_TRIAGED, 'due_at' => now()->subDay(), ]); Finding::factory()->for($tenant)->create([ 'status' => Finding::STATUS_RISK_ACCEPTED, ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); Livewire::test(NeedsAttention::class) ->assertSee('Overdue findings') ->assertSee('Lapsed accepted-risk governance') ->assertSee('Open findings') ->assertDontSee('Current governance and findings signals look trustworthy.'); }); it('surfaces expiring governance from the shared aggregate with the matching findings action', function (): void { [$user, $tenant, $profile, $snapshot] = createNeedsAttentionTenant(); $this->actingAs($user); OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => OperationRunType::BaselineCompare->value, 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Succeeded->value, 'completed_at' => now(), 'context' => [ 'baseline_profile_id' => (int) $profile->getKey(), 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'baseline_compare' => [ 'reason_code' => BaselineCompareReasonCode::NoDriftDetected->value, 'coverage' => [ 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], 'proof' => true, ], ], ], ]); $finding = Finding::factory()->riskAccepted()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'tenant_id' => (int) $tenant->getKey(), ]); FindingException::query()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'tenant_id' => (int) $tenant->getKey(), 'finding_id' => (int) $finding->getKey(), 'requested_by_user_id' => (int) $user->getKey(), 'owner_user_id' => (int) $user->getKey(), 'approved_by_user_id' => (int) $user->getKey(), 'status' => FindingException::STATUS_EXPIRING, 'current_validity_state' => FindingException::VALIDITY_EXPIRING, 'request_reason' => 'Expiring governance coverage', 'approval_reason' => 'Approved for coverage', 'requested_at' => now()->subDays(2), 'approved_at' => now()->subDay(), 'effective_from' => now()->subDay(), 'expires_at' => now()->addDays(2), 'review_due_at' => now()->addDay(), 'evidence_summary' => ['reference_count' => 0], ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee('Expiring accepted-risk governance') ->assertSee('Open findings') ->assertDontSee('Current governance and findings signals look trustworthy.'); expect($component->html())->toContain('href='); }); it('keeps findings attention visible but non-clickable when the member lacks findings access', function (): void { [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); Finding::factory()->for($tenant)->create([ 'status' => Finding::STATUS_TRIAGED, 'due_at' => now()->subDay(), ]); Gate::define(Capabilities::TENANT_FINDINGS_VIEW, fn (): bool => false); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee('Overdue findings') ->assertSee('Open findings') ->assertSee(UiTooltips::INSUFFICIENT_PERMISSION); expect($component->html()) ->not->toContain(FindingResource::getUrl('index', ['tab' => 'overdue'], panel: 'tenant', tenant: $tenant)) ->toContain('Open Baseline Compare'); }); it('separates stale active attention from terminal follow-up on tenant operations attention', function (): void { [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Queued->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subHour(), ]); OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'policy.sync', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Failed->value, ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); Livewire::test(NeedsAttention::class) ->assertSee('Active operations look stale') ->assertSee('Terminal operations need follow-up') ->assertSee('Open stale operations') ->assertSee('Open terminal follow-up') ->assertDontSee('Current governance and findings signals look trustworthy.'); }); it('surfaces a no-backup attention item with a backup-sets destination', function (): void { [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee('No usable backup basis') ->assertSee('Create or finish a backup set before relying on restore input.') ->assertSee('Open backup sets') ->assertDontSee('Backups are recent and healthy'); expect($component->html())->toContain(BackupSetResource::getUrl('index', [ 'backup_health_reason' => TenantBackupHealthAssessment::REASON_NO_BACKUP_BASIS, ], panel: 'tenant', tenant: $tenant)); }); it('surfaces stale latest-backup attention with the matching latest-backup drill-through', function (): void { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 7, 12, 0, 0, 'UTC')); [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); $staleBackup = BackupSet::factory()->for($tenant)->create([ 'name' => 'Stale backup', 'item_count' => 1, 'completed_at' => now()->subDays(2), ]); BackupItem::factory()->for($tenant)->for($staleBackup)->create([ 'payload' => ['id' => 'policy-stale'], 'metadata' => [], 'assignments' => [], ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $staleComponent = Livewire::test(NeedsAttention::class) ->assertSee('Latest backup is stale') ->assertSee('Open latest backup') ->assertDontSee('Backups are recent and healthy'); expect($staleComponent->html())->toContain(BackupSetResource::getUrl('view', [ 'record' => (int) $staleBackup->getKey(), 'backup_health_reason' => TenantBackupHealthAssessment::REASON_LATEST_BACKUP_STALE, ], panel: 'tenant', tenant: $tenant)); }); it('surfaces degraded latest-backup attention with the matching latest-backup drill-through', function (): void { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 7, 12, 0, 0, 'UTC')); [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); $degradedBackup = BackupSet::factory()->for($tenant)->create([ 'name' => 'Degraded backup', 'item_count' => 1, 'completed_at' => now()->subMinutes(45), ]); BackupItem::factory()->for($tenant)->for($degradedBackup)->create([ 'payload' => [], 'metadata' => [ 'source' => 'metadata_only', 'assignments_fetch_failed' => true, ], 'assignments' => [], ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $degradedComponent = Livewire::test(NeedsAttention::class) ->assertSee('Latest backup is degraded') ->assertSee('Open latest backup') ->assertDontSee('Backups are recent and healthy'); expect($degradedComponent->html())->toContain(BackupSetResource::getUrl('view', [ 'record' => (int) $degradedBackup->getKey(), 'backup_health_reason' => TenantBackupHealthAssessment::REASON_LATEST_BACKUP_DEGRADED, ], panel: 'tenant', tenant: $tenant)); }); it('surfaces schedule follow-up instead of a healthy backup check when automation needs review', function (): void { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 7, 12, 0, 0, 'UTC')); [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); $healthyBackup = BackupSet::factory()->for($tenant)->create([ 'name' => 'Healthy backup', 'item_count' => 1, 'completed_at' => now()->subMinutes(20), ]); BackupItem::factory()->for($tenant)->for($healthyBackup)->create([ 'payload' => ['id' => 'healthy-policy'], 'metadata' => [], 'assignments' => [], ]); makeBackupHealthScheduleForNeedsAttention($tenant, [ 'name' => 'Overdue schedule', 'last_run_at' => null, 'last_run_status' => null, 'next_run_at' => now()->subHours(2), ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee('Backup schedules need follow-up') ->assertSee('not produced a successful run') ->assertSee('Open backup schedules') ->assertDontSee('Backups are recent and healthy'); expect($component->html())->toContain(BackupScheduleResource::getUrl('index', [ 'backup_health_reason' => TenantBackupHealthAssessment::REASON_SCHEDULE_FOLLOW_UP, ], panel: 'tenant', tenant: $tenant)); }); it('adds the healthy backup check only when the latest backup basis genuinely earns it', function (): void { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 7, 12, 0, 0, 'UTC')); [$user, $tenant, $profile, $snapshot] = createNeedsAttentionTenant(); $this->actingAs($user); $healthyBackup = BackupSet::factory()->for($tenant)->create([ 'name' => 'Healthy backup', 'item_count' => 1, 'completed_at' => now()->subMinutes(10), ]); BackupItem::factory()->for($tenant)->for($healthyBackup)->create([ 'payload' => ['id' => 'healthy-policy'], 'metadata' => [], 'assignments' => [], ]); RestoreRun::factory() ->for($tenant) ->for($healthyBackup) ->completedOutcome() ->create([ 'completed_at' => now()->subMinutes(10), ]); OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => OperationRunType::BaselineCompare->value, 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Succeeded->value, 'completed_at' => now()->subHour(), 'context' => [ 'baseline_profile_id' => (int) $profile->getKey(), 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'baseline_compare' => [ 'reason_code' => BaselineCompareReasonCode::NoDriftDetected->value, 'coverage' => [ 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], 'proof' => true, ], ], ], ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); Livewire::test(NeedsAttention::class) ->assertSee('Backups are recent and healthy') ->assertSee('No recent restore issues visible') ->assertSee('Baseline compare looks trustworthy') ->assertDontSee('Backup schedules need follow-up') ->assertDontSee('No usable backup basis'); }); it('surfaces missing restore history and suppresses the healthy fallback when recovery evidence is unvalidated', function (): void { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 7, 12, 0, 0, 'UTC')); [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); $backupSet = makeHealthyBackupForRecoveryNeedsAttention($tenant); RestoreRun::factory() ->for($tenant) ->for($backupSet) ->previewOnly() ->create([ 'completed_at' => now()->subMinutes(5), ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee('Recovery evidence is unvalidated') ->assertSee('No executed restore history is visible in the latest tenant restore records.') ->assertSee('Backup health reflects backup inputs only and does not prove restore success.') ->assertSee('Open restore history') ->assertDontSee('Current governance and findings signals look trustworthy.') ->assertDontSee('Backups are recent and healthy'); expect($component->html())->toContain(RestoreRunResource::getUrl('index', [ 'recovery_posture_reason' => 'no_history', ], panel: 'tenant', tenant: $tenant)); }); it('surfaces recent weak restore history in needs-attention with the matching restore drillthrough', function ( Closure $makeRestoreRun, string $expectedTitle, string $expectedBody, string $expectedReason, ): void { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 7, 12, 0, 0, 'UTC')); [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); makeHealthyBackupForRecoveryNeedsAttention($tenant); $restoreBackupSet = BackupSet::factory()->for($tenant)->create([ 'name' => 'Recovery attention restore backup', ]); $restoreRun = $makeRestoreRun($tenant, $restoreBackupSet); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee($expectedTitle) ->assertSee($expectedBody) ->assertSee('Open restore run') ->assertDontSee('Current governance and findings signals look trustworthy.'); expect($component->html())->toContain(RestoreRunResource::getUrl('view', [ 'record' => (int) $restoreRun->getKey(), 'recovery_posture_reason' => $expectedReason, ], panel: 'tenant', tenant: $tenant)); })->with('needs-attention-recovery-cases'); it('adds a calm recovery healthy-check without claiming tenant-wide recovery proof', function (): void { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 7, 12, 0, 0, 'UTC')); [$user, $tenant, $profile, $snapshot] = createNeedsAttentionTenant(); $this->actingAs($user); makeHealthyBackupForRecoveryNeedsAttention($tenant); OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => OperationRunType::BaselineCompare->value, 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Succeeded->value, 'completed_at' => now()->subHour(), 'context' => [ 'baseline_profile_id' => (int) $profile->getKey(), 'baseline_snapshot_id' => (int) $snapshot->getKey(), 'baseline_compare' => [ 'reason_code' => BaselineCompareReasonCode::NoDriftDetected->value, 'coverage' => [ 'effective_types' => ['deviceConfiguration'], 'covered_types' => ['deviceConfiguration'], 'uncovered_types' => [], 'proof' => true, ], ], ], ]); $restoreBackupSet = BackupSet::factory()->for($tenant)->create([ 'name' => 'Calm recovery restore backup', ]); RestoreRun::factory() ->for($tenant) ->for($restoreBackupSet) ->completedOutcome() ->create([ 'completed_at' => now()->subMinutes(10), ]); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); Livewire::test(NeedsAttention::class) ->assertSee('Current governance and findings signals look trustworthy.') ->assertSee('Backups are recent and healthy') ->assertSee('No recent restore issues visible') ->assertSee('Recent executed restore history exists without a current follow-up signal.') ->assertSee('Tenant-wide recovery is not proven.') ->assertDontSee('Recovery evidence is unvalidated') ->assertDontSee('Recent restore failed'); }); it('keeps backup-health attention visible but non-clickable when the member lacks backup view access', function (): void { CarbonImmutable::setTestNow(CarbonImmutable::create(2026, 4, 7, 12, 0, 0, 'UTC')); [$user, $tenant] = createNeedsAttentionTenant(); $this->actingAs($user); $backupSet = BackupSet::factory()->for($tenant)->create([ 'name' => 'Stale hidden backup', 'item_count' => 1, 'completed_at' => now()->subDays(2), ]); BackupItem::factory()->for($tenant)->for($backupSet)->create([ 'payload' => ['id' => 'policy-stale'], 'metadata' => [], 'assignments' => [], ]); Gate::define(Capabilities::TENANT_VIEW, fn (): bool => false); Filament::setCurrentPanel(Filament::getPanel('tenant')); Filament::setTenant($tenant, true); $component = Livewire::test(NeedsAttention::class) ->assertSee('Latest backup is stale') ->assertSee('Open latest backup') ->assertSee(UiTooltips::INSUFFICIENT_PERMISSION); expect($component->html())->not->toContain(BackupSetResource::getUrl('view', [ 'record' => (int) $backupSet->getKey(), 'backup_health_reason' => TenantBackupHealthAssessment::REASON_LATEST_BACKUP_STALE, ], panel: 'tenant', tenant: $tenant)); });