*/ function spec338EnvironmentNavigationRows(array $items): array { $rows = []; foreach ($items as $item) { if (! $item instanceof NavigationItem || ! $item->isVisible()) { continue; } $group = $item->getGroup(); $rows[] = [ 'label' => $item->getLabel(), 'group' => $group instanceof UnitEnum ? $group->name : (is_string($group) ? $group : null), 'url' => $item->getUrl(), 'parent' => $item->getParentItem(), ]; $childItems = $item->getChildItems(); if ($childItems instanceof Traversable) { $childItems = iterator_to_array($childItems); } if (is_array($childItems) && $childItems !== []) { $rows = [ ...$rows, ...spec338EnvironmentNavigationRows($childItems), ]; } } return $rows; } function spec338FindNavigationRow(string $label, ?string $group = null): ?array { foreach (spec338EnvironmentNavigationRows(Filament::getCurrentOrDefaultPanel()->getNavigationItems()) as $row) { if ($row['label'] !== $label) { continue; } if ($group !== null && $row['group'] !== $group) { continue; } return $row; } return null; } it('separates workspace-wide and workspace-admin links from environment navigation', function (): void { $environment = ManagedEnvironment::factory()->active()->create(['name' => 'Spec338 IA Environment']); [$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'owner'); $workspace = $environment->workspace()->firstOrFail(); $workspaceWideGroup = __('localization.navigation.workspace_wide'); $workspaceAdminGroup = __('localization.navigation.workspace_admin'); $response = $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()]) ->get(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $environment)); $response ->assertOk() ->assertSee($workspaceWideGroup) ->assertSee($workspaceAdminGroup); $overview = spec338FindNavigationRow('Overview'); $operations = spec338FindNavigationRow(__('localization.navigation.operations'), $workspaceWideGroup); $manageWorkspaces = spec338FindNavigationRow(__('localization.navigation.manage_workspaces'), $workspaceAdminGroup); $integrations = spec338FindNavigationRow(__('localization.navigation.integrations'), $workspaceAdminGroup); expect($overview)->not->toBeNull() ->and($overview['url'])->toBe(EnvironmentDashboard::getUrl(panel: 'admin', tenant: $environment)) ->and($operations)->not->toBeNull() ->and($operations['url'])->toContain('environment_id='.(int) $environment->getKey()) ->and($operations['url'])->not->toContain('tableFilters') ->and($operations['url'])->not->toContain('managed_environment_id=') ->and($manageWorkspaces)->not->toBeNull() ->and($integrations)->not->toBeNull() ->and($integrations['url'])->toContain('environment_id='.(int) $environment->getKey()); }); it('keeps workspace-owned sidebar groups normal on workspace pages', function (): void { $environment = ManagedEnvironment::factory()->active()->create(['name' => 'Spec338 Workspace IA Environment']); [$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'owner'); $workspace = $environment->workspace()->firstOrFail(); $this->actingAs($user) ->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()]) ->get(route('admin.workspace.home', ['workspace' => $workspace])) ->assertOk(); $operations = spec338FindNavigationRow(__('localization.navigation.operations')); expect($operations)->not->toBeNull() ->and($operations['url'])->not->toContain('environment_id=') ->and($operations['url'])->not->toContain('tableFilters'); });