diff --git a/src/ui/sidebar/AdminSettingsPanel.tsx b/src/ui/sidebar/AdminSettingsPanel.tsx index 535126c2d..4c91c589c 100644 --- a/src/ui/sidebar/AdminSettingsPanel.tsx +++ b/src/ui/sidebar/AdminSettingsPanel.tsx @@ -217,6 +217,12 @@ export function AdminSettingsPanel({ setUserPage(0); }, [userSearch]); + // The panel stays mounted across Settings pages, so an open user view + // would otherwise replace whichever section is picked next. + useEffect(() => { + setManageUser(null); + }, [section]); + useEffect(() => { onEditingChange?.(manageUser !== null); return () => onEditingChange?.(false); diff --git a/src/ui/tests/sidebar/AdminSettingsPanel.test.tsx b/src/ui/tests/sidebar/AdminSettingsPanel.test.tsx new file mode 100644 index 000000000..8402b00b9 --- /dev/null +++ b/src/ui/tests/sidebar/AdminSettingsPanel.test.tsx @@ -0,0 +1,113 @@ +import { describe, it, expect, vi, afterEach } from "vitest"; +import { cleanup, render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; + +import { AdminSettingsPanel } from "../../sidebar/AdminSettingsPanel"; +import type { AdminUser } from "../../sidebar/AdminManagementSections"; + +vi.mock("@/main-axios", () => ({ + getUserList: vi.fn(async () => ({ users: [], total: 0 })), + getSessions: vi.fn(async () => ({ sessions: [] })), + getRoles: vi.fn(async () => ({ roles: [] })), + getApiKeys: vi.fn(async () => ({ apiKeys: [] })), + getUserRoles: vi.fn(async () => ({ roles: [] })), + isElectron: () => false, +})); + +vi.mock("@/api/settings-api", () => ({})); +vi.mock("@/api/tls-api", () => ({ getTlsStatus: vi.fn(async () => null) })); +vi.mock("@/api/private-endpoints-api", () => ({})); + +vi.mock("@/contexts/BrandingContext", () => ({ + useBranding: () => ({ applyBranding: vi.fn() }), +})); + +vi.mock("@/components/surface/surface-scope", () => ({ + useConfirm: () => vi.fn(async () => true), +})); + +vi.mock("@/settings/FeatureSettingsSections", () => ({ + FeatureSettingsSection: () => null, + featureSectionId: (id: string) => `feature:${id}`, + useFeatureSettings: () => [], +})); + +vi.mock("react-i18next", () => ({ + useTranslation: () => ({ t: (key: string) => key }), +})); + +vi.mock("sonner", () => ({ + toast: { success: vi.fn(), error: vi.fn() }, +})); + +const { bob, section } = vi.hoisted(() => ({ + bob: { + id: "u2", + username: "bob", + isAdmin: false, + isExternal: false, + passwordHash: "hash", + dataUnlocked: true, + } as AdminUser, + section: + (label: string) => + ({ open }: { open: boolean }) => + open ?