const { handleSearch } = require("../src/search"); describe("handleSearch", () => { let req; let res; beforeEach(() => { req = { query: {} }; // using .mockReturnThis() because of chainable methods res = { status: jest.fn().mockReturnThis(), send: jest.fn().mockReturnThis(), setHeader: jest.fn() }; }); // clean up the observed data after each test afterEach(() => { jest.restoreAllMocks(); }); test("returns 400 when query is missing", async () => { global.fetch = jest.fn().mockResolvedValue({ json: jest.fn().mockResolvedValue({ results: [ { url: "https://example.com", title: "Example", content: "Content", irrelevant: "removed" } ] }) }); await handleSearch(req, res); expect(res.status).toHaveBeenCalledWith(400); expect(res.send).toHaveBeenCalledWith("Missing search query"); expect(global.fetch).not.toHaveBeenCalled(); }); test("fetches search results and sends filtered JSON", async () => { req.query.query = "nodejs testing"; global.fetch = jest.fn().mockResolvedValue({ json: jest.fn().mockResolvedValue({ results: [ { url: "https://example.com", title: "Example", content: "Content", score: 0.8 } ] }) }); await handleSearch(req, res); expect(global.fetch).toHaveBeenCalledTimes(1); const [url, options] = global.fetch.mock.calls[0]; expect(url).toContain("/search?"); expect(url).toContain("q=nodejs+testing"); expect(url).toContain("engines=startpage"); expect(url).toContain("format=json"); expect(url).not.toContain("score=0.8"); expect(options).toEqual({ headers: { Accept: "application/json" } }); expect(res.setHeader).toHaveBeenCalledWith( "Content-Type", "application/json; charset=utf-8" ); expect(res.setHeader).toHaveBeenCalledWith( "Content-Disposition", 'attachment; filename="output.json"' ); expect(res.send).toHaveBeenCalledWith( JSON.stringify( [ { url: "https://example.com", title: "Example", content: "Content" } ], null, 2 ) ); }); test("uses an empty array when the API omits results", async () => { req.query.query = "empty"; global.fetch = jest.fn().mockResolvedValue({ json: jest.fn().mockResolvedValue({}) }); await handleSearch(req, res); expect(res.send).toHaveBeenCalledWith("[]"); }); test("returns 500 when fetch fails", async () => { req.query.query = "error"; global.fetch = jest .fn() .mockRejectedValue(new Error("SearxNG unavailable")); await handleSearch(req, res); expect(res.status).toHaveBeenCalledWith(500); expect(res.send).toHaveBeenCalledWith( "
Search failed!
See the console for the error.