fix(ui): narrow the web search settings response instead of asserting its shape

This commit is contained in:
Yuneng Jiang 2026-09-19 14:25:19 -07:00
parent 8dab23f6ac
commit e7fd89fc02
No known key found for this signature in database
2 changed files with 35 additions and 2 deletions

View file

@ -127,6 +127,29 @@ describe("WebSearchInterceptionSettings", () => {
expect(mockMutate.mock.calls[0][0]).toEqual(ENABLED_PAYLOAD);
});
it("ignores stored values whose types do not match the field", async () => {
vi.mocked(useWebSearchInterceptionSettings).mockReturnValue({
data: {
...storedSettings,
values: {
enabled: "yes",
enabled_providers: "bedrock",
search_tool_name: 7,
max_agentic_loops: "3",
},
},
isLoading: false,
isError: false,
error: null,
} as any);
await renderSettings();
expect(screen.getByRole("switch")).not.toBeChecked();
expect(screen.getByLabelText(/max agentic loops/i)).toHaveValue(null);
expect(screen.queryByText("bedrock")).not.toBeInTheDocument();
});
it("reseeds the form when the stored settings change underneath it", async () => {
vi.mocked(useWebSearchInterceptionSettings).mockReturnValue({
data: { ...storedSettings, values: { ...storedSettings.values, max_agentic_loops: 3 } },

View file

@ -45,7 +45,7 @@ interface WebSearchInterceptionFormValues {
max_agentic_loops: number | null;
}
const NO_STORED_VALUES: WebSearchInterceptionStoredValues = {};
const NO_STORED_VALUES: Readonly<Record<string, unknown>> = {};
const MAX_AGENTIC_LOOPS_MIN = 1;
@ -69,6 +69,16 @@ const labelWithHint = (label: string, hint: string): React.ReactNode => (
const parseLoops = (raw: string, rawAsNumber: number): number | null =>
raw === "" || Number.isNaN(rawAsNumber) ? null : rawAsNumber;
const isStringArray = (value: unknown): value is string[] =>
Array.isArray(value) && value.every((entry) => typeof entry === "string");
const toStoredValues = (raw: Readonly<Record<string, unknown>>): WebSearchInterceptionStoredValues => ({
enabled: typeof raw.enabled === "boolean" ? raw.enabled : undefined,
enabled_providers: isStringArray(raw.enabled_providers) ? raw.enabled_providers : undefined,
search_tool_name: typeof raw.search_tool_name === "string" ? raw.search_tool_name : null,
max_agentic_loops: typeof raw.max_agentic_loops === "number" ? raw.max_agentic_loops : null,
});
const toFormValues = (values: WebSearchInterceptionStoredValues): WebSearchInterceptionFormValues => ({
enabled: values.enabled ?? false,
enabled_providers: values.enabled_providers ?? [],
@ -282,7 +292,7 @@ export default function WebSearchInterceptionSettings() {
);
}
const values: WebSearchInterceptionStoredValues = data?.values ?? NO_STORED_VALUES;
const values: WebSearchInterceptionStoredValues = toStoredValues(data?.values ?? NO_STORED_VALUES);
return (
<div className="w-full">