fix(dataforseo): accept empty live SERPs (#451)

This commit is contained in:
Ben Senescu 2026-08-26 09:48:32 -04:00 committed by GitHub
parent ce7570e898
commit 3fc1f4ec34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 1 deletions

View File

@ -5,6 +5,7 @@ vi.mock("@/server/lib/runtime-env", () => ({
})); }));
import { import {
fetchLiveSerp,
fetchRankCheckTaskResult, fetchRankCheckTaskResult,
postRankCheckTasks, postRankCheckTasks,
} from "@/server/lib/dataforseo/serp"; } from "@/server/lib/dataforseo/serp";
@ -17,6 +18,43 @@ function parseDataforseoRequestBody(init: RequestInit | undefined): unknown {
return JSON.parse(body) as unknown; return JSON.parse(body) as unknown;
} }
describe("live SERP", () => {
// 40102 is the documented "No Search Results." code (40501 is "Invalid
// Field."). isNoResultsTask matches on the status message, not the code, so
// this stays correct whichever code DataForSEO attaches to the message.
it("returns an empty result for DataForSEO's no-results task", async () => {
vi.stubGlobal(
"fetch",
vi.fn<typeof fetch>().mockResolvedValue(
Response.json({
status_code: 20000,
tasks: [
{
status_code: 40102,
status_message: "No Search Results.",
path: ["v3", "serp", "google", "organic", "live", "advanced"],
cost: 0.002,
result_count: 0,
result: [],
},
],
}),
),
);
await expect(
fetchLiveSerp({
keyword: "obscure query",
locationCode: 2840,
languageCode: "en",
}),
).resolves.toMatchObject({
data: [],
billing: { costUsd: 0.002 },
});
});
});
describe("rank check task queue", () => { describe("rank check task queue", () => {
beforeEach(() => { beforeEach(() => {
vi.restoreAllMocks(); vi.restoreAllMocks();

View File

@ -92,7 +92,9 @@ export async function fetchLiveSerp(input: {
}, },
], ],
); );
const task = assertOk(response); // DataForSEO uses a task error for a valid empty SERP. Keep the charged
// response in the normal billing path and return an empty item list.
const task = assertOk(response, { treatNoResultsAsEmpty: true });
return { return {
data: parseTaskItems( data: parseTaskItems(
"google-organic-live-advanced", "google-organic-live-advanced",