chore: bump task worker version comment
Force new git SHA to avoid CI scientific notation bug. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
211
backend/scripts/test-treez-load-all.ts
Normal file
211
backend/scripts/test-treez-load-all.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Find and interact with "load more brands" selector
|
||||
*/
|
||||
|
||||
import puppeteer, { Page } from 'puppeteer';
|
||||
|
||||
const STORE_ID = 'best';
|
||||
|
||||
async function sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function bypassAgeGate(page: Page): Promise<void> {
|
||||
const ageGate = await page.$('[data-testid="age-gate-modal"]');
|
||||
if (ageGate) {
|
||||
console.log(' Age gate detected, bypassing...');
|
||||
const btn = await page.$('[data-testid="age-gate-submit-button"]');
|
||||
if (btn) await btn.click();
|
||||
await sleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('='.repeat(60));
|
||||
console.log('Finding "Load More Brands" control');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
const browser = await puppeteer.launch({
|
||||
headless: true,
|
||||
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: 1920, height: 1080 });
|
||||
|
||||
// Don't block stylesheets - might affect layout
|
||||
await page.setRequestInterception(true);
|
||||
page.on('request', (req) => {
|
||||
if (['image', 'font', 'media'].includes(req.resourceType())) {
|
||||
req.abort();
|
||||
} else {
|
||||
req.continue();
|
||||
}
|
||||
});
|
||||
|
||||
const url = `https://${STORE_ID}.treez.io/onlinemenu/brands?customerType=ADULT`;
|
||||
console.log(`\nNavigating to ${url}`);
|
||||
|
||||
await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 });
|
||||
await sleep(3000);
|
||||
await bypassAgeGate(page);
|
||||
await sleep(2000);
|
||||
|
||||
// Find all selects and dropdowns
|
||||
console.log('\n[1] Looking for select elements...');
|
||||
|
||||
const selectInfo = await page.evaluate(() => {
|
||||
const results: any[] = [];
|
||||
|
||||
// Native select elements
|
||||
document.querySelectorAll('select').forEach((sel, i) => {
|
||||
const options = Array.from(sel.options).map(o => ({ value: o.value, text: o.text }));
|
||||
results.push({
|
||||
type: 'select',
|
||||
id: sel.id || `select-${i}`,
|
||||
class: sel.className,
|
||||
options: options.slice(0, 10),
|
||||
totalOptions: sel.options.length,
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
});
|
||||
|
||||
console.log('Native selects found:', JSON.stringify(selectInfo, null, 2));
|
||||
|
||||
// Look for custom dropdown buttons
|
||||
console.log('\n[2] Looking for dropdown/button elements...');
|
||||
|
||||
const dropdownInfo = await page.evaluate(() => {
|
||||
const results: any[] = [];
|
||||
|
||||
// Look for common dropdown patterns
|
||||
const selectors = [
|
||||
'[class*="dropdown"]',
|
||||
'[class*="Dropdown"]',
|
||||
'[class*="select"]',
|
||||
'[class*="Select"]',
|
||||
'[class*="picker"]',
|
||||
'[class*="Picker"]',
|
||||
'[role="listbox"]',
|
||||
'[role="combobox"]',
|
||||
'button[aria-haspopup]',
|
||||
'[class*="brand"] button',
|
||||
'[class*="Brand"] button',
|
||||
'[class*="filter"]',
|
||||
'[class*="Filter"]',
|
||||
];
|
||||
|
||||
selectors.forEach(sel => {
|
||||
document.querySelectorAll(sel).forEach((el, i) => {
|
||||
const text = el.textContent?.trim().slice(0, 100) || '';
|
||||
const className = el.className?.toString?.().slice(0, 100) || '';
|
||||
if (text.toLowerCase().includes('brand') || text.toLowerCase().includes('more') || text.toLowerCase().includes('all')) {
|
||||
results.push({
|
||||
selector: sel,
|
||||
tag: el.tagName,
|
||||
class: className,
|
||||
text: text.slice(0, 50),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
});
|
||||
|
||||
console.log('Dropdown-like elements:', JSON.stringify(dropdownInfo.slice(0, 10), null, 2));
|
||||
|
||||
// Look for any element containing "brand" text
|
||||
console.log('\n[3] Looking for elements with "brand" or "more" text...');
|
||||
|
||||
const brandTextElements = await page.evaluate(() => {
|
||||
const results: any[] = [];
|
||||
const textContent = ['brand', 'more', 'load', 'view all', 'show all'];
|
||||
|
||||
document.querySelectorAll('button, a, [role="button"], select, [class*="select"]').forEach(el => {
|
||||
const text = el.textContent?.toLowerCase() || '';
|
||||
if (textContent.some(t => text.includes(t))) {
|
||||
results.push({
|
||||
tag: el.tagName,
|
||||
class: el.className?.toString?.().slice(0, 80) || '',
|
||||
text: el.textContent?.trim().slice(0, 100) || '',
|
||||
href: el.getAttribute('href') || '',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
});
|
||||
|
||||
console.log('Elements with brand/more text:', JSON.stringify(brandTextElements.slice(0, 15), null, 2));
|
||||
|
||||
// Count current brand sections
|
||||
console.log('\n[4] Counting brand sections...');
|
||||
|
||||
const brandSections = await page.evaluate(() => {
|
||||
// Look for brand section headers or containers
|
||||
const sections: { title: string; productCount: number }[] = [];
|
||||
|
||||
document.querySelectorAll('[class*="products_product__section"]').forEach(section => {
|
||||
const header = section.querySelector('h2, h3, [class*="heading"]');
|
||||
const title = header?.textContent?.trim() || 'Unknown';
|
||||
const products = section.querySelectorAll('a[class*="product_product__"]');
|
||||
sections.push({ title, productCount: products.length });
|
||||
});
|
||||
|
||||
return sections;
|
||||
});
|
||||
|
||||
console.log(`Found ${brandSections.length} brand sections:`);
|
||||
brandSections.slice(0, 20).forEach(s => console.log(` - ${s.title}: ${s.productCount} products`));
|
||||
|
||||
// Take a screenshot
|
||||
await page.screenshot({ path: '/tmp/treez-brands-full.png', fullPage: true });
|
||||
console.log('\n[5] Full page screenshot saved to /tmp/treez-brands-full.png');
|
||||
|
||||
// Try scrolling to bottom to trigger any lazy loading
|
||||
console.log('\n[6] Scrolling to load more content...');
|
||||
|
||||
let previousHeight = 0;
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
await sleep(1500);
|
||||
|
||||
const currentHeight = await page.evaluate(() => document.body.scrollHeight);
|
||||
const sectionCount = await page.evaluate(() =>
|
||||
document.querySelectorAll('[class*="products_product__section"]').length
|
||||
);
|
||||
|
||||
console.log(` Scroll ${i + 1}: height=${currentHeight}, sections=${sectionCount}`);
|
||||
|
||||
if (currentHeight === previousHeight) {
|
||||
console.log(' No new content, stopping');
|
||||
break;
|
||||
}
|
||||
previousHeight = currentHeight;
|
||||
}
|
||||
|
||||
// Final count
|
||||
const finalSections = await page.evaluate(() => {
|
||||
const sections: { title: string; productCount: number }[] = [];
|
||||
document.querySelectorAll('[class*="products_product__section"]').forEach(section => {
|
||||
const header = section.querySelector('h2, h3, [class*="heading"]');
|
||||
const title = header?.textContent?.trim() || 'Unknown';
|
||||
const products = section.querySelectorAll('a[class*="product_product__"]');
|
||||
sections.push({ title, productCount: products.length });
|
||||
});
|
||||
return sections;
|
||||
});
|
||||
|
||||
console.log(`\n[7] After scrolling: ${finalSections.length} brand sections`);
|
||||
finalSections.forEach(s => console.log(` - ${s.title}: ${s.productCount} products`));
|
||||
|
||||
const totalProducts = finalSections.reduce((sum, s) => sum + s.productCount, 0);
|
||||
console.log(`\nTotal products across all sections: ${totalProducts}`);
|
||||
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
Reference in New Issue
Block a user