create(); [$user, $tenantA] = createUserWithTenant($tenantA, role: 'owner'); $tenantB = Tenant::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $tenantA->workspace_id, ]); $user->tenants()->syncWithoutDetaching([ $tenantB->getKey() => ['role' => 'owner'], ]); $runA = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'policy.sync', 'initiator_name' => 'TenantA', ]); $runB = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantB->getKey(), 'workspace_id' => (int) $tenantB->workspace_id, 'type' => 'inventory_sync', 'initiator_name' => 'TenantB', ]); Filament::setTenant(null, true); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenantA->workspace_id]) ->get('/admin/operations') ->assertOk() ->assertSee('Policy sync') ->assertSee('Inventory sync') ->assertSee('TenantA') ->assertSee('TenantB'); }); it('serves /admin/operations/{run} with and without tenant context', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner'); $run = OperationRun::factory()->create([ 'tenant_id' => (int) $tenant->getKey(), 'workspace_id' => (int) $tenant->workspace_id, 'type' => 'policy.sync', ]); Filament::setTenant(null, true); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(route('admin.operations.view', ['run' => (int) $run->getKey()])) ->assertOk() ->assertSee('Operation run') ->assertDontSee('/admin/t/'.((int) $tenant->getKey()).'/operations/r/'.((int) $run->getKey())); Filament::setTenant($tenant, true); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(route('admin.operations.view', ['run' => (int) $run->getKey()])) ->assertOk() ->assertSee('Operation run'); }); it('keeps operation detail accessible when the active tenant context does not match the run tenant', 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'); $runB = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantB->getKey(), 'workspace_id' => (int) $tenantB->workspace_id, 'type' => 'inventory_sync', ]); Filament::setTenant($tenantA, true); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenantA->workspace_id]) ->get(route('admin.operations.view', ['run' => (int) $runB->getKey()])) ->assertOk() ->assertSee('Operation run'); }); it('defaults the tenant filter from tenant context and can be cleared', function (): void { $tenantA = Tenant::factory()->create(); [$user, $tenantA] = createUserWithTenant($tenantA, role: 'owner'); $tenantB = Tenant::factory()->create([ 'status' => 'active', 'workspace_id' => (int) $tenantA->workspace_id, ]); $user->tenants()->syncWithoutDetaching([ $tenantB->getKey() => ['role' => 'owner'], ]); $runA = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantA->getKey(), 'workspace_id' => (int) $tenantA->workspace_id, 'type' => 'policy.sync', 'initiator_name' => 'TenantA', ]); $runB = OperationRun::factory()->create([ 'tenant_id' => (int) $tenantB->getKey(), 'workspace_id' => (int) $tenantB->workspace_id, 'type' => 'inventory_sync', 'initiator_name' => 'TenantB', ]); Filament::setTenant($tenantA, true); $this->withSession([ WorkspaceContext::SESSION_KEY => (int) $tenantA->workspace_id, ]); session([ WorkspaceContext::SESSION_KEY => (int) $tenantA->workspace_id, ]); $component = Livewire::actingAs($user) ->test(Operations::class) ->assertCanSeeTableRecords([$runA]) ->assertCanNotSeeTableRecords([$runB]) ->assertSet('tableFilters.tenant_id.value', (string) $tenantA->getKey()); $component ->callAction('operate_hub_show_all_tenants') ->assertSet('tableFilters.tenant_id.value', null) ->assertRedirect('/admin/operations'); Filament::setTenant(null, true); Livewire::actingAs($user) ->test(Operations::class) ->assertSee('TenantA') ->assertSee('TenantB'); }); it('shows an explicit back-link when canonical context is present on the operations index', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner'); Filament::setTenant($tenant, true); $context = new CanonicalNavigationContext( sourceSurface: 'backup_set.detail_section', canonicalRouteName: 'admin.operations.index', tenantId: (int) $tenant->getKey(), backLinkLabel: 'Back to backup set', backLinkUrl: '/admin/tenant/backup-sets/1', ); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get(OperationRunLinks::index($tenant, $context)) ->assertOk() ->assertSee('Back to backup set') ->assertSee('/admin/tenant/backup-sets/1', false); }); it('keeps the canonical back-link action after Livewire hydration on the operations index', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner'); Filament::setTenant($tenant, true); $this->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]); session([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]); Livewire::withQueryParams([ 'nav' => [ 'source_surface' => 'finding.list_row', 'canonical_route_name' => 'admin.operations.index', 'tenant_id' => (int) $tenant->getKey(), 'back_label' => 'Back to findings', 'back_url' => '/admin/findings?tenant='.$tenant->external_id, ], ]) ->actingAs($user) ->test(Operations::class) ->assertActionVisible('operate_hub_back_to_origin_operations'); }); it('does not register legacy operation resource routes', function (): void { expect(Route::has('filament.admin.resources.operations.index'))->toBeFalse(); expect(Route::has('filament.admin.resources.operations.view'))->toBeFalse(); }); it('has reserved Monitoring placeholder pages for Alerts and Audit Log', function (): void { $tenant = Tenant::factory()->create(); [$user, $tenant] = createUserWithTenant($tenant, role: 'owner'); Filament::setTenant(null, true); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->followingRedirects() ->get('/admin/alerts') ->assertOk(); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id]) ->get('/admin/audit-log') ->assertOk(); });