add: unit and integration testing
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
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(
|
||||
"<p><b>Search failed!<br>See the console for the error.</b></p>"
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user