272 lines
9.6 KiB
JavaScript
272 lines
9.6 KiB
JavaScript
const puppeteer = require('puppeteer');
|
||
const fs = require('fs');
|
||
|
||
const testFiles = [
|
||
{ name: 'AGENTS.md', status: 'M', expectPreview: true, expectPDF: true, expectGitDiff: true },
|
||
{ name: 'FEATURE_PDF_DOWNLOAD.md', status: '??', expectPreview: true, expectPDF: true, expectGitDiff: false },
|
||
{ name: 'TOOLS.md', status: 'M', expectPreview: true, expectPDF: true, expectGitDiff: true },
|
||
{ name: 'dashboard/api.py', status: 'M', expectPreview: false, expectPDF: false, expectGitDiff: true },
|
||
{ name: 'memory/2026-02-05.md', status: '??', expectPreview: true, expectPDF: true, expectGitDiff: false }
|
||
];
|
||
|
||
(async () => {
|
||
const browser = await puppeteer.launch({
|
||
headless: true,
|
||
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
||
});
|
||
const page = await browser.newPage();
|
||
await page.setViewport({ width: 375, height: 667 });
|
||
|
||
const results = [];
|
||
const consoleErrors = [];
|
||
|
||
// Capture console errors
|
||
page.on('console', msg => {
|
||
if (msg.type() === 'error') {
|
||
consoleErrors.push(`[${msg.type()}] ${msg.text()}`);
|
||
}
|
||
});
|
||
|
||
page.on('pageerror', error => {
|
||
consoleErrors.push(`[pageerror] ${error.message}`);
|
||
});
|
||
|
||
for (const file of testFiles) {
|
||
console.log(`\n========================================`);
|
||
console.log(`Testing: ${file.name} (${file.status})`);
|
||
console.log(`========================================`);
|
||
|
||
try {
|
||
// Navigate to the file
|
||
await page.goto(`http://localhost:8000/files.html#${file.name}`, { waitUntil: 'networkidle2' });
|
||
await page.waitForTimeout(1500);
|
||
|
||
// Screenshot the header
|
||
const screenshotPath = `/home/moltbot/clawd/test-mobile-${file.name.replace(/\//g, '-')}.png`;
|
||
await page.screenshot({ path: screenshotPath, fullPage: false });
|
||
console.log(`Screenshot saved: ${screenshotPath}`);
|
||
|
||
// Check viewport
|
||
const viewport = page.viewport();
|
||
console.log(`Viewport: ${viewport.width}x${viewport.height}`);
|
||
|
||
// Check what's visible in the header before clicking menu
|
||
const headerState = await page.evaluate(() => {
|
||
const result = {
|
||
hamburgerMenu: false,
|
||
previewButton: false,
|
||
pdfButton: false,
|
||
gitDiffButton: false,
|
||
menuButtonSelector: null
|
||
};
|
||
|
||
// Check for hamburger menu (three dots)
|
||
const selectors = [
|
||
'.file-actions-menu button',
|
||
'button[aria-label*="menu"]',
|
||
'.actions-menu button',
|
||
'button.menu-trigger',
|
||
'.header button:has-text("⋮")',
|
||
'button:contains("⋮")'
|
||
];
|
||
|
||
// Try to find the menu button
|
||
for (const sel of selectors) {
|
||
try {
|
||
const el = document.querySelector(sel);
|
||
if (el && window.getComputedStyle(el).display !== 'none') {
|
||
result.hamburgerMenu = true;
|
||
result.menuButtonSelector = sel;
|
||
break;
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
|
||
// If we can't find by those selectors, look for any button with ⋮ text
|
||
if (!result.hamburgerMenu) {
|
||
const buttons = Array.from(document.querySelectorAll('button'));
|
||
const menuBtn = buttons.find(btn => btn.textContent.includes('⋮'));
|
||
if (menuBtn && window.getComputedStyle(menuBtn).display !== 'none') {
|
||
result.hamburgerMenu = true;
|
||
result.menuButtonSelector = 'button (contains ⋮)';
|
||
}
|
||
}
|
||
|
||
// Check for other buttons in header
|
||
const allButtons = Array.from(document.querySelectorAll('button'));
|
||
allButtons.forEach(btn => {
|
||
const text = btn.textContent.toLowerCase();
|
||
const style = window.getComputedStyle(btn);
|
||
if (style.display !== 'none' && style.visibility !== 'hidden') {
|
||
if (text.includes('preview')) result.previewButton = true;
|
||
if (text.includes('pdf')) result.pdfButton = true;
|
||
if (text.includes('git') || text.includes('diff')) result.gitDiffButton = true;
|
||
}
|
||
});
|
||
|
||
return result;
|
||
});
|
||
|
||
console.log('\nHeader buttons visible:');
|
||
console.log(` Hamburger Menu: ${headerState.hamburgerMenu} (selector: ${headerState.menuButtonSelector})`);
|
||
console.log(` Preview: ${headerState.previewButton}`);
|
||
console.log(` PDF: ${headerState.pdfButton}`);
|
||
console.log(` Git Diff: ${headerState.gitDiffButton}`);
|
||
|
||
// Try to click hamburger menu and check menu items
|
||
let menuClicked = false;
|
||
let menuItems = {};
|
||
|
||
if (headerState.hamburgerMenu) {
|
||
try {
|
||
// Try to find and click the menu button
|
||
const menuButtonClicked = await page.evaluate(() => {
|
||
// Look for the menu button
|
||
const buttons = Array.from(document.querySelectorAll('button'));
|
||
const menuBtn = buttons.find(btn =>
|
||
btn.textContent.includes('⋮') ||
|
||
btn.classList.contains('menu-trigger') ||
|
||
btn.getAttribute('aria-label')?.toLowerCase().includes('menu')
|
||
);
|
||
|
||
if (menuBtn) {
|
||
menuBtn.click();
|
||
return true;
|
||
}
|
||
return false;
|
||
});
|
||
|
||
if (menuButtonClicked) {
|
||
await page.waitForTimeout(500);
|
||
menuClicked = true;
|
||
|
||
// Check what's in the menu
|
||
menuItems = await page.evaluate(() => {
|
||
const items = {
|
||
preview: false,
|
||
downloadPDF: false,
|
||
gitDiff: false
|
||
};
|
||
|
||
// Look for menu items (they might be in a dropdown/popup)
|
||
const allElements = Array.from(document.querySelectorAll('*'));
|
||
|
||
allElements.forEach(el => {
|
||
const text = el.textContent?.toLowerCase() || '';
|
||
const style = window.getComputedStyle(el);
|
||
|
||
// Only count visible elements
|
||
if (style.display !== 'none' && style.visibility !== 'hidden') {
|
||
if (text === 'preview' || el.textContent?.trim() === 'Preview') items.preview = true;
|
||
if (text === 'download pdf' || el.textContent?.trim() === 'Download PDF') items.downloadPDF = true;
|
||
if (text === 'git diff' || el.textContent?.trim() === 'Git Diff') items.gitDiff = true;
|
||
}
|
||
});
|
||
|
||
return items;
|
||
});
|
||
|
||
console.log('\nMenu items visible:');
|
||
console.log(` Preview: ${menuItems.preview}`);
|
||
console.log(` Download PDF: ${menuItems.downloadPDF}`);
|
||
console.log(` Git Diff: ${menuItems.gitDiff}`);
|
||
}
|
||
} catch (error) {
|
||
console.log(`\n⚠️ Error clicking menu: ${error.message}`);
|
||
}
|
||
} else {
|
||
console.log('\n⚠️ Could not find hamburger menu');
|
||
}
|
||
|
||
// Verify expectations
|
||
const issues = [];
|
||
|
||
if (!headerState.hamburgerMenu) {
|
||
issues.push('❌ Hamburger menu NOT visible on mobile');
|
||
}
|
||
|
||
if (menuClicked) {
|
||
if (file.expectPreview && !menuItems.preview) {
|
||
issues.push('❌ Preview should be in menu but is NOT');
|
||
}
|
||
if (!file.expectPreview && menuItems.preview) {
|
||
issues.push('❌ Preview should NOT be in menu but IS');
|
||
}
|
||
if (file.expectPDF && !menuItems.downloadPDF) {
|
||
issues.push('❌ Download PDF should be in menu but is NOT');
|
||
}
|
||
if (!file.expectPDF && menuItems.downloadPDF) {
|
||
issues.push('❌ Download PDF should NOT be in menu but IS');
|
||
}
|
||
if (file.expectGitDiff && !menuItems.gitDiff) {
|
||
issues.push('❌ Git Diff should be in menu but is NOT');
|
||
}
|
||
if (!file.expectGitDiff && menuItems.gitDiff) {
|
||
issues.push('❌ Git Diff should NOT be in menu but IS');
|
||
}
|
||
} else if (headerState.hamburgerMenu) {
|
||
issues.push('⚠️ Hamburger menu found but could not click it');
|
||
}
|
||
|
||
if (issues.length > 0) {
|
||
console.log('\n🔴 ISSUES FOUND:');
|
||
issues.forEach(issue => console.log(` ${issue}`));
|
||
} else {
|
||
console.log('\n✅ All checks passed');
|
||
}
|
||
|
||
results.push({
|
||
file: file.name,
|
||
status: file.status,
|
||
hamburgerVisible: headerState.hamburgerMenu,
|
||
menuClicked,
|
||
menuItems,
|
||
expected: {
|
||
preview: file.expectPreview,
|
||
pdf: file.expectPDF,
|
||
gitDiff: file.expectGitDiff
|
||
},
|
||
issues
|
||
});
|
||
|
||
} catch (error) {
|
||
console.error(`\n❌ Error testing ${file.name}:`, error.message);
|
||
results.push({
|
||
file: file.name,
|
||
error: error.message
|
||
});
|
||
}
|
||
}
|
||
|
||
await browser.close();
|
||
|
||
// Print summary
|
||
console.log('\n\n========================================');
|
||
console.log('SUMMARY');
|
||
console.log('========================================\n');
|
||
|
||
const filesWithIssues = results.filter(r => r.issues && r.issues.length > 0);
|
||
|
||
if (filesWithIssues.length === 0) {
|
||
console.log('✅ All files passed mobile menu tests!');
|
||
} else {
|
||
console.log('🔴 Files with issues:\n');
|
||
filesWithIssues.forEach(r => {
|
||
console.log(`${r.file}:`);
|
||
r.issues.forEach(issue => console.log(` ${issue}`));
|
||
console.log('');
|
||
});
|
||
}
|
||
|
||
if (consoleErrors.length > 0) {
|
||
console.log('\n⚠️ Console Errors:');
|
||
consoleErrors.forEach(err => console.log(` ${err}`));
|
||
} else {
|
||
console.log('\n✅ No console errors detected');
|
||
}
|
||
|
||
// Write results to JSON
|
||
fs.writeFileSync('/home/moltbot/clawd/mobile-test-results.json', JSON.stringify(results, null, 2));
|
||
console.log('\n📄 Full results saved to: mobile-test-results.json');
|
||
})();
|