chore: biome lint and formatting
Signed-off-by: Dmytro Stanchiev <git@dmytros.dev>
This commit is contained in:
@@ -136,7 +136,9 @@ describe("eBay Scraper Cookie Handling", () => {
|
||||
|
||||
expect(results).toHaveLength(1);
|
||||
expect(results[0]).toEqual(
|
||||
expect.objectContaining({ url: "https://www.ebay.ca/itm/123?_trkparms=foo" }),
|
||||
expect.objectContaining({
|
||||
url: "https://www.ebay.ca/itm/123?_trkparms=foo",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -229,7 +231,10 @@ describe("eBay Scraper Cookie Handling", () => {
|
||||
|
||||
expect(results).toEqual([
|
||||
expect.objectContaining({
|
||||
listingPrice: expect.objectContaining({ currency: "USD", cents: 12345 }),
|
||||
listingPrice: expect.objectContaining({
|
||||
currency: "USD",
|
||||
cents: 12345,
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
@@ -255,7 +260,10 @@ describe("eBay Scraper Cookie Handling", () => {
|
||||
|
||||
expect(results).toEqual([
|
||||
expect.objectContaining({
|
||||
listingPrice: expect.objectContaining({ currency: "USD", cents: 12345 }),
|
||||
listingPrice: expect.objectContaining({
|
||||
currency: "USD",
|
||||
cents: 12345,
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
@@ -281,7 +289,10 @@ describe("eBay Scraper Cookie Handling", () => {
|
||||
|
||||
expect(results).toEqual([
|
||||
expect.objectContaining({
|
||||
listingPrice: expect.objectContaining({ currency: "GBP", cents: 12345 }),
|
||||
listingPrice: expect.objectContaining({
|
||||
currency: "GBP",
|
||||
cents: 12345,
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
@@ -314,10 +325,16 @@ describe("eBay Scraper Cookie Handling", () => {
|
||||
|
||||
expect(results).toEqual([
|
||||
expect.objectContaining({
|
||||
listingPrice: expect.objectContaining({ currency: "EUR", cents: 12345 }),
|
||||
listingPrice: expect.objectContaining({
|
||||
currency: "EUR",
|
||||
cents: 12345,
|
||||
}),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
listingPrice: expect.objectContaining({ currency: "JPY", cents: 12300 }),
|
||||
listingPrice: expect.objectContaining({
|
||||
currency: "JPY",
|
||||
cents: 12300,
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -2,13 +2,13 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
||||
import cliProgress from "cli-progress";
|
||||
import {
|
||||
classifyFacebookResponse,
|
||||
type FacebookListingDetails,
|
||||
ensureFacebookCookies,
|
||||
extractFacebookBootstrapCandidates,
|
||||
extractFacebookItemData,
|
||||
extractFacebookMarketplaceData,
|
||||
default as fetchFacebookItems,
|
||||
type FacebookListingDetails,
|
||||
fetchFacebookItem,
|
||||
default as fetchFacebookItems,
|
||||
parseFacebookAds,
|
||||
parseFacebookCookieString,
|
||||
parseFacebookItem,
|
||||
@@ -30,9 +30,13 @@ type IsExact<T, U> =
|
||||
const getDefaultFacebookItems = async () => fetchFacebookItems("chair");
|
||||
const getUnstableFacebookItems = async (): Promise<
|
||||
UnstableListingBuckets<FacebookListingDetails>
|
||||
> => fetchFacebookItems("chair", 1, "toronto", 25, { hideUnstableResults: true });
|
||||
> =>
|
||||
fetchFacebookItems("chair", 1, "toronto", 25, { hideUnstableResults: true });
|
||||
type _FacebookDefaultReturn = Assert<
|
||||
IsExact<Awaited<ReturnType<typeof getDefaultFacebookItems>>, FacebookListingDetails[]>
|
||||
IsExact<
|
||||
Awaited<ReturnType<typeof getDefaultFacebookItems>>,
|
||||
FacebookListingDetails[]
|
||||
>
|
||||
>;
|
||||
type _FacebookUnstableReturn = Assert<
|
||||
IsExact<
|
||||
@@ -533,30 +537,32 @@ describe("Facebook Marketplace Scraper Core Tests", () => {
|
||||
});
|
||||
|
||||
test("returns an array by default", async () => {
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify({
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "1",
|
||||
marketplace_listing_title: "Stable Chair Listing",
|
||||
listing_price: {
|
||||
amount: "120.00",
|
||||
formatted_amount: "CA$120",
|
||||
currency: "CAD",
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify(
|
||||
{
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "1",
|
||||
marketplace_listing_title: "Stable Chair Listing",
|
||||
listing_price: {
|
||||
amount: "120.00",
|
||||
formatted_amount: "CA$120",
|
||||
currency: "CAD",
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})}</script></body></html>`;
|
||||
)}</script></body></html>`;
|
||||
|
||||
global.fetch = mock(() =>
|
||||
Promise.resolve({
|
||||
@@ -576,30 +582,32 @@ describe("Facebook Marketplace Scraper Core Tests", () => {
|
||||
});
|
||||
|
||||
test("preserves free listings through the public fetch entrypoint", async () => {
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify({
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "free-1",
|
||||
marketplace_listing_title: "Free Chair",
|
||||
listing_price: {
|
||||
amount: "0.00",
|
||||
formatted_amount: "FREE",
|
||||
currency: "CAD",
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify(
|
||||
{
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "free-1",
|
||||
marketplace_listing_title: "Free Chair",
|
||||
listing_price: {
|
||||
amount: "0.00",
|
||||
formatted_amount: "FREE",
|
||||
currency: "CAD",
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})}</script></body></html>`;
|
||||
)}</script></body></html>`;
|
||||
|
||||
global.fetch = mock(() =>
|
||||
Promise.resolve({
|
||||
@@ -626,30 +634,32 @@ 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",
|
||||
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,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})}</script></body></html>`;
|
||||
)}</script></body></html>`;
|
||||
|
||||
process.stdout.isTTY = false;
|
||||
const startSpy = mock(() => {});
|
||||
@@ -688,58 +698,60 @@ describe("Facebook Marketplace Scraper Core Tests", () => {
|
||||
});
|
||||
|
||||
test("returns results and unstableResults when unstable mode is enabled", async () => {
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify({
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "1",
|
||||
marketplace_listing_title: "Stable Chair Listing",
|
||||
listing_price: {
|
||||
amount: "100.00",
|
||||
formatted_amount: "CA$100",
|
||||
currency: "CAD",
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify(
|
||||
{
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "1",
|
||||
marketplace_listing_title: "Stable Chair Listing",
|
||||
listing_price: {
|
||||
amount: "100.00",
|
||||
formatted_amount: "CA$100",
|
||||
currency: "CAD",
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "2",
|
||||
marketplace_listing_title: "Another Stable Chair",
|
||||
listing_price: {
|
||||
amount: "110.00",
|
||||
formatted_amount: "CA$110",
|
||||
currency: "CAD",
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "2",
|
||||
marketplace_listing_title: "Another Stable Chair",
|
||||
listing_price: {
|
||||
amount: "110.00",
|
||||
formatted_amount: "CA$110",
|
||||
currency: "CAD",
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "3",
|
||||
marketplace_listing_title: "Suspiciously Cheap Chair",
|
||||
listing_price: {
|
||||
amount: "70.00",
|
||||
formatted_amount: "CA$70",
|
||||
currency: "CAD",
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "3",
|
||||
marketplace_listing_title: "Suspiciously Cheap Chair",
|
||||
listing_price: {
|
||||
amount: "70.00",
|
||||
formatted_amount: "CA$70",
|
||||
currency: "CAD",
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})}</script></body></html>`;
|
||||
)}</script></body></html>`;
|
||||
|
||||
global.fetch = mock(() =>
|
||||
Promise.resolve({
|
||||
@@ -768,58 +780,61 @@ describe("Facebook Marketplace Scraper Core Tests", () => {
|
||||
});
|
||||
|
||||
test("unstable mode classifies before the final MAX_ITEMS limit", async () => {
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify({
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "1",
|
||||
marketplace_listing_title: "Boundary Stable Chair",
|
||||
listing_price: {
|
||||
amount: "100.00",
|
||||
formatted_amount: "CA$100",
|
||||
currency: "CAD",
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify(
|
||||
{
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "1",
|
||||
marketplace_listing_title: "Boundary Stable Chair",
|
||||
listing_price: {
|
||||
amount: "100.00",
|
||||
formatted_amount: "CA$100",
|
||||
currency: "CAD",
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "2",
|
||||
marketplace_listing_title: "Second Boundary Stable Chair",
|
||||
listing_price: {
|
||||
amount: "110.00",
|
||||
formatted_amount: "CA$110",
|
||||
currency: "CAD",
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "2",
|
||||
marketplace_listing_title:
|
||||
"Second Boundary Stable Chair",
|
||||
listing_price: {
|
||||
amount: "110.00",
|
||||
formatted_amount: "CA$110",
|
||||
currency: "CAD",
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "3",
|
||||
marketplace_listing_title: "Past Boundary Cheap Chair",
|
||||
listing_price: {
|
||||
amount: "70.00",
|
||||
formatted_amount: "CA$70",
|
||||
currency: "CAD",
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "3",
|
||||
marketplace_listing_title: "Past Boundary Cheap Chair",
|
||||
listing_price: {
|
||||
amount: "70.00",
|
||||
formatted_amount: "CA$70",
|
||||
currency: "CAD",
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})}</script></body></html>`;
|
||||
)}</script></body></html>`;
|
||||
|
||||
global.fetch = mock(() =>
|
||||
Promise.resolve({
|
||||
@@ -869,7 +884,10 @@ describe("Facebook Marketplace Scraper Core Tests", () => {
|
||||
},
|
||||
redacted_description: { text: "Solid wood chair" },
|
||||
location_text: { text: "Toronto, ON" },
|
||||
marketplace_listing_seller: { id: "seller-1", name: "Alex" },
|
||||
marketplace_listing_seller: {
|
||||
id: "seller-1",
|
||||
name: "Alex",
|
||||
},
|
||||
condition: "USED",
|
||||
is_live: true,
|
||||
},
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
||||
import fetchFacebookItems, { fetchFacebookItem } from "../src/scrapers/facebook";
|
||||
import fetchFacebookItems, {
|
||||
fetchFacebookItem,
|
||||
} from "../src/scrapers/facebook";
|
||||
|
||||
// Mock fetch globally
|
||||
const originalFetch = global.fetch;
|
||||
@@ -27,35 +29,37 @@ describe("Facebook Marketplace Scraper Integration Tests", () => {
|
||||
|
||||
describe("Main Search Function", () => {
|
||||
test("should successfully fetch search results", async () => {
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify({
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "1",
|
||||
marketplace_listing_title: "iPhone 13",
|
||||
listing_price: {
|
||||
amount: "500.00",
|
||||
formatted_amount: "CA$500",
|
||||
currency: "CAD",
|
||||
},
|
||||
location: {
|
||||
reverse_geocode: {
|
||||
city_page: { display_name: "Toronto" },
|
||||
const mockSearchHtml = `<html><body><script>"XCometMarketplaceSearchController"</script><script>${JSON.stringify(
|
||||
{
|
||||
payload: {
|
||||
resultGroups: [
|
||||
{
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
listing: {
|
||||
id: "1",
|
||||
marketplace_listing_title: "iPhone 13",
|
||||
listing_price: {
|
||||
amount: "500.00",
|
||||
formatted_amount: "CA$500",
|
||||
currency: "CAD",
|
||||
},
|
||||
location: {
|
||||
reverse_geocode: {
|
||||
city_page: { display_name: "Toronto" },
|
||||
},
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
is_live: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})}</script></body></html>`;
|
||||
)}</script></body></html>`;
|
||||
|
||||
global.fetch = mock(() =>
|
||||
Promise.resolve({
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
||||
import {
|
||||
buildSearchUrl,
|
||||
default as fetchKijijiItems,
|
||||
type DetailedListing,
|
||||
default as fetchKijijiItems,
|
||||
NetworkError,
|
||||
parseSearch,
|
||||
parseDetailedListing,
|
||||
ParseError,
|
||||
parseDetailedListing,
|
||||
parseSearch,
|
||||
RateLimitError,
|
||||
resolveCategoryId,
|
||||
resolveLocationId,
|
||||
@@ -282,7 +282,8 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-low/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Low Listing", 7000, "v-low/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(listingHtml("Low Listing", 7000, "v-low/k0l0")),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -291,7 +292,8 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-mid/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Mid Listing", 9000, "v-mid/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(listingHtml("Mid Listing", 9000, "v-mid/k0l0")),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -300,7 +302,8 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-high/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("High Listing", 12000, "v-high/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(listingHtml("High Listing", 12000, "v-high/k0l0")),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -534,9 +537,18 @@ describe("fetchKijijiItems", () => {
|
||||
props: {
|
||||
pageProps: {
|
||||
__APOLLO_STATE__: {
|
||||
"Listing:1": { url: "/v-stable-one/k0l0", title: "Stable Listing One" },
|
||||
"Listing:2": { url: "/v-stable-two/k0l0", title: "Stable Listing Two" },
|
||||
"Listing:3": { url: "/v-unstable/k0l0", title: "Unstable Listing" },
|
||||
"Listing:1": {
|
||||
url: "/v-stable-one/k0l0",
|
||||
title: "Stable Listing One",
|
||||
},
|
||||
"Listing:2": {
|
||||
url: "/v-stable-two/k0l0",
|
||||
title: "Stable Listing Two",
|
||||
},
|
||||
"Listing:3": {
|
||||
url: "/v-unstable/k0l0",
|
||||
title: "Unstable Listing",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -582,7 +594,10 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-stable-one/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Stable Listing One", 10000, "v-stable-one/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(
|
||||
listingHtml("Stable Listing One", 10000, "v-stable-one/k0l0"),
|
||||
),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -591,7 +606,10 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-stable-two/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Stable Listing Two", 11000, "v-stable-two/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(
|
||||
listingHtml("Stable Listing Two", 11000, "v-stable-two/k0l0"),
|
||||
),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -600,7 +618,10 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-unstable/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Unstable Listing", 7000, "v-unstable/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(
|
||||
listingHtml("Unstable Listing", 7000, "v-unstable/k0l0"),
|
||||
),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -635,10 +656,22 @@ describe("fetchKijijiItems", () => {
|
||||
props: {
|
||||
pageProps: {
|
||||
__APOLLO_STATE__: {
|
||||
"Listing:1": { url: "/v-stable-one/k0l0", title: "Stable Listing One" },
|
||||
"Listing:2": { url: "/v-stable-two/k0l0", title: "Stable Listing Two" },
|
||||
"Listing:3": { url: "/v-out-of-range-high/k0l0", title: "Out Of Range High" },
|
||||
"Listing:4": { url: "/v-out-of-range-low/k0l0", title: "Out Of Range Low" },
|
||||
"Listing:1": {
|
||||
url: "/v-stable-one/k0l0",
|
||||
title: "Stable Listing One",
|
||||
},
|
||||
"Listing:2": {
|
||||
url: "/v-stable-two/k0l0",
|
||||
title: "Stable Listing Two",
|
||||
},
|
||||
"Listing:3": {
|
||||
url: "/v-out-of-range-high/k0l0",
|
||||
title: "Out Of Range High",
|
||||
},
|
||||
"Listing:4": {
|
||||
url: "/v-out-of-range-low/k0l0",
|
||||
title: "Out Of Range Low",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -672,7 +705,11 @@ describe("fetchKijijiItems", () => {
|
||||
global.fetch = mock((input: string | URL | Request) => {
|
||||
const url = typeof input === "string" ? input : input.toString();
|
||||
|
||||
if (url.includes("/k0c0l1700272") && url.includes("priceMin=80") && url.includes("priceMax=150")) {
|
||||
if (
|
||||
url.includes("/k0c0l1700272") &&
|
||||
url.includes("priceMin=80") &&
|
||||
url.includes("priceMax=150")
|
||||
) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(searchHtml),
|
||||
@@ -684,7 +721,10 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-stable-one/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Stable Listing One", 10000, "v-stable-one/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(
|
||||
listingHtml("Stable Listing One", 10000, "v-stable-one/k0l0"),
|
||||
),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -693,7 +733,10 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-stable-two/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Stable Listing Two", 11000, "v-stable-two/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(
|
||||
listingHtml("Stable Listing Two", 11000, "v-stable-two/k0l0"),
|
||||
),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -702,7 +745,14 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-out-of-range-high/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Out Of Range High", 20000, "v-out-of-range-high/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(
|
||||
listingHtml(
|
||||
"Out Of Range High",
|
||||
20000,
|
||||
"v-out-of-range-high/k0l0",
|
||||
),
|
||||
),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
@@ -711,7 +761,10 @@ describe("fetchKijijiItems", () => {
|
||||
if (url.endsWith("/v-out-of-range-low/k0l0")) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
text: () => Promise.resolve(listingHtml("Out Of Range Low", 7000, "v-out-of-range-low/k0l0")),
|
||||
text: () =>
|
||||
Promise.resolve(
|
||||
listingHtml("Out Of Range Low", 7000, "v-out-of-range-low/k0l0"),
|
||||
),
|
||||
headers: { get: () => null },
|
||||
url,
|
||||
});
|
||||
|
||||
@@ -31,8 +31,13 @@ describe("classifyUnstableListings", () => {
|
||||
|
||||
const buckets = classifyUnstableListings(listings);
|
||||
|
||||
expect(buckets.results.map((listing) => listing.id)).toEqual(["stable-1", "stable-2"]);
|
||||
expect(buckets.unstableResults.map((listing) => listing.id)).toEqual(["unstable"]);
|
||||
expect(buckets.results.map((listing) => listing.id)).toEqual([
|
||||
"stable-1",
|
||||
"stable-2",
|
||||
]);
|
||||
expect(buckets.unstableResults.map((listing) => listing.id)).toEqual([
|
||||
"unstable",
|
||||
]);
|
||||
});
|
||||
|
||||
test("uses the midpoint median for even-sized priced inputs", () => {
|
||||
@@ -45,8 +50,14 @@ describe("classifyUnstableListings", () => {
|
||||
|
||||
const buckets = classifyUnstableListings(listings);
|
||||
|
||||
expect(buckets.results.map((listing) => listing.id)).toEqual(["mid-low", "mid-high", "high"]);
|
||||
expect(buckets.unstableResults.map((listing) => listing.id)).toEqual(["low"]);
|
||||
expect(buckets.results.map((listing) => listing.id)).toEqual([
|
||||
"mid-low",
|
||||
"mid-high",
|
||||
"high",
|
||||
]);
|
||||
expect(buckets.unstableResults.map((listing) => listing.id)).toEqual([
|
||||
"low",
|
||||
]);
|
||||
});
|
||||
|
||||
test("keeps non-positive prices in results and excludes them from the median input", () => {
|
||||
@@ -66,7 +77,9 @@ describe("classifyUnstableListings", () => {
|
||||
"stable-1",
|
||||
"stable-2",
|
||||
]);
|
||||
expect(buckets.unstableResults.map((listing) => listing.id)).toEqual(["unstable"]);
|
||||
expect(buckets.unstableResults.map((listing) => listing.id)).toEqual([
|
||||
"unstable",
|
||||
]);
|
||||
});
|
||||
|
||||
test("returns all listings in results when fewer than two valid prices are present", () => {
|
||||
@@ -78,7 +91,11 @@ describe("classifyUnstableListings", () => {
|
||||
|
||||
const buckets = classifyUnstableListings(listings);
|
||||
|
||||
expect(buckets.results.map((listing) => listing.id)).toEqual(["zero", "negative", "only-valid"]);
|
||||
expect(buckets.results.map((listing) => listing.id)).toEqual([
|
||||
"zero",
|
||||
"negative",
|
||||
"only-valid",
|
||||
]);
|
||||
expect(buckets.unstableResults).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user