- Store product images locally with hierarchy: /images/products/<state>/<store>/<brand>/<product>/ - Add /img/* proxy endpoint for on-demand resizing via Sharp - Implement per-product image checking to skip existing downloads - Fix pathToUrl() to correctly generate /images/... URLs - Add frontend getImageUrl() helper with preset sizes (thumb, medium, large) - Update all product pages to use optimized image URLs - Add stealth session support for Dutchie GraphQL crawls - Include test scripts for crawl and image verification 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
118 lines
3.9 KiB
TypeScript
118 lines
3.9 KiB
TypeScript
/**
|
|
* Test script for stealth session management
|
|
*
|
|
* Tests:
|
|
* 1. Per-session fingerprint rotation
|
|
* 2. Geographic consistency (timezone → Accept-Language)
|
|
* 3. Proxy location loading from database
|
|
*
|
|
* Usage:
|
|
* npx tsx src/scripts/test-stealth-session.ts
|
|
*/
|
|
|
|
import {
|
|
startSession,
|
|
endSession,
|
|
getCurrentSession,
|
|
getFingerprint,
|
|
getRandomFingerprint,
|
|
getLocaleForTimezone,
|
|
buildHeaders,
|
|
} from '../platforms/dutchie';
|
|
|
|
console.log('='.repeat(60));
|
|
console.log('STEALTH SESSION TEST');
|
|
console.log('='.repeat(60));
|
|
|
|
// Test 1: Timezone to Locale mapping
|
|
console.log('\n[Test 1] Timezone to Locale Mapping:');
|
|
const testTimezones = [
|
|
'America/Phoenix',
|
|
'America/Los_Angeles',
|
|
'America/New_York',
|
|
'America/Chicago',
|
|
undefined,
|
|
'Invalid/Timezone',
|
|
];
|
|
|
|
for (const tz of testTimezones) {
|
|
const locale = getLocaleForTimezone(tz);
|
|
console.log(` ${tz || '(undefined)'} → ${locale}`);
|
|
}
|
|
|
|
// Test 2: Random fingerprint selection
|
|
console.log('\n[Test 2] Random Fingerprint Selection (5 samples):');
|
|
for (let i = 0; i < 5; i++) {
|
|
const fp = getRandomFingerprint();
|
|
console.log(` ${i + 1}. ${fp.userAgent.slice(0, 60)}...`);
|
|
}
|
|
|
|
// Test 3: Session Management
|
|
console.log('\n[Test 3] Session Management:');
|
|
|
|
// Before session - should use default fingerprint
|
|
console.log(' Before session:');
|
|
const beforeFp = getFingerprint();
|
|
console.log(` getFingerprint(): ${beforeFp.userAgent.slice(0, 50)}...`);
|
|
console.log(` getCurrentSession(): ${getCurrentSession()}`);
|
|
|
|
// Start session with Arizona timezone
|
|
console.log('\n Starting session (AZ, America/Phoenix):');
|
|
const session1 = startSession('AZ', 'America/Phoenix');
|
|
console.log(` Session ID: ${session1.sessionId}`);
|
|
console.log(` Fingerprint UA: ${session1.fingerprint.userAgent.slice(0, 50)}...`);
|
|
console.log(` Accept-Language: ${session1.fingerprint.acceptLanguage}`);
|
|
console.log(` Timezone: ${session1.timezone}`);
|
|
|
|
// During session - should use session fingerprint
|
|
console.log('\n During session:');
|
|
const duringFp = getFingerprint();
|
|
console.log(` getFingerprint(): ${duringFp.userAgent.slice(0, 50)}...`);
|
|
console.log(` Same as session? ${duringFp.userAgent === session1.fingerprint.userAgent}`);
|
|
|
|
// Test buildHeaders with session
|
|
console.log('\n buildHeaders() during session:');
|
|
const headers = buildHeaders('/embedded-menu/test-store');
|
|
console.log(` User-Agent: ${headers['user-agent'].slice(0, 50)}...`);
|
|
console.log(` Accept-Language: ${headers['accept-language']}`);
|
|
console.log(` Origin: ${headers['origin']}`);
|
|
console.log(` Referer: ${headers['referer']}`);
|
|
|
|
// End session
|
|
console.log('\n Ending session:');
|
|
endSession();
|
|
console.log(` getCurrentSession(): ${getCurrentSession()}`);
|
|
|
|
// Test 4: Multiple sessions should have different fingerprints
|
|
console.log('\n[Test 4] Multiple Sessions (fingerprint variety):');
|
|
const fingerprints: string[] = [];
|
|
for (let i = 0; i < 10; i++) {
|
|
const session = startSession('CA', 'America/Los_Angeles');
|
|
fingerprints.push(session.fingerprint.userAgent);
|
|
endSession();
|
|
}
|
|
|
|
const uniqueCount = new Set(fingerprints).size;
|
|
console.log(` 10 sessions created, ${uniqueCount} unique fingerprints`);
|
|
console.log(` Variety: ${uniqueCount >= 3 ? '✅ Good' : '⚠️ Low - may need more fingerprint options'}`);
|
|
|
|
// Test 5: Geographic consistency check
|
|
console.log('\n[Test 5] Geographic Consistency:');
|
|
const geoTests = [
|
|
{ state: 'AZ', tz: 'America/Phoenix' },
|
|
{ state: 'CA', tz: 'America/Los_Angeles' },
|
|
{ state: 'NY', tz: 'America/New_York' },
|
|
{ state: 'IL', tz: 'America/Chicago' },
|
|
];
|
|
|
|
for (const { state, tz } of geoTests) {
|
|
const session = startSession(state, tz);
|
|
const consistent = session.fingerprint.acceptLanguage.includes('en-US');
|
|
console.log(` ${state} (${tz}): Accept-Language=${session.fingerprint.acceptLanguage} ${consistent ? '✅' : '❌'}`);
|
|
endSession();
|
|
}
|
|
|
|
console.log('\n' + '='.repeat(60));
|
|
console.log('TEST COMPLETE');
|
|
console.log('='.repeat(60));
|