diff --git a/src/components/widgets/search/search.jsx b/src/components/widgets/search/search.jsx index 486b89ccf..c41e299ca 100644 --- a/src/components/widgets/search/search.jsx +++ b/src/components/widgets/search/search.jsx @@ -139,6 +139,8 @@ export default function Search({ options }) { }, [selectedProvider, options, query, searchSuggestions]); function doSearch(value) { + if (!value) return; + const q = encodeURIComponent(value); const { url } = selectedProvider; if (url) { diff --git a/src/components/widgets/search/search.test.jsx b/src/components/widgets/search/search.test.jsx index 6c0fb0328..dee084dce 100644 --- a/src/components/widgets/search/search.test.jsx +++ b/src/components/widgets/search/search.test.jsx @@ -24,7 +24,19 @@ vi.mock("@headlessui/react", async () => {
{children}
), - ComboboxInput: (props) => , + ComboboxInput: (props) => { + const ctx = useContext(ComboboxContext); + // real headlessui fires onChange(null) when the input is cleared + return ( + { + props.onChange?.(event); + if (event.target.value === "") ctx?.onChange?.(null); + }} + /> + ); + }, ComboboxOption: ({ as: As = "div", value, children, ...props }) => { const ctx = useContext(ComboboxContext); const content = typeof children === "function" ? children({ active: false }) : children; @@ -83,6 +95,21 @@ describe("components/widgets/search", () => { openSpy.mockRestore(); }); + it("does not search when the input is cleared", () => { + const openSpy = vi.spyOn(window, "open").mockImplementation(() => null); + + renderWithProviders(, { + settings: {}, + }); + + const input = screen.getByPlaceholderText("search.placeholder"); + fireEvent.change(input, { target: { value: "a" } }); + fireEvent.change(input, { target: { value: "" } }); + + expect(openSpy).not.toHaveBeenCalled(); + openSpy.mockRestore(); + }); + it("accepts provider configured as a string", () => { const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);