diff --git a/packages/api-server/src/routes/ebay.ts b/packages/api-server/src/routes/ebay.ts index 17540df..0dc04db 100644 --- a/packages/api-server/src/routes/ebay.ts +++ b/packages/api-server/src/routes/ebay.ts @@ -37,17 +37,34 @@ export async function ebayRoute(req: Request): Promise { const maxItemsParam = reqUrl.searchParams.get("maxItems"); const maxItems = maxItemsParam ? parseInt(maxItemsParam, 10) : undefined; - const items = await fetchEbayItems(SEARCH_QUERY, 1, { - minPrice, - maxPrice, - strictMode, - exclusions, - keywords, - buyItNowOnly, - canadaOnly, - }); + const hideUnstableResults = + reqUrl.searchParams.get("unstableFilter") === "true"; + const items = hideUnstableResults + ? await fetchEbayItems( + SEARCH_QUERY, + 1, + { + minPrice, + maxPrice, + strictMode, + exclusions, + keywords, + buyItNowOnly, + canadaOnly, + }, + { hideUnstableResults: true }, + ) + : await fetchEbayItems(SEARCH_QUERY, 1, { + minPrice, + maxPrice, + strictMode, + exclusions, + keywords, + buyItNowOnly, + canadaOnly, + }); - const results = maxItems ? items.slice(0, maxItems) : items; + const results = hideUnstableResults || !maxItems ? items : items.slice(0, maxItems); if (!results || results.length === 0) return Response.json( diff --git a/packages/api-server/src/routes/facebook.ts b/packages/api-server/src/routes/facebook.ts index 048cd90..6038a27 100644 --- a/packages/api-server/src/routes/facebook.ts +++ b/packages/api-server/src/routes/facebook.ts @@ -20,9 +20,15 @@ export async function facebookRoute(req: Request): Promise { const LOCATION = reqUrl.searchParams.get("location") || "toronto"; const maxItemsParam = reqUrl.searchParams.get("maxItems"); const maxItems = maxItemsParam ? parseInt(maxItemsParam, 10) : 25; + const hideUnstableResults = + reqUrl.searchParams.get("unstableFilter") === "true"; try { - const items = await fetchFacebookItems(SEARCH_QUERY, 1, LOCATION, maxItems); + const items = hideUnstableResults + ? await fetchFacebookItems(SEARCH_QUERY, 1, LOCATION, maxItems, { + hideUnstableResults: true, + }) + : await fetchFacebookItems(SEARCH_QUERY, 1, LOCATION, maxItems); if (!items || items.length === 0) return Response.json( { message: "Search didn't return any results!" }, diff --git a/packages/api-server/src/routes/kijiji.ts b/packages/api-server/src/routes/kijiji.ts index 6b8ea18..a51302b 100644 --- a/packages/api-server/src/routes/kijiji.ts +++ b/packages/api-server/src/routes/kijiji.ts @@ -23,6 +23,8 @@ export async function kijijiRoute(req: Request): Promise { const priceMin = priceMinParam ? parseInt(priceMinParam, 10) : undefined; const priceMaxParam = reqUrl.searchParams.get("priceMax"); const priceMax = priceMaxParam ? parseInt(priceMaxParam, 10) : undefined; + const hideUnstableResults = + reqUrl.searchParams.get("unstableFilter") === "true"; const searchOptions = { location: reqUrl.searchParams.get("location") || undefined, @@ -45,13 +47,22 @@ export async function kijijiRoute(req: Request): Promise { }; try { - const items = await fetchKijijiItems( - SEARCH_QUERY, - 4, // 4 requests per second for faster scraping - "https://www.kijiji.ca", - searchOptions, - {}, - ); + const items = hideUnstableResults + ? await fetchKijijiItems( + SEARCH_QUERY, + 4, // 4 requests per second for faster scraping + "https://www.kijiji.ca", + searchOptions, + {}, + { hideUnstableResults: true }, + ) + : await fetchKijijiItems( + SEARCH_QUERY, + 4, // 4 requests per second for faster scraping + "https://www.kijiji.ca", + searchOptions, + {}, + ); if (!items) return Response.json( { message: "Search didn't return any results!" }, diff --git a/packages/api-server/test/routes.test.ts b/packages/api-server/test/routes.test.ts index e6b54a6..0d7f807 100644 --- a/packages/api-server/test/routes.test.ts +++ b/packages/api-server/test/routes.test.ts @@ -2,10 +2,12 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"; const fetchFacebookItems = mock(() => Promise.resolve([{ title: "item" }])); const fetchEbayItems = mock(() => Promise.resolve([{ title: "item" }])); +const fetchKijijiItems = mock(() => Promise.resolve([{ title: "item" }])); mock.module("@marketplace-scrapers/core", () => ({ fetchFacebookItems, fetchEbayItems, + fetchKijijiItems, })); describe("API routes", () => { @@ -18,11 +20,16 @@ describe("API routes", () => { fetchEbayItems.mockImplementation(() => Promise.resolve([{ title: "item" }]), ); + fetchKijijiItems.mockReset(); + fetchKijijiItems.mockImplementation(() => + Promise.resolve([{ title: "item" }]), + ); }); afterEach(() => { fetchFacebookItems.mockClear(); fetchEbayItems.mockClear(); + fetchKijijiItems.mockClear(); }); test("facebookRoute ignores cookies query parameter", async () => { @@ -56,4 +63,99 @@ describe("API routes", () => { canadaOnly: true, }); }); + + test("kijijiRoute ignores cookies query parameter", async () => { + const { kijijiRoute } = await import("../src/routes/kijiji"); + + await kijijiRoute( + new Request( + "http://localhost/api/kijiji?q=laptop&cookies=s%3D1&maxPages=3", + ), + ); + + expect(fetchKijijiItems).toHaveBeenCalledWith( + "laptop", + 4, + "https://www.kijiji.ca", + { + location: undefined, + category: undefined, + keywords: undefined, + sortBy: null, + sortOrder: null, + maxPages: 3, + priceMin: undefined, + priceMax: undefined, + cookies: "s=1", + }, + {}, + ); + }); + + test("facebookRoute forwards unstableFilter=true to core", async () => { + const { facebookRoute } = await import("../src/routes/facebook"); + + await facebookRoute( + new Request( + "http://localhost/api/facebook?q=laptop&location=toronto&maxItems=3&unstableFilter=true", + ), + ); + + expect(fetchFacebookItems).toHaveBeenCalledWith("laptop", 1, "toronto", 3, { + hideUnstableResults: true, + }); + }); + + test("ebayRoute forwards unstableFilter=true to core", async () => { + const { ebayRoute } = await import("../src/routes/ebay"); + + await ebayRoute( + new Request( + "http://localhost/api/ebay?q=laptop&buyItNowOnly=true&unstableFilter=true", + ), + ); + + expect(fetchEbayItems).toHaveBeenCalledWith("laptop", 1, { + minPrice: undefined, + maxPrice: undefined, + strictMode: false, + exclusions: [], + keywords: ["laptop"], + buyItNowOnly: true, + canadaOnly: true, + }, { + hideUnstableResults: true, + }); + }); + + test("kijijiRoute forwards unstableFilter=true to core", async () => { + const { kijijiRoute } = await import("../src/routes/kijiji"); + + await kijijiRoute( + new Request( + "http://localhost/api/kijiji?q=laptop&maxPages=5&unstableFilter=true", + ), + ); + + expect(fetchKijijiItems).toHaveBeenCalledWith( + "laptop", + 4, + "https://www.kijiji.ca", + { + location: undefined, + category: undefined, + keywords: undefined, + sortBy: null, + sortOrder: null, + maxPages: 5, + priceMin: undefined, + priceMax: undefined, + cookies: undefined, + }, + {}, + { + hideUnstableResults: true, + }, + ); + }); });