fix: refine scraper output behavior

This commit is contained in:
2026-04-23 10:43:38 -04:00
parent 244a88e63c
commit 9c8643086a
4 changed files with 141 additions and 7 deletions

View File

@@ -234,6 +234,68 @@ describe("eBay Scraper Cookie Handling", () => {
]);
});
test("maps pound prices to GBP", async () => {
global.fetch = mock(() =>
Promise.resolve({
ok: true,
text: () =>
Promise.resolve(`
<html><body>
<li class="s-item">
<a href="/itm/123"></a>
<h3>Stable Laptop Bundle</h3>
<span class="s-item__price">£123.45</span>
</li>
</body></html>
`),
}),
) as typeof fetch;
const results = await fetchEbayItems("laptop", 1000);
expect(results).toEqual([
expect.objectContaining({
listingPrice: expect.objectContaining({ currency: "GBP", cents: 12345 }),
}),
]);
});
test("maps euro and yen prices to the matching currency labels", async () => {
global.fetch = mock(() =>
Promise.resolve({
ok: true,
text: () =>
Promise.resolve(`
<html><body>
<li class="s-item">
<a href="/itm/123"></a>
<h3>Euro Bundle</h3>
<span class="s-item__price">€123.45</span>
</li>
<li class="s-item">
<a href="/itm/456"></a>
<h3>Yen Bundle</h3>
<span class="s-item__price">¥123</span>
</li>
</body></html>
`),
}),
) as typeof fetch;
const results = await fetchEbayItems("bundle", 1000, {
keywords: ["bundle"],
});
expect(results).toEqual([
expect.objectContaining({
listingPrice: expect.objectContaining({ currency: "EUR", cents: 12345 }),
}),
expect.objectContaining({
listingPrice: expect.objectContaining({ currency: "JPY", cents: 12300 }),
}),
]);
});
test("prefers the discounted Canadian-formatted price", async () => {
global.fetch = mock(() =>
Promise.resolve({

View File

@@ -1,4 +1,5 @@
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
import cliProgress from "cli-progress";
import {
classifyFacebookResponse,
type FacebookListingDetails,
@@ -16,6 +17,8 @@ import type { UnstableListingBuckets } from "../src/types/common";
import { formatCookiesForHeader } from "../src/utils/cookies";
import { formatCentsToCurrency } from "../src/utils/format";
const originalStdoutIsTTY = process.stdout.isTTY;
type Assert<T extends true> = T;
type IsExact<T, U> =
(<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2
@@ -50,6 +53,7 @@ describe("Facebook Marketplace Scraper Core Tests", () => {
afterEach(() => {
global.fetch = originalFetch;
process.stdout.isTTY = originalStdoutIsTTY;
});
describe("Cookie Parsing", () => {
@@ -621,6 +625,68 @@ describe("Facebook Marketplace Scraper Core Tests", () => {
]);
});
test("does not start a progress bar when stdout is not a TTY", async () => {
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify({
payload: {
resultGroups: [
{
edges: [
{
node: {
listing: {
id: "1",
marketplace_listing_title: "Chair Listing",
listing_price: {
amount: "120.00",
formatted_amount: "CA$120",
currency: "CAD",
},
is_live: true,
},
},
},
],
},
],
},
})}</script></body></html>`;
process.stdout.isTTY = false;
const startSpy = mock(() => {});
const updateSpy = mock(() => {});
const stopSpy = mock(() => {});
const originalStart = cliProgress.SingleBar.prototype.start;
const originalUpdate = cliProgress.SingleBar.prototype.update;
const originalStop = cliProgress.SingleBar.prototype.stop;
try {
cliProgress.SingleBar.prototype.start = startSpy;
cliProgress.SingleBar.prototype.update = updateSpy;
cliProgress.SingleBar.prototype.stop = stopSpy;
global.fetch = mock(() =>
Promise.resolve({
ok: true,
text: () => Promise.resolve(mockSearchHtml),
url: "https://www.facebook.com/marketplace/toronto/search?query=chair",
headers: {
get: () => null,
},
}),
);
const results = await fetchFacebookItems("chair", 1, "toronto", 25);
expect(results).toHaveLength(1);
expect(startSpy).not.toHaveBeenCalled();
expect(updateSpy).not.toHaveBeenCalled();
expect(stopSpy).not.toHaveBeenCalled();
} finally {
cliProgress.SingleBar.prototype.start = originalStart;
cliProgress.SingleBar.prototype.update = originalUpdate;
cliProgress.SingleBar.prototype.stop = originalStop;
}
});
test("returns results and unstableResults when unstable mode is enabled", async () => {
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify({
payload: {