mirror of
https://github.com/primedigitaltech/azon_seeker.git
synced 2026-10-05 07:13:06 +08:00
226 lines
9.5 KiB
TypeScript
226 lines
9.5 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { JSDOM } from 'jsdom';
|
|
import { collectAmazonSearchPageData } from '../src/page-worker/web-injectors/amazon-search-parser';
|
|
|
|
const html = `
|
|
<main id="search">
|
|
<section data-component-type="sponsored-brand">
|
|
<span aria-label="Sponsored">Sponsored</span>
|
|
<a href="/stores/example"><span class="brand-logo">Example brand</span></a>
|
|
<h2>Example brand headline</h2>
|
|
<article data-asin="B000000001">
|
|
<h3>Brand product one</h3>
|
|
<a href="/dp/B000000001"><img src="https://example.com/brand-1.jpg" /></a>
|
|
</article>
|
|
<article data-asin="B000000002">
|
|
<h3>Brand product two</h3>
|
|
<a href="/dp/B000000002"><img src="https://example.com/brand-2.jpg" /></a>
|
|
</article>
|
|
</section>
|
|
|
|
<div class="s-main-slot">
|
|
<div class="ordinary-result-grid">
|
|
<article data-component-type="s-search-result" data-asin="B000000003">
|
|
<span>Amazon's Choice</span>
|
|
<h2>Organic product</h2>
|
|
<a href="/dp/B000000003"><img class="s-image" src="https://example.com/organic.jpg" /></a>
|
|
<span class="a-price"><span class="a-offscreen">$29.99</span></span>
|
|
</article>
|
|
|
|
<article data-component-type="s-search-result" data-asin="B000000004">
|
|
<a aria-label="View Sponsored information or leave ad feedback"></a>
|
|
<h2>Sponsored product</h2>
|
|
<a href="/sspa/click?url=%2Fdp%2FB000000004"><img class="s-image" src="https://example.com/sp.jpg" /></a>
|
|
<span class="a-price"><span class="a-offscreen">$33.93</span></span>
|
|
<span class="a-price a-text-price" data-a-strike="true"><span class="a-offscreen">$39.99</span></span>
|
|
<span class="a-price a-text-price apex-priceperunit-value"><span class="a-offscreen">$0.28</span></span>
|
|
</article>
|
|
|
|
<article data-component-type="s-search-result" data-asin="B000000007">
|
|
<h2>Second organic product</h2>
|
|
<a href="/dp/B000000007"><img class="s-image" src="https://example.com/organic-2.jpg" /></a>
|
|
</article>
|
|
</div>
|
|
|
|
<section class="custom-sponsored-module">
|
|
<span>Sponsored</span>
|
|
<article data-asin="B000000005">
|
|
<h3>Unknown sponsored product</h3>
|
|
<a href="/dp/B000000005"><img src="https://example.com/unknown.jpg" /></a>
|
|
</article>
|
|
</section>
|
|
|
|
<section class="bottom-sponsored-video-module">
|
|
<video></video>
|
|
<span>Sponsored</span>
|
|
<a href="/stores/video-brand"><span class="brand-logo">Video brand</span></a>
|
|
<h2>Video brand headline</h2>
|
|
<div class="puis-card-container">
|
|
<div class="puisg-row">
|
|
<article data-asin="B000000008">
|
|
<h3>Sponsored Brands video product</h3>
|
|
<a href="/dp/B000000008"><img src="https://example.com/brand-video.jpg" /></a>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section style="display: none">
|
|
<span>Sponsored</span>
|
|
<article data-asin="B000000009">
|
|
<h3 aria-label="Sponsored Ad - hidden preloaded product">Hidden preloaded product</h3>
|
|
<a href="/sspa/click?url=%2Fdp%2FB000000009">
|
|
<img src="https://example.com/hidden.jpg" />
|
|
</a>
|
|
</article>
|
|
</section>
|
|
|
|
<section aria-hidden="true">
|
|
<span>Sponsored</span>
|
|
<article data-asin="B000000010">
|
|
<h3>Hidden accessibility product</h3>
|
|
<a href="/dp/B000000010"><img src="https://example.com/hidden-aria.jpg" /></a>
|
|
</article>
|
|
</section>
|
|
</div>
|
|
|
|
<aside id="rightResultsATF" data-component-type="sponsored-display">
|
|
<span>Sponsored</span>
|
|
<article data-asin="B000000006">
|
|
<h3>Display product</h3>
|
|
<a href="/dp/B000000006"><img src="https://example.com/display.jpg" /></a>
|
|
</article>
|
|
</aside>
|
|
</main>
|
|
`;
|
|
|
|
const dom = new JSDOM(html, { url: 'https://www.amazon.com/s?k=mirror' });
|
|
Object.assign(globalThis, {
|
|
document: dom.window.document,
|
|
Node: dom.window.Node,
|
|
Element: dom.window.Element,
|
|
HTMLElement: dom.window.HTMLElement,
|
|
HTMLAnchorElement: dom.window.HTMLAnchorElement,
|
|
HTMLImageElement: dom.window.HTMLImageElement,
|
|
});
|
|
|
|
async function main() {
|
|
const items = await collectAmazonSearchPageData({ pattern: 'pattern-2' });
|
|
assert.equal(items.length, 8);
|
|
|
|
const byAsin = new Map(items.map((item) => [item.asin, item]));
|
|
assert.equal(byAsin.get('B000000003')?.adType, 'organic');
|
|
assert.equal(byAsin.get('B000000004')?.adType, 'sponsoredProducts');
|
|
assert.equal(byAsin.get('B000000004')?.price, '$33.93');
|
|
assert.equal(byAsin.get('B000000004')?.strikethroughPrice, '$39.99');
|
|
assert.equal(byAsin.get('B000000004')?.link, 'https://www.amazon.com/dp/B000000004');
|
|
assert.equal(byAsin.get('B000000004')?.placement, 'middleOfSearch');
|
|
assert.equal(byAsin.get('B000000001')?.adType, 'sponsoredBrands');
|
|
assert.equal(byAsin.get('B000000002')?.adType, 'sponsoredBrands');
|
|
assert.equal(byAsin.get('B000000001')?.placement, 'topOfSearch');
|
|
assert.equal(byAsin.get('B000000001')?.placementId, byAsin.get('B000000002')?.placementId);
|
|
assert.equal(byAsin.get('B000000001')?.adProductIndex, 1);
|
|
assert.equal(byAsin.get('B000000002')?.adProductIndex, 2);
|
|
assert.equal(byAsin.get('B000000005')?.adType, 'sponsoredProducts');
|
|
assert.equal(byAsin.get('B000000005')?.placement, 'bottomOfSearch');
|
|
assert.equal(byAsin.get('B000000006')?.adType, 'sponsoredDisplay');
|
|
assert.equal(byAsin.get('B000000006')?.placement, 'sidebar');
|
|
assert.equal(byAsin.get('B000000008')?.adType, 'sponsoredBrands');
|
|
assert.equal(byAsin.get('B000000008')?.adFormat, 'video');
|
|
assert.equal(byAsin.get('B000000008')?.placement, 'bottomOfSearch');
|
|
assert.equal(items.filter((item) => item.asin === 'B000000008').length, 1);
|
|
assert.equal(byAsin.has('B000000009'), false);
|
|
assert.equal(byAsin.has('B000000010'), false);
|
|
assert.deepEqual(
|
|
items.map((item) => item.pageRank),
|
|
[1, 2, 3, 4, 5, 6, 7, 8],
|
|
);
|
|
|
|
const hiddenDisclosureDom = new JSDOM(
|
|
`
|
|
<main id="search">
|
|
<div class="s-main-slot">
|
|
<article data-component-type="s-search-result" data-asin="B000000011">
|
|
<h2>Visible organic product</h2>
|
|
<span
|
|
aria-label="Sponsored Ad - hidden disclosure"
|
|
style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0)"
|
|
>Sponsored</span>
|
|
<a href="/sspa/click?url=%2Fdp%2FB000000011">
|
|
<img class="s-image" src="https://example.com/visible-product.jpg" />
|
|
</a>
|
|
</article>
|
|
</div>
|
|
</main>
|
|
`,
|
|
{ url: 'https://www.amazon.com/s?k=mirror' },
|
|
);
|
|
Object.assign(globalThis, {
|
|
document: hiddenDisclosureDom.window.document,
|
|
Node: hiddenDisclosureDom.window.Node,
|
|
Element: hiddenDisclosureDom.window.Element,
|
|
HTMLElement: hiddenDisclosureDom.window.HTMLElement,
|
|
HTMLAnchorElement: hiddenDisclosureDom.window.HTMLAnchorElement,
|
|
HTMLImageElement: hiddenDisclosureDom.window.HTMLImageElement,
|
|
});
|
|
const hiddenDisclosureItems = await collectAmazonSearchPageData({ pattern: 'pattern-2' });
|
|
assert.equal(hiddenDisclosureItems.length, 1);
|
|
assert.equal(hiddenDisclosureItems[0].adType, 'organic');
|
|
|
|
const groupedAdsDom = new JSDOM(
|
|
`
|
|
<main id="search">
|
|
<div class="s-main-slot">
|
|
<section class="shared-sponsored-products">
|
|
<span aria-label="Sponsored">Sponsored</span>
|
|
<a href="/stores/reolink" style="display: none">Hidden brand destination</a>
|
|
<article data-asin="B000000012">
|
|
<h3>Grouped sponsored product one</h3>
|
|
<a href="/dp/B000000012"><img src="https://example.com/grouped-1.jpg" /></a>
|
|
</article>
|
|
<article data-asin="B000000013">
|
|
<h3>Grouped sponsored product two</h3>
|
|
<a href="/dp/B000000013"><img src="https://example.com/grouped-2.jpg" /></a>
|
|
</article>
|
|
</section>
|
|
</div>
|
|
<aside class="left-sponsored-display" data-component-type="sponsored-display">
|
|
<span aria-label="Sponsored">Sponsored</span>
|
|
<article>
|
|
<h3>Left rail display product</h3>
|
|
<a href="/dp/B000000014"><img src="https://example.com/display-left.jpg" /></a>
|
|
</article>
|
|
</aside>
|
|
</main>
|
|
`,
|
|
{ url: 'https://www.amazon.com/s?k=mirror&page=8' },
|
|
);
|
|
Object.assign(globalThis, {
|
|
document: groupedAdsDom.window.document,
|
|
Node: groupedAdsDom.window.Node,
|
|
Element: groupedAdsDom.window.Element,
|
|
HTMLElement: groupedAdsDom.window.HTMLElement,
|
|
HTMLAnchorElement: groupedAdsDom.window.HTMLAnchorElement,
|
|
HTMLImageElement: groupedAdsDom.window.HTMLImageElement,
|
|
});
|
|
const groupedAds = await collectAmazonSearchPageData({ pattern: 'pattern-2' });
|
|
const groupedAdsByAsin = new Map(groupedAds.map((item) => [item.asin, item]));
|
|
assert.equal(groupedAdsByAsin.get('B000000012')?.adType, 'sponsoredProducts');
|
|
assert.equal(groupedAdsByAsin.get('B000000013')?.adType, 'sponsoredProducts');
|
|
assert.equal(
|
|
groupedAdsByAsin.get('B000000012')?.placementId,
|
|
groupedAdsByAsin.get('B000000013')?.placementId,
|
|
);
|
|
assert.equal(groupedAdsByAsin.get('B000000012')?.adProductIndex, 1);
|
|
assert.equal(groupedAdsByAsin.get('B000000013')?.adProductIndex, 2);
|
|
assert.equal(groupedAdsByAsin.get('B000000014')?.adType, 'sponsoredDisplay');
|
|
assert.equal(groupedAdsByAsin.get('B000000014')?.placement, 'sidebar');
|
|
|
|
console.log('Amazon search parser fixtures passed.');
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error(error);
|
|
process.exitCode = 1;
|
|
});
|