setAccessible(true); return collect($method->invoke($component->instance())) ->mapWithKeys(fn (Stat $stat): array => [ (string) $stat->getLabel() => (string) $stat->getValue(), ]) ->all(); } it('filters KPI deliveries by tenant when context is set via lastTenantId fallback only', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $workspaceId = (int) $tenant->workspace_id; $rule = AlertRule::factory()->create(['workspace_id' => $workspaceId]); $destination = AlertDestination::factory()->create(['workspace_id' => $workspaceId]); AlertDelivery::factory()->create([ 'workspace_id' => $workspaceId, 'tenant_id' => (int) $tenant->getKey(), 'alert_rule_id' => (int) $rule->getKey(), 'alert_destination_id' => (int) $destination->getKey(), 'status' => AlertDelivery::STATUS_SENT, 'created_at' => now()->subHour(), ]); $otherTenant = Tenant::factory()->create(['workspace_id' => $workspaceId]); $user->tenants()->syncWithoutDetaching([ $otherTenant->getKey() => ['role' => 'owner'], ]); AlertDelivery::factory()->create([ 'workspace_id' => $workspaceId, 'tenant_id' => (int) $otherTenant->getKey(), 'alert_rule_id' => (int) $rule->getKey(), 'alert_destination_id' => (int) $destination->getKey(), 'status' => AlertDelivery::STATUS_SENT, 'created_at' => now()->subHour(), ]); $this->actingAs($user); Filament::setTenant(null, true); session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [ (string) $workspaceId => (int) $tenant->getKey(), ]); $values = alertsKpiValues(Livewire::test(AlertsKpiHeader::class)); expect($values)->toMatchArray([ 'Deliveries (24h)' => '1', 'Failed (7d)' => '0', ]); })->group('ops-ux'); it('filters KPI deliveries by tenant when context is set via Filament setTenant', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $workspaceId = (int) $tenant->workspace_id; $rule = AlertRule::factory()->create(['workspace_id' => $workspaceId]); $destination = AlertDestination::factory()->create(['workspace_id' => $workspaceId]); AlertDelivery::factory()->create([ 'workspace_id' => $workspaceId, 'tenant_id' => (int) $tenant->getKey(), 'alert_rule_id' => (int) $rule->getKey(), 'alert_destination_id' => (int) $destination->getKey(), 'status' => AlertDelivery::STATUS_SENT, 'created_at' => now()->subHour(), ]); $otherTenant = Tenant::factory()->create(['workspace_id' => $workspaceId]); $user->tenants()->syncWithoutDetaching([ $otherTenant->getKey() => ['role' => 'owner'], ]); AlertDelivery::factory()->create([ 'workspace_id' => $workspaceId, 'tenant_id' => (int) $otherTenant->getKey(), 'alert_rule_id' => (int) $rule->getKey(), 'alert_destination_id' => (int) $destination->getKey(), 'status' => AlertDelivery::STATUS_SENT, 'created_at' => now()->subHour(), ]); $this->actingAs($user); Filament::setTenant($tenant, true); session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); $values = alertsKpiValues(Livewire::test(AlertsKpiHeader::class)); expect($values)->toMatchArray([ 'Deliveries (24h)' => '1', 'Failed (7d)' => '0', ]); })->group('ops-ux'); it('shows workspace-wide KPI counts when no tenant context is active', function (): void { [$user, $tenant] = createUserWithTenant(role: 'owner'); $workspaceId = (int) $tenant->workspace_id; $rule = AlertRule::factory()->create(['workspace_id' => $workspaceId]); $destination = AlertDestination::factory()->create(['workspace_id' => $workspaceId]); AlertDelivery::factory()->create([ 'workspace_id' => $workspaceId, 'tenant_id' => (int) $tenant->getKey(), 'alert_rule_id' => (int) $rule->getKey(), 'alert_destination_id' => (int) $destination->getKey(), 'status' => AlertDelivery::STATUS_SENT, 'created_at' => now()->subHour(), ]); $otherTenant = Tenant::factory()->create(['workspace_id' => $workspaceId]); $user->tenants()->syncWithoutDetaching([ $otherTenant->getKey() => ['role' => 'owner'], ]); AlertDelivery::factory()->create([ 'workspace_id' => $workspaceId, 'tenant_id' => (int) $otherTenant->getKey(), 'alert_rule_id' => (int) $rule->getKey(), 'alert_destination_id' => (int) $destination->getKey(), 'status' => AlertDelivery::STATUS_SENT, 'created_at' => now()->subHour(), ]); $this->actingAs($user); Filament::setTenant(null, true); session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); $values = alertsKpiValues(Livewire::test(AlertsKpiHeader::class)); expect($values)->toMatchArray([ 'Deliveries (24h)' => '2', 'Failed (7d)' => '0', ]); })->group('ops-ux'); it('prefers the Filament tenant over remembered tenant fallback in KPI scope conflicts', function (): void { [$user, $tenantA] = createUserWithTenant(role: 'owner'); $workspaceId = (int) $tenantA->workspace_id; $tenantB = Tenant::factory()->create(['workspace_id' => $workspaceId]); $user->tenants()->syncWithoutDetaching([ $tenantB->getKey() => ['role' => 'owner'], ]); $rule = AlertRule::factory()->create(['workspace_id' => $workspaceId]); $destination = AlertDestination::factory()->create(['workspace_id' => $workspaceId]); AlertDelivery::factory()->create([ 'workspace_id' => $workspaceId, 'tenant_id' => (int) $tenantA->getKey(), 'alert_rule_id' => (int) $rule->getKey(), 'alert_destination_id' => (int) $destination->getKey(), 'status' => AlertDelivery::STATUS_SENT, 'created_at' => now()->subHour(), ]); AlertDelivery::factory()->create([ 'workspace_id' => $workspaceId, 'tenant_id' => (int) $tenantB->getKey(), 'alert_rule_id' => (int) $rule->getKey(), 'alert_destination_id' => (int) $destination->getKey(), 'status' => AlertDelivery::STATUS_FAILED, 'created_at' => now()->subHour(), ]); $this->actingAs($user); Filament::setTenant($tenantB, true); session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [ (string) $workspaceId => (int) $tenantA->getKey(), ]); $values = alertsKpiValues(Livewire::test(AlertsKpiHeader::class)); expect($values)->toMatchArray([ 'Deliveries (24h)' => '1', 'Failed (7d)' => '1', ]); })->group('ops-ux');