import { chromium } from 'playwright'; async function completeAuthTest() { const browser = await chromium.launch({ headless: false, slowMo: 1000 }); const context = await browser.newContext(); const page = await context.newPage(); const apiCalls = []; // 监听所有API调用,特别关注/auth和/base接口 page.on('request', (request) => { const url = request.url(); // 监听所有后端API调用 if ( url.includes('localhost:3000') || url.includes('/auth/') || url.includes('/base') || url.includes('/api/') ) { const headers = request.headers(); apiCalls.push({ method: request.method(), url: request.url(), headers: headers, timestamp: new Date().toISOString(), }); console.log(`🔵 API请求: ${request.method()} ${request.url()}`); // 检查Authorization头 if (headers['authorization']) { console.log( `🔑 包含Authorization头: ${headers['authorization'].substring(0, 30)}...`, ); } else { console.log(`⚠️ 未包含Authorization头`); } } }); page.on('response', async (response) => { const url = response.url(); if ( url.includes('localhost:3000') || url.includes('/auth/') || url.includes('/base') || url.includes('/api/') ) { const status = response.status(); console.log(`🟢 API响应: ${status} ${response.url()}`); if (status === 200) { try { const responseText = await response.text(); console.log(`📋 响应内容: ${responseText.substring(0, 200)}...`); } catch (e) { console.log('获取响应内容失败'); } } else if (status === 401) { console.log(`❌ 401认证失败: ${response.url()}`); try { const errorText = await response.text(); console.log(`📋 错误响应: ${errorText}`); } catch (e) { console.log('无法获取错误响应内容'); } } } }); // 监听控制台 page.on('console', (msg) => { if (msg.type() === 'error') { console.log(`❌ 页面错误: ${msg.text()}`); } }); try { console.log('🚀 开始完整认证测试...'); // 1. 访问登录页面 await page.goto('http://localhost:5173/auth/login'); console.log('✅ 已访问登录页面'); // 等待页面完全加载 await page.waitForLoadState('networkidle'); await page.waitForTimeout(3000); // 2. 等待并填写表单 console.log('📝 等待表单元素...'); try { await page.waitForSelector('input[name="username"]', { timeout: 15000 }); await page.waitForSelector('input[name="password"]', { timeout: 15000 }); console.log('✅ 表单元素已找到'); } catch (e) { console.log('❌ 表单元素查找超时,尝试其他选择器...'); // 尝试其他选择器 const inputs = await page.$$('input'); console.log(`发现 ${inputs.length} 个输入框`); if (inputs.length >= 2) { console.log('✅ 使用通用输入框选择器'); await inputs[0].fill('admin'); await inputs[1].fill('111111'); } else { throw new Error('未找到足够的输入框'); } } // 填写表单 if (await page.$('input[name="username"]')) { await page.fill('input[name="username"]', 'admin'); await page.fill('input[name="password"]', '111111'); console.log('✅ 表单已填写'); } // 3. 提交表单 console.log('🖱️ 寻找并点击登录按钮...'); // 尝试多种登录按钮选择器 const buttonSelectors = [ 'button:has-text("登录")', 'button[type="submit"]', '.ant-btn-primary', 'button.login-btn', ]; let buttonClicked = false; for (const selector of buttonSelectors) { try { const button = await page.$(selector); if (button) { await button.click(); console.log(`✅ 使用选择器 ${selector} 点击了登录按钮`); buttonClicked = true; break; } } catch (e) { continue; } } if (!buttonClicked) { console.log('⚠️ 未找到登录按钮,尝试按Enter键'); await page.keyboard.press('Enter'); } // 4. 等待认证处理 console.log('⏳ 等待认证处理...'); await page.waitForTimeout(5000); // 5. 检查结果 const currentUrl = page.url(); console.log(`📍 当前URL: ${currentUrl}`); if (currentUrl.includes('/dashboard')) { console.log('🎉 登录成功!成功跳转到dashboard'); // 检查token const token = await page.evaluate(() => { return ( localStorage.getItem('accessToken') || localStorage.getItem('token') || localStorage.getItem('authToken') ); }); if (token) { console.log(`✅ Token已存储: ${token.substring(0, 20)}...`); } else { console.log('⚠️ 未找到token,但页面已跳转'); } // 等待dashboard加载并检查数据 await page.waitForTimeout(5000); console.log('📊 检查dashboard数据和API调用...'); // 检查页面内容 const hasData = await page.evaluate(() => { const bodyText = document.body.textContent || ''; return ( bodyText.includes('数据') || bodyText.includes('统计') || bodyText.includes('总数') || bodyText.includes('Dashboard') || bodyText.includes('仪表板') ); }); if (hasData) { console.log('✅ Dashboard显示数据内容'); } else { console.log('⚠️ Dashboard可能没有显示预期数据'); } // 检查是否有/base接口调用(用户特别要求的) const baseApiCalls = apiCalls.filter((call) => call.url.includes('/base'), ); if (baseApiCalls.length > 0) { console.log(`✅ 发现 ${baseApiCalls.length} 个/base接口调用:`); baseApiCalls.forEach((call) => { console.log(` - ${call.method} ${call.url}`); if (call.headers['authorization']) { console.log( ` Authorization: ${call.headers['authorization'].substring(0, 30)}...`, ); } }); } else { console.log('⚠️ 未发现/base接口调用'); } // 再等待一段时间,确保所有异步数据加载完成 console.log('⏳ 等待更多API调用...'); await page.waitForTimeout(5000); } else { console.log('❌ 登录失败,仍在登录页面'); // 检查是否有错误消息 const errorMessage = await page.textContent('body'); if (errorMessage.includes('失败') || errorMessage.includes('错误')) { console.log('⚠️ 页面显示错误信息'); } } // 6. 详细API调用分析 console.log(`\n📊 详细API调用分析:`); console.log(`总共发起了 ${apiCalls.length} 个API调用`); if (apiCalls.length > 0) { console.log('\n🔍 所有API调用详情:'); apiCalls.forEach((call, index) => { console.log(`${index + 1}. ${call.method} ${call.url}`); if (call.headers['authorization']) { console.log( ` 🔑 Authorization: ${call.headers['authorization'].substring(0, 40)}...`, ); } else { console.log(` ⚠️ 无Authorization头`); } console.log(` ⏰ 时间: ${call.timestamp}`); console.log(''); }); // 分类统计 const authCalls = apiCalls.filter((call) => call.url.includes('/auth/')); const baseCalls = apiCalls.filter((call) => call.url.includes('/base')); const apiRoutes = apiCalls.filter((call) => call.url.includes('/api/')); console.log('\n📈 分类统计:'); console.log(`- 认证接口(/auth/): ${authCalls.length} 个`); console.log(`- 基础接口(/base): ${baseCalls.length} 个`); console.log(`- API路由(/api/): ${apiRoutes.length} 个`); // 检查401错误 const has401 = apiCalls.some( (call) => call.url.includes('401') || call.status === 401, ); if (has401) { console.log('\n❌ 发现401认证错误'); } else { console.log('\n✅ 未发现401认证错误'); } } else { console.log('❌ 没有发现任何API调用'); } console.log('\n⏰ 保持浏览器打开15秒供手动检查...'); await page.waitForTimeout(15000); } catch (error) { console.error('❌ 测试失败:', error.message); } await browser.close(); } completeAuthTest().catch(console.error);