create(); [$user, $tenantA] = createUserWithTenant(tenant: $tenantA, role: 'owner'); $tenantB = Tenant::factory()->create([ 'workspace_id' => (int) $tenantA->workspace_id, ]); createUserWithTenant(tenant: $tenantB, user: $user, role: 'owner'); $healthyActive = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Running->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subMinute(), 'started_at' => now()->subMinute(), ]); $staleActive = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Queued->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subHour(), ]); $otherTenantActive = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantB->getKey(), 'workspace_id' => (int) $tenantB->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Running->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subMinute(), 'started_at' => now()->subMinute(), ]); $this->actingAs($user); Filament::setTenant($tenantA, true); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id); Livewire::withQueryParams([ 'tenant_id' => (string) $tenantA->getKey(), 'activeTab' => 'active', ]) ->actingAs($user) ->test(Operations::class) ->assertSet('tableFilters.tenant_id.value', (string) $tenantA->getKey()) ->assertSet('activeTab', 'active') ->assertCanSeeTableRecords([$healthyActive]) ->assertCanNotSeeTableRecords([$staleActive, $otherTenantActive]); }); it('uses the stale-attention dashboard landing for likely stale active runs', function (): void { $tenantA = Tenant::factory()->create(); [$user, $tenantA] = createUserWithTenant(tenant: $tenantA, role: 'owner'); $tenantB = Tenant::factory()->create([ 'workspace_id' => (int) $tenantA->workspace_id, ]); createUserWithTenant(tenant: $tenantB, user: $user, role: 'owner'); $staleRun = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Queued->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subHour(), ]); $terminalRun = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'policy.sync', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Failed->value, ]); $otherTenantStale = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantB->getKey(), 'workspace_id' => (int) $tenantB->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Queued->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subHour(), ]); $this->actingAs($user); Filament::setTenant($tenantA, true); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id); Livewire::withQueryParams([ 'tenant_id' => (string) $tenantA->getKey(), 'activeTab' => OperationRun::PROBLEM_CLASS_ACTIVE_STALE_ATTENTION, 'problemClass' => OperationRun::PROBLEM_CLASS_ACTIVE_STALE_ATTENTION, ]) ->actingAs($user) ->test(Operations::class) ->assertSet('tableFilters.tenant_id.value', (string) $tenantA->getKey()) ->assertSet('activeTab', OperationRun::PROBLEM_CLASS_ACTIVE_STALE_ATTENTION) ->assertCanSeeTableRecords([$staleRun]) ->assertCanNotSeeTableRecords([$terminalRun, $otherTenantStale]); }); it('uses the terminal follow-up landing for failed, warning, and blocked runs without mixing in stale active work', function (): void { $tenantA = Tenant::factory()->create(); [$user, $tenantA] = createUserWithTenant(tenant: $tenantA, role: 'owner'); $tenantB = Tenant::factory()->create([ 'workspace_id' => (int) $tenantA->workspace_id, ]); createUserWithTenant(tenant: $tenantB, user: $user, role: 'owner'); $partialRun = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'policy.sync', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::PartiallySucceeded->value, ]); $failedRun = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'policy.sync', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Failed->value, ]); $blockedRun = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'policy.sync', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Blocked->value, ]); $staleRun = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Queued->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subHour(), ]); $healthyActive = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Queued->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subMinute(), ]); $otherTenantFailed = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantB->getKey(), 'workspace_id' => (int) $tenantB->workspace_id, 'type' => 'policy.sync', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Failed->value, ]); $this->actingAs($user); Filament::setTenant($tenantA, true); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id); Livewire::withQueryParams([ 'tenant_id' => (string) $tenantA->getKey(), 'activeTab' => OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, 'problemClass' => OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, ]) ->actingAs($user) ->test(Operations::class) ->assertSet('tableFilters.tenant_id.value', (string) $tenantA->getKey()) ->assertSet('activeTab', OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP) ->assertCanSeeTableRecords([$partialRun, $failedRun, $blockedRun]) ->assertCanNotSeeTableRecords([$healthyActive, $otherTenantFailed]); }); it('allows workspace-originated operations drill-through to clear tenant context and show workspace-wide terminal follow-up', function (): void { $tenantA = Tenant::factory()->create(); [$user, $tenantA] = createUserWithTenant(tenant: $tenantA, role: 'owner'); $tenantB = Tenant::factory()->create([ 'workspace_id' => (int) $tenantA->workspace_id, ]); createUserWithTenant(tenant: $tenantB, user: $user, role: 'owner'); $workspaceRun = OperationRun::factory()->tenantlessForWorkspace($tenantA->workspace()->firstOrFail())->create([ 'type' => 'policy.sync', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Failed->value, ]); $otherTenantFailed = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantB->getKey(), 'workspace_id' => (int) $tenantB->workspace_id, 'type' => 'policy.sync', 'status' => OperationRunStatus::Completed->value, 'outcome' => OperationRunOutcome::Failed->value, ]); $healthyActive = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'inventory_sync', 'status' => OperationRunStatus::Running->value, 'outcome' => OperationRunOutcome::Pending->value, 'created_at' => now()->subMinute(), 'started_at' => now()->subMinute(), ]); $this->actingAs($user); Filament::setTenant($tenantA, true); session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id); Livewire::withQueryParams([ 'tenant_scope' => 'all', 'activeTab' => OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, 'problemClass' => OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, ]) ->actingAs($user) ->test(Operations::class) ->assertSet('tableFilters.tenant_id.value', null) ->assertSet('activeTab', OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP) ->assertCanSeeTableRecords([$workspaceRun, $otherTenantFailed]) ->assertCanNotSeeTableRecords([$healthyActive]); }); it('builds canonical dashboard operations URLs with tenant and tab continuity', function (): void { $tenant = Tenant::factory()->create(); expect(OperationRunLinks::index($tenant, activeTab: 'active')) ->toBe(route('admin.operations.index', [ 'tenant_id' => (int) $tenant->getKey(), 'activeTab' => 'active', ])) ->and(OperationRunLinks::index( $tenant, activeTab: OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, problemClass: OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, )) ->toBe(route('admin.operations.index', [ 'tenant_id' => (int) $tenant->getKey(), 'activeTab' => OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, 'problemClass' => OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, ])) ->and(OperationRunLinks::index( activeTab: OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, allTenants: true, problemClass: OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, )) ->toBe(route('admin.operations.index', [ 'tenant_scope' => 'all', 'activeTab' => OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, 'problemClass' => OperationRun::PROBLEM_CLASS_TERMINAL_FOLLOW_UP, ])); });