Some checks failed
Deploy / deploy (push) Has been cancelled
Full-stack web application for Telegram management - Frontend: Vue 3 + Vben Admin - Backend: NestJS - Features: User management, group broadcast, statistics 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
193 lines
5.7 KiB
JavaScript
193 lines
5.7 KiB
JavaScript
const { chromium } = require('playwright');
|
|
|
|
(async () => {
|
|
let browser;
|
|
|
|
try {
|
|
console.log('启动浏览器捕获控制台错误...');
|
|
browser = await chromium.launch({
|
|
headless: false,
|
|
slowMo: 100,
|
|
devtools: true // 自动打开开发者工具
|
|
});
|
|
|
|
const context = await browser.newContext({
|
|
viewport: { width: 1920, height: 1080 }
|
|
});
|
|
|
|
const page = await context.newPage();
|
|
|
|
// 捕获控制台消息
|
|
const errors = [];
|
|
const warnings = [];
|
|
|
|
page.on('console', async msg => {
|
|
const type = msg.type();
|
|
const text = msg.text();
|
|
const location = msg.location();
|
|
|
|
if (type === 'error') {
|
|
const errorInfo = {
|
|
text,
|
|
location: `${location.url}:${location.lineNumber}:${location.columnNumber}`,
|
|
args: []
|
|
};
|
|
|
|
// 尝试获取更详细的错误信息
|
|
try {
|
|
for (const arg of msg.args()) {
|
|
const value = await arg.jsonValue().catch(() => null);
|
|
if (value) {
|
|
errorInfo.args.push(value);
|
|
}
|
|
}
|
|
} catch (e) {}
|
|
|
|
errors.push(errorInfo);
|
|
console.log('\n[ERROR]', text);
|
|
console.log('位置:', errorInfo.location);
|
|
if (errorInfo.args.length > 0) {
|
|
console.log('详情:', JSON.stringify(errorInfo.args, null, 2));
|
|
}
|
|
} else if (type === 'warning') {
|
|
warnings.push(text);
|
|
console.log('\n[WARNING]', text);
|
|
}
|
|
});
|
|
|
|
// 捕获页面错误
|
|
page.on('pageerror', error => {
|
|
console.log('\n[PAGE ERROR]', error.message);
|
|
console.log('Stack:', error.stack);
|
|
errors.push({
|
|
text: error.message,
|
|
stack: error.stack
|
|
});
|
|
});
|
|
|
|
// 监听网络错误
|
|
page.on('requestfailed', request => {
|
|
console.log('\n[NETWORK ERROR]', request.failure().errorText);
|
|
console.log('URL:', request.url());
|
|
});
|
|
|
|
console.log('\n访问登录页面...');
|
|
await page.goto('http://localhost:5173/', { waitUntil: 'networkidle' });
|
|
|
|
// 等待一下让错误都加载出来
|
|
await page.waitForTimeout(2000);
|
|
|
|
console.log('\n执行登录...');
|
|
await page.fill('[name="username"]', 'admin');
|
|
await page.fill('[name="password"]', '111111');
|
|
await page.click('button:has-text("登录")');
|
|
|
|
await page.waitForTimeout(3000);
|
|
|
|
// 检查Vue应用状态
|
|
console.log('\n检查Vue应用状态...');
|
|
const vueStatus = await page.evaluate(() => {
|
|
const app = window.__VUE_APP__ || window.app || document.querySelector('#app')?.__vue_app__;
|
|
if (!app) {
|
|
return { hasApp: false };
|
|
}
|
|
|
|
const stores = app._context.provides.pinia?._s;
|
|
if (!stores) {
|
|
return { hasApp: true, hasStores: false };
|
|
}
|
|
|
|
let accessStore = null;
|
|
stores.forEach(store => {
|
|
if (store.accessMenus !== undefined) {
|
|
accessStore = store;
|
|
}
|
|
});
|
|
|
|
if (!accessStore) {
|
|
return { hasApp: true, hasStores: true, hasAccessStore: false };
|
|
}
|
|
|
|
return {
|
|
hasApp: true,
|
|
hasStores: true,
|
|
hasAccessStore: true,
|
|
accessMenus: accessStore.accessMenus,
|
|
menuCount: accessStore.accessMenus?.length || 0,
|
|
isAccessChecked: accessStore.isAccessChecked,
|
|
accessCodes: accessStore.accessCodes
|
|
};
|
|
});
|
|
|
|
console.log('\nVue应用状态:', JSON.stringify(vueStatus, null, 2));
|
|
|
|
// 检查菜单渲染
|
|
console.log('\n检查菜单渲染...');
|
|
const menuInfo = await page.evaluate(() => {
|
|
// 查找菜单容器
|
|
const menuContainers = document.querySelectorAll('.ant-menu, .menu-container, [class*="menu"]');
|
|
const info = {
|
|
containers: [],
|
|
menuItems: 0
|
|
};
|
|
|
|
menuContainers.forEach(container => {
|
|
const items = container.querySelectorAll('.ant-menu-item, .ant-menu-submenu');
|
|
info.containers.push({
|
|
class: container.className,
|
|
itemCount: items.length,
|
|
visible: container.offsetWidth > 0 && container.offsetHeight > 0
|
|
});
|
|
info.menuItems += items.length;
|
|
});
|
|
|
|
return info;
|
|
});
|
|
|
|
console.log('菜单信息:', JSON.stringify(menuInfo, null, 2));
|
|
|
|
// 尝试手动触发菜单渲染
|
|
console.log('\n尝试手动触发菜单渲染...');
|
|
const renderResult = await page.evaluate(() => {
|
|
// 尝试找到并触发菜单组件更新
|
|
const menuElements = document.querySelectorAll('[class*="menu"]');
|
|
|
|
menuElements.forEach(el => {
|
|
// 尝试获取Vue组件实例
|
|
const vueInstance = el.__vue__ || el.__vueParentComponent;
|
|
if (vueInstance && vueInstance.proxy && vueInstance.proxy.$forceUpdate) {
|
|
vueInstance.proxy.$forceUpdate();
|
|
return { updated: true, element: el.className };
|
|
}
|
|
});
|
|
|
|
return { updated: false };
|
|
});
|
|
|
|
console.log('渲染结果:', renderResult);
|
|
|
|
// 总结
|
|
console.log('\n\n=== 错误总结 ===');
|
|
console.log(`捕获到 ${errors.length} 个错误`);
|
|
console.log(`捕获到 ${warnings.length} 个警告`);
|
|
|
|
if (errors.length > 0) {
|
|
console.log('\n主要错误:');
|
|
errors.forEach((err, index) => {
|
|
console.log(`${index + 1}. ${err.text}`);
|
|
});
|
|
}
|
|
|
|
// 截图
|
|
await page.screenshot({ path: 'test-screenshots/console-errors.png', fullPage: true });
|
|
|
|
console.log('\n截图已保存。保持浏览器打开以查看详情...');
|
|
await new Promise(() => {});
|
|
|
|
} catch (error) {
|
|
console.error('脚本出错:', error);
|
|
if (browser) {
|
|
await browser.close();
|
|
}
|
|
}
|
|
})(); |