mirror of
https://github.com/primedigitaltech/azon_seeker.git
synced 2026-10-04 06:52:40 +08:00
* feat: add Amazon collection metadata and reliable sync * fix: route extension sync through configured server * chore: release extension v0.7.13 * fix: handle extension ports across BFCache navigation * fix: classify bottom Sponsored Brands video placements * fix: exclude hidden Amazon ad cards * fix: derive Amazon result page from URL * fix: ignore hidden Amazon sponsored products * fix: preserve base Amazon product collection * fix: bind Amazon results to visible page * fix: classify visible Amazon ad formats * fix: wait for lazy Amazon ad modules * perf: reduce Amazon lazy-load scroll stops * fix: classify Amazon sponsored brand and video search ads Co-authored-by: Cursor <cursoragent@cursor.com> * fix: collect Shop by type thematic SP ads via redirect chains without data-asin Co-authored-by: Cursor <cursoragent@cursor.com> * fix: classify sponsored ads across new Amazon templates --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: PetrichorFun <127877748+PetrichorFun@users.noreply.github.com>
77 lines
3.0 KiB
TypeScript
77 lines
3.0 KiB
TypeScript
import { JSDOM } from 'jsdom';
|
|
import { waitForAmazonSearchPageReady } from '../src/page-worker/web-injectors/amazon-search-page-ready';
|
|
|
|
const main = async () => {
|
|
const dom = new JSDOM(
|
|
'<main><div class="a-spinner">Persistent widget spinner</div><div data-component-type="s-search-result" data-asin="B000000001"></div><a class="s-pagination-next" href="/s?page=2">Next</a></main>',
|
|
{ url: 'https://www.amazon.com/s?k=security+camera' },
|
|
);
|
|
Object.defineProperty(dom.window.document, 'readyState', {
|
|
configurable: true,
|
|
value: 'complete',
|
|
});
|
|
Object.assign(globalThis, { document: dom.window.document, window: dom.window });
|
|
Object.assign(dom.window.HTMLElement.prototype, { scrollIntoView: () => undefined });
|
|
Object.assign(dom.window, { scrollTo: () => undefined });
|
|
|
|
dom.window.setTimeout(() => {
|
|
const sponsoredModule = dom.window.document.createElement('section');
|
|
sponsoredModule.innerHTML =
|
|
'<span aria-label="Sponsored">Sponsored</span><article data-asin="B000000002"><h3>Lazy sponsored product</h3><a href="/dp/B000000002"><img src="https://example.com/lazy.jpg"></a></article>';
|
|
dom.window.document.querySelector('main')?.append(sponsoredModule);
|
|
}, 500);
|
|
|
|
const started = Date.now();
|
|
await waitForAmazonSearchPageReady();
|
|
const elapsed = Date.now() - started;
|
|
|
|
if (!dom.window.document.querySelector('[data-asin="B000000002"]')) {
|
|
throw new Error('Lazy sponsored DOM was not loaded before page readiness completed');
|
|
}
|
|
if (elapsed >= 5000) {
|
|
throw new Error(`Ready search results were delayed by a persistent spinner (${elapsed}ms)`);
|
|
}
|
|
dom.window.close();
|
|
|
|
const errorDom = new JSDOM(
|
|
'<main><h1>SORRY</h1><p>Something went wrong on our end.</p><p>Please go back and try again.</p></main>',
|
|
{ url: 'https://www.amazon.com/s?k=protein+powder' },
|
|
);
|
|
Object.defineProperty(errorDom.window.document, 'readyState', {
|
|
configurable: true,
|
|
value: 'complete',
|
|
});
|
|
Object.assign(globalThis, { document: errorDom.window.document, window: errorDom.window });
|
|
await waitForAmazonSearchPageReady().then(
|
|
() => {
|
|
throw new Error('Amazon transient error page must not be accepted as an empty result page');
|
|
},
|
|
(error) => {
|
|
if (!String(error).includes('临时错误页')) throw error;
|
|
},
|
|
);
|
|
errorDom.window.close();
|
|
|
|
const captchaDom = new JSDOM('<input id="captchacharacters">', {
|
|
url: 'https://www.amazon.com/s?k=protein+powder',
|
|
});
|
|
Object.defineProperty(captchaDom.window.document, 'readyState', {
|
|
configurable: true,
|
|
value: 'complete',
|
|
});
|
|
Object.assign(globalThis, { document: captchaDom.window.document, window: captchaDom.window });
|
|
await waitForAmazonSearchPageReady().then(
|
|
() => {
|
|
throw new Error('Amazon captcha page must fail immediately');
|
|
},
|
|
(error) => {
|
|
if (!String(error).includes('验证码')) throw error;
|
|
},
|
|
);
|
|
captchaDom.window.close();
|
|
|
|
console.log('Amazon search page-ready tests passed.');
|
|
};
|
|
|
|
void main();
|