- Add WorkerFingerprint interface with timezone, city, state, ip, locale - Store fingerprint in TaskWorker after preflight passes - Pass fingerprint through TaskContext to handlers - Apply timezone via CDP and locale via Accept-Language header - Ensures browser fingerprint matches proxy IP location This fixes anti-detect detection where timezone/locale mismatch with proxy IP was getting blocked by Cloudflare. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
127 lines
4.3 KiB
TypeScript
127 lines
4.3 KiB
TypeScript
/**
|
|
* Test script for Jane platform client
|
|
* Tests the new Jane integration with The Flower Shop Mesa
|
|
*
|
|
* Usage: npx ts-node scripts/test-jane-client.ts
|
|
*/
|
|
|
|
import {
|
|
startSession,
|
|
endSession,
|
|
fetchProductsFromUrl,
|
|
resolveStoreFromUrl,
|
|
} from '../src/platforms/jane';
|
|
import { JaneNormalizer } from '../src/hydration/normalizers/jane';
|
|
|
|
const TEST_URL = 'https://theflowershopusa.com/mesa/menu/';
|
|
|
|
async function main() {
|
|
console.log('='.repeat(60));
|
|
console.log('Jane Platform Client Test');
|
|
console.log('='.repeat(60));
|
|
console.log(`Test URL: ${TEST_URL}`);
|
|
console.log('');
|
|
|
|
try {
|
|
// Test 1: Fetch products from URL
|
|
console.log('[Test 1] Fetching products from menu URL...');
|
|
const result = await fetchProductsFromUrl(TEST_URL);
|
|
|
|
console.log('');
|
|
console.log('[Results]');
|
|
console.log(` Store: ${result.store?.name || 'Not captured'}`);
|
|
console.log(` Store ID: ${result.store?.id || 'N/A'}`);
|
|
console.log(` Products captured: ${result.products.length}`);
|
|
console.log(` API responses: ${result.responses.length}`);
|
|
|
|
if (result.store) {
|
|
console.log('');
|
|
console.log('[Store Info]');
|
|
console.log(` Address: ${result.store.address}, ${result.store.city}, ${result.store.state} ${result.store.zip}`);
|
|
console.log(` Phone: ${result.store.phone}`);
|
|
console.log(` Coordinates: ${result.store.lat}, ${result.store.long}`);
|
|
console.log(` Medical: ${result.store.medical}, Recreational: ${result.store.recreational}`);
|
|
console.log(` Rating: ${result.store.rating} (${result.store.reviews_count} reviews)`);
|
|
console.log(` Product count (store): ${result.store.product_count}`);
|
|
}
|
|
|
|
if (result.products.length > 0) {
|
|
console.log('');
|
|
console.log('[Sample Products (first 5)]');
|
|
for (const p of result.products.slice(0, 5)) {
|
|
const price = p.price_gram || p.price_each || 'N/A';
|
|
console.log(` - ${p.name} (${p.brand}) - $${price}`);
|
|
console.log(` Kind: ${p.kind}, Category: ${p.category}, THC: ${p.percent_thc}%`);
|
|
}
|
|
|
|
// Test 2: Normalize products
|
|
console.log('');
|
|
console.log('[Test 2] Testing normalizer...');
|
|
const normalizer = new JaneNormalizer();
|
|
|
|
// Build a fake payload structure
|
|
const fakePayload = {
|
|
id: 'test-payload',
|
|
dispensary_id: 9999,
|
|
crawl_run_id: null,
|
|
platform: 'jane',
|
|
payload_version: 1,
|
|
raw_json: { hits: result.products.map(p => p.raw) },
|
|
product_count: result.products.length,
|
|
pricing_type: null,
|
|
crawl_mode: null,
|
|
fetched_at: new Date(),
|
|
processed: false,
|
|
normalized_at: null,
|
|
hydration_error: null,
|
|
hydration_attempts: 0,
|
|
created_at: new Date(),
|
|
};
|
|
|
|
const normalized = normalizer.normalize(fakePayload);
|
|
|
|
console.log(` Products normalized: ${normalized.products.length}`);
|
|
console.log(` Brands extracted: ${normalized.brands.length}`);
|
|
console.log(` Categories extracted: ${normalized.categories.length}`);
|
|
console.log(` Errors: ${normalized.errors.length}`);
|
|
|
|
if (normalized.products.length > 0) {
|
|
console.log('');
|
|
console.log('[Sample Normalized Product]');
|
|
const np = normalized.products[0];
|
|
console.log(` External ID: ${np.externalProductId}`);
|
|
console.log(` Name: ${np.name}`);
|
|
console.log(` Brand: ${np.brandName}`);
|
|
console.log(` Category: ${np.category}`);
|
|
console.log(` Type: ${np.type}`);
|
|
console.log(` Strain: ${np.strainType}`);
|
|
console.log(` THC: ${np.thcPercent}%`);
|
|
console.log(` CBD: ${np.cbdPercent}%`);
|
|
console.log(` Image: ${np.primaryImageUrl?.slice(0, 60)}...`);
|
|
|
|
const pricing = normalized.pricing.get(np.externalProductId);
|
|
if (pricing) {
|
|
console.log(` Price (cents): ${pricing.priceRec}`);
|
|
console.log(` On Special: ${pricing.isOnSpecial}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('');
|
|
console.log('='.repeat(60));
|
|
console.log('TEST PASSED');
|
|
console.log('='.repeat(60));
|
|
|
|
} catch (error: any) {
|
|
console.error('');
|
|
console.error('='.repeat(60));
|
|
console.error('TEST FAILED');
|
|
console.error('='.repeat(60));
|
|
console.error(`Error: ${error.message}`);
|
|
console.error(error.stack);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
main().catch(console.error);
|