diff --git a/src/features/settings/__tests__/dialog.test.tsx b/src/features/settings/__tests__/dialog.test.tsx index f33d9d401..a4bc899e7 100644 --- a/src/features/settings/__tests__/dialog.test.tsx +++ b/src/features/settings/__tests__/dialog.test.tsx @@ -24,8 +24,9 @@ import { registerAction, executeAction } from "@/platform/actions"; import { useProject } from "@/platform/project"; import { useKeymap } from "@/platform/keymap"; import { ContextMenuHost } from "@/ui"; +import { PageContext, useSetting } from "../components/context"; import { DEFAULT_SETTINGS, setAt } from "../model/schema"; -import { stage, useSettingsDialog } from "../model/staging"; +import { openSettings, stage, useSettingsDialog } from "../model/staging"; import { SettingsDialog } from "../dialog/SettingsDialog"; import { activate } from ".."; import { MessagesHost } from "@/workbench/messages"; @@ -271,6 +272,37 @@ describe("Settings dialog", () => { }); }); + it("keeps object settings stable when child keys are staged (HTTP Proxy)", async () => { + const seen: Array<{ mode: string; host: string }> = []; + function Probe() { + const [proxy] = useSetting<{ mode: string; host: string }>("proxy", "global"); + seen.push(proxy); + return {`${proxy.mode}:${proxy.host}`}; + } + openSettings("general.httpProxy"); + const view = render( + + + , + ); + expect(screen.getByTestId("proxy")).toHaveTextContent("auto:"); + act(() => { + stage("general.httpProxy", "global", "proxy.mode", "manual"); + stage("general.httpProxy", "global", "proxy.host", "127.0.0.1"); + }); + expect(screen.getByTestId("proxy")).toHaveTextContent("manual:127.0.0.1"); + expect(seen.at(-1)).toMatchObject({ mode: "manual", host: "127.0.0.1" }); + view.unmount(); + + const dialog = await openDialog("general.httpProxy"); + fireEvent.click(within(dialog).getByRole("radio", { name: "Manual proxy configuration" })); + expect(within(dialog).getByRole("radio", { name: "Manual proxy configuration" })).toBeChecked(); + fireEvent.change(within(dialog).getByLabelText("Host name"), { target: { value: "127.0.0.1" } }); + expect(within(dialog).getByLabelText("Host name")).toHaveValue("127.0.0.1"); + fireEvent.click(within(dialog).getByRole("radio", { name: "No proxy" })); + expect(within(dialog).getByRole("radio", { name: "No proxy" })).toBeChecked(); + }); + it("survives invalid settings values", async () => { act(() => useProject.setState({ diff --git a/src/features/settings/components/context.ts b/src/features/settings/components/context.ts index 9e762f663..d0a3fc690 100644 --- a/src/features/settings/components/context.ts +++ b/src/features/settings/components/context.ts @@ -19,7 +19,7 @@ export function usePageContext(): PageContextValue { export function useSetting(key: string, scopeOverride?: Scope): [T, (value: T) => void] { const { pageId, scope: pageScope } = usePageContext(); const scope = scopeOverride ?? pageScope; - const value = useSettingsDialog((s) => stagedValue(s, scope, key)) as T; + const value = useStagedValue(scope, key) as T; const set = useCallback((v: T) => stage(pageId, scope, key, v), [pageId, scope, key]); return [value, set]; }