feat: 配置开发环境和清理项目结构

- 修改默认路由重定向到首页 (/home)
- 配置开发服务器使用5667端口
- 整理测试文件到temp-tests目录
- 优化项目结构便于开发和部署

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
woshiqp465
2025-09-15 21:35:49 +08:00
parent 9be0b9788f
commit 9683b940bf
37 changed files with 3 additions and 223 deletions

View File

@@ -0,0 +1,187 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
});
const context = await browser.newContext();
const page = await context.newPage();
// 监听控制台错误
page.on('console', msg => {
if (msg.type() === 'error') {
console.error('浏览器控制台错误:', msg.text());
}
});
try {
console.log('🚀 开始完整测试分析功能...\n');
// 1. 访问首页并登录
console.log('1. 登录系统...');
await page.goto('http://localhost:5669/', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);
// 检查是否需要登录
const needLogin = await page.locator('button:has-text("登录")').isVisible();
if (needLogin) {
await page.fill('input[placeholder*="账号"]', 'vben');
await page.fill('input[placeholder*="密码"]', '123456');
await page.locator('button:has-text("登录")').click();
await page.waitForTimeout(3000);
console.log(' ✅ 登录成功');
}
// 2. 刷新页面让菜单重新加载
console.log('\n2. 刷新页面重新加载菜单...');
await page.reload({ waitUntil: 'networkidle' });
await page.waitForTimeout(3000);
// 3. 查找并点击数据分析菜单
console.log('\n3. 导航到分析页面...');
// 尝试查找数据分析菜单
const analyticsMenu = await page.locator('span:has-text("数据分析")').first();
if (await analyticsMenu.isVisible()) {
console.log(' ✅ 找到"数据分析"菜单');
await analyticsMenu.click();
await page.waitForTimeout(1500);
// 查找数据概览子菜单
const overviewMenu = await page.locator('span:has-text("数据概览")').first();
if (await overviewMenu.isVisible()) {
console.log(' ✅ 找到"数据概览"子菜单');
await overviewMenu.click();
await page.waitForTimeout(3000);
} else {
console.log(' ❌ 未找到"数据概览"子菜单尝试直接访问URL');
await page.goto('http://localhost:5669/analytics/overview', { waitUntil: 'networkidle' });
await page.waitForTimeout(3000);
}
} else {
console.log(' ❌ 未找到"数据分析"菜单尝试直接访问URL');
await page.goto('http://localhost:5668/analytics/overview', { waitUntil: 'networkidle' });
await page.waitForTimeout(3000);
}
// 4. 检查页面是否正确加载
console.log('\n4. 检查页面加载状态...');
const currentUrl = page.url();
console.log(' 当前URL:', currentUrl);
// 检查是否还是404
const is404 = await page.locator('text="404"').isVisible();
if (is404) {
console.log(' ❌ 页面仍然显示404错误');
console.log('\n 尝试访问财务管理页面作为备选...');
// 访问财务管理
await page.goto('http://localhost:5669/finance/dashboard', { waitUntil: 'networkidle' });
await page.waitForTimeout(3000);
const financeLoaded = !await page.locator('text="404"').isVisible();
if (financeLoaded) {
console.log(' ✅ 财务管理页面加载成功');
}
} else {
console.log(' ✅ 分析页面加载成功!');
// 5. 详细检查功能组件
console.log('\n5. 检查关键功能组件...');
// 等待组件加载
await page.waitForTimeout(2000);
// 检查关键指标卡片
const hasMetricsCards = await page.locator('.key-metrics-cards').isVisible();
console.log(` 关键指标卡片: ${hasMetricsCards ? '✅' : '❌'}`);
if (hasMetricsCards) {
const metricsCount = await page.locator('.metric-card').count();
console.log(` - 发现 ${metricsCount} 个指标卡片`);
// 检查具体指标
const indicators = [
{ selector: '.ant-statistic-title:has-text("总收入")', name: '总收入' },
{ selector: '.ant-statistic-title:has-text("总支出")', name: '总支出' },
{ selector: '.ant-statistic-title:has-text("净收益")', name: '净收益' },
{ selector: '.ant-statistic-title:has-text("日均收支")', name: '日均收支' },
];
for (const ind of indicators) {
const visible = await page.locator(ind.selector).isVisible();
console.log(` - ${ind.name}: ${visible ? '✅' : '❌'}`);
}
}
// 检查标签页
const hasTabs = await page.locator('.ant-tabs').isVisible();
console.log(`\n 标签页导航: ${hasTabs ? '✅' : '❌'}`);
if (hasTabs) {
const tabs = [
{ name: '核心指标', selector: '.trend-chart' },
{ name: '预算分析', selector: '.budget-comparison' },
{ name: '智能洞察', selector: '.smart-insights' },
{ name: '标签分析', selector: '.tag-cloud-analysis' },
{ name: '时间维度', selector: '.time-dimension-analysis' },
];
for (const tab of tabs) {
console.log(`\n 测试"${tab.name}"标签页...`);
const tabElement = await page.locator(`.ant-tabs-tab:has-text("${tab.name}")`);
if (await tabElement.isVisible()) {
await tabElement.click();
await page.waitForTimeout(2000);
// 检查对应组件是否加载
const componentVisible = await page.locator(tab.selector).isVisible();
console.log(` 组件加载: ${componentVisible ? '✅' : '❌'}`);
// 截取每个标签页的截图
await page.screenshot({
path: `analytics-tab-${tab.name.replace(/[^a-z0-9]/gi, '-')}.png`,
fullPage: false
});
} else {
console.log(` 标签不可见 ❌`);
}
}
}
// 6. 测试交互功能
console.log('\n6. 测试交互功能...');
// 测试日期选择器
const dateRangePicker = await page.locator('.ant-picker-range');
if (await dateRangePicker.isVisible()) {
console.log(' 日期范围选择器: ✅');
}
// 测试刷新按钮
const refreshButton = await page.locator('button:has-text("刷新数据")');
if (await refreshButton.isVisible()) {
console.log(' 刷新数据按钮: ✅');
await refreshButton.click();
await page.waitForTimeout(2000);
console.log(' 数据刷新完成');
}
// 最终成功截图
await page.screenshot({ path: 'analytics-complete-success.png', fullPage: true });
console.log('\n📸 完整功能测试截图已保存: analytics-complete-success.png');
console.log('\n✅ 🎉 分析功能测试完全成功!所有组件正常工作!');
}
} catch (error) {
console.error('\n❌ 测试过程中出错:', error);
await page.screenshot({ path: 'analytics-complete-error.png' });
console.log('错误截图已保存: analytics-complete-error.png');
} finally {
console.log('\n测试完成5秒后关闭浏览器...');
await page.waitForTimeout(5000);
await browser.close();
}
})();

View File

@@ -0,0 +1,144 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
devtools: true // 打开开发者工具
});
const context = await browser.newContext();
const page = await context.newPage();
// 监听控制台消息
page.on('console', msg => {
if (msg.type() === 'error') {
console.error('浏览器控制台错误:', msg.text());
}
});
// 监听页面错误
page.on('pageerror', error => {
console.error('页面错误:', error.message);
});
// 监听响应
page.on('response', response => {
if (response.status() >= 400) {
console.log(`请求失败: ${response.url()} - 状态码: ${response.status()}`);
}
});
try {
console.log('开始调试分析功能...\n');
// 1. 首先访问首页
console.log('1. 访问首页...');
await page.goto('http://localhost:5667/', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);
// 检查是否需要登录
const needLogin = await page.locator('button:has-text("登录")').isVisible();
if (needLogin) {
console.log(' 需要登录,使用默认账号...');
await page.fill('input[placeholder*="账号"]', 'vben');
await page.fill('input[placeholder*="密码"]', '123456');
await page.locator('button:has-text("登录")').click();
await page.waitForTimeout(3000);
}
// 2. 检查菜单
console.log('\n2. 检查菜单结构...');
const analyticsMenu = await page.locator('span:has-text("数据分析")').first();
if (await analyticsMenu.isVisible()) {
console.log(' ✅ 找到"数据分析"菜单');
await analyticsMenu.click();
await page.waitForTimeout(1000);
// 查找数据概览子菜单
const overviewMenu = await page.locator('span:has-text("数据概览")').first();
if (await overviewMenu.isVisible()) {
console.log(' ✅ 找到"数据概览"子菜单');
await overviewMenu.click();
await page.waitForTimeout(2000);
} else {
console.log(' ❌ 未找到"数据概览"子菜单');
}
} else {
console.log(' ❌ 未找到"数据分析"菜单');
}
// 3. 检查当前URL
console.log('\n3. 检查当前页面...');
const currentUrl = page.url();
console.log(' 当前URL:', currentUrl);
// 4. 直接导航到分析页面
console.log('\n4. 直接访问分析页面...');
await page.goto('http://localhost:5667/analytics/overview', { waitUntil: 'networkidle' });
await page.waitForTimeout(3000);
// 检查是否404
const is404 = await page.locator('text="404"').isVisible();
if (is404) {
console.log(' ❌ 页面返回404错误');
// 检查可用的路由
console.log('\n5. 尝试其他路由...');
const testRoutes = [
'/finance/dashboard',
'/finance/transaction',
'/dashboard/analytics',
'/analytics',
];
for (const route of testRoutes) {
await page.goto(`http://localhost:5667${route}`, { waitUntil: 'networkidle' });
await page.waitForTimeout(1000);
const hasError = await page.locator('text="404"').isVisible();
console.log(` ${route}: ${hasError ? '❌ 404' : '✅ 成功'}`);
}
} else {
console.log(' ✅ 页面加载成功');
// 检查组件是否加载
console.log('\n6. 检查组件加载...');
const components = [
{ selector: '.key-metrics-cards', name: '关键指标卡片' },
{ selector: '.ant-tabs', name: '标签页' },
{ selector: '.budget-comparison', name: '预算对比' },
{ selector: '.smart-insights', name: '智能洞察' },
{ selector: '.tag-cloud-analysis', name: '标签云' },
{ selector: '.time-dimension-analysis', name: '时间维度' },
];
for (const comp of components) {
const isVisible = await page.locator(comp.selector).isVisible();
console.log(` ${comp.name}: ${isVisible ? '✅' : '❌'}`);
}
}
// 7. 获取页面内容检查
console.log('\n7. 页面内容检查...');
const pageTitle = await page.title();
console.log(' 页面标题:', pageTitle);
const bodyText = await page.locator('body').textContent();
if (bodyText.includes('数据概览')) {
console.log(' ✅ 找到"数据概览"文本');
}
if (bodyText.includes('关键指标')) {
console.log(' ✅ 找到"关键指标"相关内容');
}
// 截图
await page.screenshot({ path: 'analytics-debug.png', fullPage: true });
console.log('\n📸 调试截图已保存: analytics-debug.png');
} catch (error) {
console.error('\n❌ 调试过程中出错:', error);
await page.screenshot({ path: 'error-debug.png' });
} finally {
console.log('\n按任意键关闭浏览器...');
await page.waitForTimeout(10000); // 等待10秒让开发者查看
await browser.close();
}
})();

View File

@@ -0,0 +1,139 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
try {
console.log('开始测试分析功能...');
// 访问登录页
await page.goto('http://localhost:5667/');
await page.waitForTimeout(2000);
// 跳过登录或使用默认账号
const loginButton = await page.locator('button:has-text("登录")').first();
if (await loginButton.isVisible()) {
console.log('正在登录...');
await page.fill('input[placeholder*="账号"]', 'vben');
await page.fill('input[placeholder*="密码"]', '123456');
await loginButton.click();
await page.waitForTimeout(3000);
}
// 导航到分析页面
console.log('导航到分析页面...');
await page.goto('http://localhost:5667/analytics/overview');
await page.waitForTimeout(3000);
// 检查关键指标卡片
console.log('\n✅ 检查关键指标卡片...');
const metricsCards = await page.locator('.key-metrics-cards').isVisible();
console.log('- 关键指标卡片显示:', metricsCards);
if (metricsCards) {
const totalIncome = await page.locator('.ant-statistic-title:has-text("总收入")').isVisible();
const totalExpense = await page.locator('.ant-statistic-title:has-text("总支出")').isVisible();
const netProfit = await page.locator('.ant-statistic-title:has-text("净收益")').isVisible();
const dailyAvg = await page.locator('.ant-statistic-title:has-text("日均收支")').isVisible();
console.log(' - 总收入卡片:', totalIncome);
console.log(' - 总支出卡片:', totalExpense);
console.log(' - 净收益卡片:', netProfit);
console.log(' - 日均收支卡片:', dailyAvg);
}
// 测试各个标签页
console.log('\n✅ 测试标签页切换...');
// 测试预算分析标签
const budgetTab = await page.locator('.ant-tabs-tab:has-text("预算分析")');
if (await budgetTab.isVisible()) {
console.log('- 切换到预算分析标签');
await budgetTab.click();
await page.waitForTimeout(2000);
const budgetComparison = await page.locator('.budget-comparison').isVisible();
console.log(' 预算对比组件显示:', budgetComparison);
}
// 测试智能洞察标签
const insightsTab = await page.locator('.ant-tabs-tab:has-text("智能洞察")');
if (await insightsTab.isVisible()) {
console.log('- 切换到智能洞察标签');
await insightsTab.click();
await page.waitForTimeout(2000);
const smartInsights = await page.locator('.smart-insights').isVisible();
console.log(' 智能洞察组件显示:', smartInsights);
// 检查洞察内容
const insightItems = await page.locator('.insight-item').count();
console.log(` 发现 ${insightItems} 条洞察建议`);
}
// 测试标签分析标签
const tagTab = await page.locator('.ant-tabs-tab:has-text("标签分析")');
if (await tagTab.isVisible()) {
console.log('- 切换到标签分析标签');
await tagTab.click();
await page.waitForTimeout(2000);
const tagCloud = await page.locator('.tag-cloud-analysis').isVisible();
console.log(' 标签云分析组件显示:', tagCloud);
}
// 测试时间维度标签
const timeTab = await page.locator('.ant-tabs-tab:has-text("时间维度")');
if (await timeTab.isVisible()) {
console.log('- 切换到时间维度标签');
await timeTab.click();
await page.waitForTimeout(2000);
const timeDimension = await page.locator('.time-dimension-analysis').isVisible();
console.log(' 时间维度分析组件显示:', timeDimension);
// 测试视图切换
const viewModes = await page.locator('.ant-radio-button-wrapper').count();
console.log(` 发现 ${viewModes} 个视图模式`);
if (viewModes > 0) {
const hourView = await page.locator('.ant-radio-button-wrapper:has-text("时段")');
if (await hourView.isVisible()) {
console.log(' 切换到时段视图');
await hourView.click();
await page.waitForTimeout(1000);
}
}
}
// 测试日期筛选
console.log('\n✅ 测试日期筛选功能...');
const dateRangePicker = await page.locator('.ant-picker-range');
if (await dateRangePicker.isVisible()) {
console.log('- 日期范围选择器可用');
// 测试刷新按钮
const refreshButton = await page.locator('button:has-text("刷新数据")');
if (await refreshButton.isVisible()) {
console.log('- 点击刷新数据');
await refreshButton.click();
await page.waitForTimeout(2000);
}
}
// 截图保存
console.log('\n📸 保存截图...');
await page.screenshot({ path: 'analytics-overview.png', fullPage: true });
console.log('\n✨ 分析功能测试完成!');
console.log('所有新功能都已成功集成并正常工作。');
} catch (error) {
console.error('测试过程中出错:', error);
await page.screenshot({ path: 'error-screenshot.png' });
} finally {
await browser.close();
}
})();

View File

@@ -0,0 +1,144 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
});
const context = await browser.newContext();
const page = await context.newPage();
// 监听控制台错误
page.on('console', msg => {
if (msg.type() === 'error') {
console.error('浏览器控制台错误:', msg.text());
}
});
try {
console.log('🚀 开始测试新的分析功能...\n');
// 1. 访问首页并登录
console.log('1. 登录系统...');
await page.goto('http://localhost:5668/', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);
const needLogin = await page.locator('button:has-text("登录")').isVisible();
if (needLogin) {
await page.fill('input[placeholder*="账号"]', 'vben');
await page.fill('input[placeholder*="密码"]', '123456');
await page.locator('button:has-text("登录")').click();
await page.waitForTimeout(3000);
console.log(' ✅ 登录成功');
}
// 2. 导航到分析页面
console.log('\n2. 导航到分析页面...');
// 尝试通过菜单导航
const analyticsMenu = await page.locator('span:has-text("数据分析")').first();
if (await analyticsMenu.isVisible()) {
console.log(' 点击数据分析菜单');
await analyticsMenu.click();
await page.waitForTimeout(1000);
const overviewMenu = await page.locator('span:has-text("数据概览")').first();
if (await overviewMenu.isVisible()) {
console.log(' 点击数据概览子菜单');
await overviewMenu.click();
await page.waitForTimeout(3000);
}
} else {
// 直接导航
console.log(' 直接访问分析页面URL');
await page.goto('http://localhost:5668/analytics/overview', { waitUntil: 'networkidle' });
await page.waitForTimeout(3000);
}
// 3. 检查页面是否正确加载
console.log('\n3. 检查页面加载状态...');
const currentUrl = page.url();
console.log(' 当前URL:', currentUrl);
const is404 = await page.locator('text="404"').isVisible();
if (is404) {
console.log(' ❌ 页面显示404错误');
// 截图保存错误状态
await page.screenshot({ path: 'analytics-404-error.png', fullPage: true });
console.log(' 错误截图已保存: analytics-404-error.png');
// 尝试返回首页再重新导航
console.log('\n4. 尝试从首页重新导航...');
await page.goto('http://localhost:5668/workspace', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);
} else {
console.log(' ✅ 页面加载成功');
// 4. 检查关键功能组件
console.log('\n4. 检查关键功能组件...');
// 检查关键指标卡片
const hasMetricsCards = await page.locator('.key-metrics-cards').isVisible();
console.log(` 关键指标卡片: ${hasMetricsCards ? '✅' : '❌'}`);
if (hasMetricsCards) {
const metricsCount = await page.locator('.metric-card').count();
console.log(` - 发现 ${metricsCount} 个指标卡片`);
}
// 检查标签页
const hasTabs = await page.locator('.ant-tabs').isVisible();
console.log(` 标签页导航: ${hasTabs ? '✅' : '❌'}`);
if (hasTabs) {
const tabCount = await page.locator('.ant-tabs-tab').count();
console.log(` - 发现 ${tabCount} 个标签页`);
// 测试每个标签页
const tabs = [
{ name: '预算分析', selector: '.budget-comparison' },
{ name: '智能洞察', selector: '.smart-insights' },
{ name: '标签分析', selector: '.tag-cloud-analysis' },
{ name: '时间维度', selector: '.time-dimension-analysis' },
];
for (const tab of tabs) {
const tabElement = await page.locator(`.ant-tabs-tab:has-text("${tab.name}")`);
if (await tabElement.isVisible()) {
console.log(`\n 测试 ${tab.name} 标签页...`);
await tabElement.click();
await page.waitForTimeout(2000);
const componentVisible = await page.locator(tab.selector).isVisible();
console.log(` 组件显示: ${componentVisible ? '✅' : '❌'}`);
}
}
}
// 5. 测试数据刷新功能
console.log('\n5. 测试数据刷新...');
const refreshButton = await page.locator('button:has-text("刷新数据")');
if (await refreshButton.isVisible()) {
console.log(' 点击刷新按钮');
await refreshButton.click();
await page.waitForTimeout(2000);
console.log(' ✅ 数据刷新完成');
}
// 成功截图
await page.screenshot({ path: 'analytics-success.png', fullPage: true });
console.log('\n📸 功能测试截图已保存: analytics-success.png');
}
console.log('\n✨ 测试完成!');
} catch (error) {
console.error('\n❌ 测试过程中出错:', error);
await page.screenshot({ path: 'analytics-error.png' });
console.log('错误截图已保存: analytics-error.png');
} finally {
await page.waitForTimeout(5000); // 等待5秒让用户查看
await browser.close();
}
})();

View File

@@ -0,0 +1,131 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 300,
});
const page = await browser.newPage();
// 监听控制台
page.on('console', (msg) => {
const text = msg.text();
if (text.includes('开发模式')) {
console.log('[自动登录]', text);
}
if (msg.type() === 'error') {
console.log('[错误]', text);
}
});
try {
console.log('========== 测试自动登录功能 ==========\n');
// 1. 访问登录页
console.log('1. 访问登录页面...');
await page.goto('http://localhost:5667/auth/login');
console.log(' 等待自动登录...');
// 等待自动登录执行
await page.waitForTimeout(3000);
// 2. 检查是否自动跳转
const currentUrl = page.url();
console.log(' 当前URL:', currentUrl);
if (currentUrl.includes('/login')) {
console.log(' ⚠️ 自动登录未执行或失败');
console.log(' 请检查是否在开发模式下运行');
// 检查页面元素
const sliderBtn = await page.locator('.slider-button');
const captchaVisible = await sliderBtn.isVisible();
console.log(` 验证码是否显示: ${captchaVisible ? '是' : '否'}`);
await page.screenshot({ path: 'auto-login-failed.png' });
console.log('\n截图保存: auto-login-failed.png');
} else {
console.log(' ✅ 自动登录成功!已跳转到首页\n');
// 3. 访问交易管理页面
console.log('2. 访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(2000);
// 检查页面元素
const table = await page.locator('.ant-table');
const createBtn = await page.locator('button:has-text("新建")');
if (await table.isVisible()) {
console.log(' ✅ 交易列表显示正常');
const rows = await page.locator('.ant-table-tbody tr').count();
console.log(` 当前有 ${rows} 条交易记录`);
}
// 4. 测试新建交易
if (await createBtn.isVisible()) {
console.log('\n3. 测试新建交易功能...');
await createBtn.click();
await page.waitForTimeout(1000);
const modal = await page.locator('.ant-modal');
if (await modal.isVisible()) {
console.log(' ✅ 新建交易弹窗打开');
// 选择类型
const typeSelect = await page.locator('.ant-select').nth(0);
await typeSelect.click();
await page.locator('.ant-select-item:has-text("支出")').click();
console.log(' 选择类型: 支出');
// 输入金额
const amountInput = await page.locator(
'input.ant-input-number-input',
);
await amountInput.fill('288.88');
console.log(' 输入金额: 288.88');
// 输入描述
const descInput = await page.locator('textarea[placeholder*="描述"]');
if (await descInput.isVisible()) {
await descInput.fill('自动登录测试交易');
console.log(' 输入描述: 自动登录测试交易');
}
// 提交
const submitBtn = await page.locator(
'.ant-modal-footer button.ant-btn-primary',
);
await submitBtn.click();
console.log(' 提交表单...');
await page.waitForTimeout(2000);
// 检查结果
const successMsg = await page.locator('.ant-message-success');
if (await successMsg.isVisible()) {
console.log(' ✅ 交易创建成功!');
}
}
}
// 截图
await page.screenshot({ path: 'auto-login-success.png', fullPage: true });
console.log('\n截图保存: auto-login-success.png');
console.log('\n========== 测试完成 ==========');
console.log('✅ 开发模式自动登录正常');
console.log('✅ 无需手动处理验证码');
console.log('✅ 交易管理功能正常');
console.log('✅ 新建交易功能正常');
}
} catch (error) {
console.error('\n❌ 测试失败:', error.message);
await page.screenshot({ path: 'error.png' });
} finally {
console.log('\n浏览器将在5秒后关闭...');
await page.waitForTimeout(5000);
await browser.close();
}
})();

View File

@@ -0,0 +1,87 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('1. 访问分类统计页面...');
await page.goto('http://localhost:5666/finance/category-stats', { waitUntil: 'networkidle' });
await page.waitForTimeout(3000);
// 检查当前URL
const currentUrl = page.url();
console.log('当前URL:', currentUrl);
if (currentUrl.includes('login')) {
console.log('需要登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
await page.click('button:has-text("登录")');
await page.waitForTimeout(2000);
await page.goto('http://localhost:5666/finance/category-stats', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);
}
console.log('\n2. 测试快速日期选择...');
// 测试"本月"按钮选中状态
const monthButtonClass = await page.locator('button:has-text("本月")').getAttribute('class');
console.log(' - 本月按钮默认选中:', monthButtonClass?.includes('ant-radio-button-checked') ? '✓' : '✗');
// 点击"本年"
await page.click('button:has-text("本年")');
await page.waitForTimeout(1000);
const yearButtonClass = await page.locator('button:has-text("本年")').getAttribute('class');
console.log(' - 本年按钮选中:', yearButtonClass?.includes('ant-radio-button-checked') ? '✓' : '✗');
// 点击"今天"
await page.click('button:has-text("今天")');
await page.waitForTimeout(1000);
const todayButtonClass = await page.locator('button:has-text("今天")').getAttribute('class');
console.log(' - 今天按钮选中:', todayButtonClass?.includes('ant-radio-button-checked') ? '✓' : '✗');
console.log('\n3. 测试图表切换和数据显示...');
// 切换到柱状图
await page.click('button:has-text("柱状图")');
await page.waitForTimeout(2000);
// 检查柱状图是否显示
const barChartVisible = await page.locator('div[style*="height: 500px"]:visible canvas').count();
console.log(' - 柱状图显示:', barChartVisible > 0 ? '✓' : '✗');
// 截图柱状图
await page.screenshot({ path: 'bar-chart.png' });
console.log(' - 柱状图截图: bar-chart.png');
// 切换到趋势图
await page.click('button:has-text("趋势图")');
await page.waitForTimeout(2000);
// 检查趋势图是否显示
const trendChartVisible = await page.locator('div[style*="height: 500px"]:visible canvas').count();
console.log(' - 趋势图显示:', trendChartVisible > 0 ? '✓' : '✗');
// 截图趋势图
await page.screenshot({ path: 'trend-chart.png' });
console.log(' - 趋势图截图: trend-chart.png');
// 切换回饼图
await page.click('button:has-text("饼图")');
await page.waitForTimeout(2000);
const pieChartVisible = await page.locator('div[style*="height: 500px"]:visible canvas').count();
console.log(' - 饼图显示:', pieChartVisible > 0 ? '✓' : '✗');
// 最终截图
await page.screenshot({ path: 'final-category-stats.png', fullPage: true });
console.log('\n✅ 测试完成!最终截图: final-category-stats.png');
} catch (error) {
console.error('测试失败:', error.message);
await page.screenshot({ path: 'test-error.png' });
} finally {
await browser.close();
}
})();

View File

@@ -0,0 +1,104 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('1. 访问登录页面...');
await page.goto('http://localhost:5666');
// 等待登录页面加载
await page.waitForSelector('input[placeholder*="账号"]', { timeout: 10000 });
console.log('2. 执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
// 点击登录按钮
await page.click('button:has-text("登录")');
// 等待跳转到首页
await page.waitForURL('**/dashboard', { timeout: 10000 });
console.log('3. 登录成功,已进入系统');
// 导航到分类统计页面
console.log('4. 访问分类统计页面...');
await page.goto('http://localhost:5666/finance/category-stats');
// 等待页面加载完成
await page.waitForLoadState('networkidle');
// 检查页面元素
console.log('5. 检查页面元素...');
// 检查统计卡片
const totalIncomeCard = await page.locator('.ant-statistic-title:has-text("总收入")').isVisible();
const totalExpenseCard = await page.locator('.ant-statistic-title:has-text("总支出")').isVisible();
const netIncomeCard = await page.locator('.ant-statistic-title:has-text("净收入")').isVisible();
console.log(' - 总收入卡片:', totalIncomeCard ? '✓' : '✗');
console.log(' - 总支出卡片:', totalExpenseCard ? '✓' : '✗');
console.log(' - 净收入卡片:', netIncomeCard ? '✓' : '✗');
// 检查图表切换按钮
const pieButton = await page.locator('button:has-text("饼图")').isVisible();
const barButton = await page.locator('button:has-text("柱状图")').isVisible();
const trendButton = await page.locator('button:has-text("趋势图")').isVisible();
console.log(' - 饼图按钮:', pieButton ? '✓' : '✗');
console.log(' - 柱状图按钮:', barButton ? '✓' : '✗');
console.log(' - 趋势图按钮:', trendButton ? '✓' : '✗');
// 切换到表格视图
console.log('6. 切换到表格视图...');
await page.click('button:has-text("表格")');
await page.waitForTimeout(1000);
// 检查表格是否显示
const table = await page.locator('.ant-table').isVisible();
console.log(' - 表格显示:', table ? '✓' : '✗');
// 切换回图表视图
console.log('7. 切换回图表视图...');
await page.click('button:has-text("图表")');
await page.waitForTimeout(1000);
// 切换不同的图表类型
console.log('8. 测试图表切换...');
await page.click('button:has-text("柱状图")');
await page.waitForTimeout(1000);
console.log(' - 切换到柱状图: ✓');
await page.click('button:has-text("趋势图")');
await page.waitForTimeout(1000);
console.log(' - 切换到趋势图: ✓');
await page.click('button:has-text("饼图")');
await page.waitForTimeout(1000);
console.log(' - 切换回饼图: ✓');
// 测试日期快速选择
console.log('9. 测试日期快速选择...');
await page.click('button:has-text("本月")');
await page.waitForTimeout(1000);
console.log(' - 选择本月: ✓');
await page.click('button:has-text("本年")');
await page.waitForTimeout(1000);
console.log(' - 选择本年: ✓');
// 截图
await page.screenshot({ path: 'category-stats-test.png', fullPage: true });
console.log('10. 页面截图已保存为 category-stats-test.png');
console.log('\n✅ 分类统计页面测试完成!所有功能正常工作。');
} catch (error) {
console.error('❌ 测试失败:', error.message);
await page.screenshot({ path: 'category-stats-error.png' });
console.log('错误截图已保存为 category-stats-error.png');
} finally {
await browser.close();
}
})();

View File

@@ -0,0 +1,109 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('1. 访问系统...');
await page.goto('http://localhost:5670');
await page.waitForTimeout(3000);
// 检查是否需要登录
if (page.url().includes('login')) {
console.log('2. 执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
await page.click('button:has-text("登录")');
await page.waitForTimeout(5000);
}
console.log('3. 刷新页面加载最新菜单...');
await page.reload();
await page.waitForTimeout(3000);
// 展开侧边栏
const isCollapsed = await page.locator('.ant-layout-sider-collapsed').count();
if (isCollapsed > 0) {
console.log(' 展开侧边栏...');
await page.click('.ant-layout-sider-trigger');
await page.waitForTimeout(1000);
}
console.log('\n4. 检查菜单结构...');
// 获取所有可见的菜单项
const menuItems = await page.locator('.ant-menu-item, .ant-menu-submenu').evaluateAll(elements => {
return elements.map(el => {
const titleEl = el.querySelector('.ant-menu-title-content');
const iconEl = el.querySelector('.ant-menu-item-icon, .ant-menu-submenu-icon');
const isSubmenu = el.classList.contains('ant-menu-submenu');
const level = el.closest('.ant-menu-sub') ? 2 : 1;
return {
text: titleEl?.textContent?.trim() || '',
hasIcon: !!iconEl,
isSubmenu,
level,
visible: window.getComputedStyle(el).display !== 'none'
};
}).filter(item => item.text && item.visible);
});
console.log('\n当前菜单结构:');
console.log('================');
menuItems.forEach((item, index) => {
const prefix = item.level === 2 ? ' └─ ' : '';
const type = item.isSubmenu ? '[父菜单]' : '[菜单项]';
const icon = item.hasIcon ? '✓' : '✗';
console.log(`${prefix}${index + 1}. ${item.text} ${type} 图标:${icon}`);
});
console.log('\n期望的菜单顺序:');
console.log('1. 记一笔 (快速记账)');
console.log('2. 交易记录 (查看所有交易)');
console.log('3. 统计分析 (各种报表)');
console.log('4. 设置 (分类/预算/标签/人员)');
console.log('5. 贷款管理');
console.log('6. 系统工具 (导入导出等)');
// 截图
await page.screenshot({ path: 'menu-structure-check.png', fullPage: true });
console.log('\n截图保存为: menu-structure-check.png');
// 点击测试
console.log('\n5. 测试菜单点击...');
// 尝试点击"记一笔"
const quickAddMenu = await page.locator('.ant-menu-item:has-text("记一笔")').count();
if (quickAddMenu > 0) {
console.log(' 找到"记一笔"菜单,点击测试...');
await page.click('.ant-menu-item:has-text("记一笔")');
await page.waitForTimeout(2000);
console.log(' 当前URL:', page.url());
} else {
console.log(' ⚠️ 未找到"记一笔"菜单');
}
// 尝试点击"交易记录"
const transMenu = await page.locator('.ant-menu-item:has-text("交易记录")').count();
if (transMenu > 0) {
console.log(' 找到"交易记录"菜单,点击测试...');
await page.click('.ant-menu-item:has-text("交易记录")');
await page.waitForTimeout(2000);
console.log(' 当前URL:', page.url());
} else {
console.log(' ⚠️ 未找到"交易记录"菜单');
}
console.log('\n✅ 检查完成!');
} catch (error) {
console.error('❌ 错误:', error.message);
await page.screenshot({ path: 'menu-error.png' });
} finally {
await page.waitForTimeout(3000);
await browser.close();
}
})();

107
temp-tests/test-check.js Normal file
View File

@@ -0,0 +1,107 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 500,
});
const page = await browser.newPage();
try {
console.log('访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
console.log('点击新建按钮...');
const createBtn = await page
.locator('button')
.filter({ hasText: '新建' })
.first();
await createBtn.click();
console.log('等待弹窗...');
await page.waitForTimeout(2000);
// 检查弹窗中的按钮
console.log('\n检查弹窗按钮...');
const modalFooterButtons = await page
.locator('.ant-modal-footer button')
.all();
console.log(`找到 ${modalFooterButtons.length} 个按钮`);
for (const [i, btn] of modalFooterButtons.entries()) {
const text = await btn.textContent();
const disabled = await btn.isDisabled();
const classes = await btn.getAttribute('class');
console.log(
`按钮 ${i + 1}: 文本="${text}", 禁用=${disabled}, class="${classes}"`,
);
}
// 填写必填字段
console.log('\n填写必填字段...');
// 1. 金额
console.log('填写金额...');
const amountInput = await page
.locator('input.ant-input-number-input')
.first();
await amountInput.clear();
await amountInput.fill('100');
// 2. 选择分类 - 使用更精确的方式
console.log('选择分类...');
// 先找到分类的选择框(在弹窗内)
const modal = await page.locator('.ant-modal-content');
const categorySelect = await modal.locator('.ant-select').nth(1);
await categorySelect.click();
await page.waitForTimeout(500);
// 选择第一个选项
const firstOption = await page
.locator('.ant-select-dropdown:visible .ant-select-item')
.first();
if (await firstOption.isVisible()) {
const optionText = await firstOption.textContent();
console.log(`选择分类: ${optionText}`);
await firstOption.click();
await page.waitForTimeout(500);
}
// 再次检查按钮状态
console.log('\n填写后再次检查按钮...');
const submitBtn = await page
.locator('.ant-modal-footer button.ant-btn-primary')
.first();
if (await submitBtn.isVisible()) {
const text = await submitBtn.textContent();
const disabled = await submitBtn.isDisabled();
console.log(`提交按钮: 文本="${text}", 禁用=${disabled}`);
if (!disabled) {
console.log('点击提交...');
await submitBtn.click();
await page.waitForTimeout(2000);
// 检查是否有消息
const successMsg = await page.locator('.ant-message-success');
const errorMsg = await page.locator('.ant-message-error');
if (await successMsg.isVisible()) {
console.log('✅ 成功提示出现');
}
if (await errorMsg.isVisible()) {
const error = await errorMsg.textContent();
console.log('❌ 错误提示:', error);
}
}
}
} catch (error) {
console.error('错误:', error.message);
} finally {
console.log('\n保持打开10秒供检查...');
await page.waitForTimeout(10_000);
await browser.close();
}
})();

View File

@@ -0,0 +1,111 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext({
// 完全清除缓存
storageState: undefined
});
const page = await context.newPage();
try {
console.log('1. 清除所有缓存,重新登录...');
// 直接访问登录页
await page.goto('http://localhost:5670/auth/login', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);
console.log('2. 执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
await page.click('button:has-text("登录")');
// 等待登录完成并跳转
await page.waitForURL('**/workspace', { timeout: 10000 }).catch(() => {
console.log(' 等待workspace页面超时继续...');
});
await page.waitForTimeout(3000);
console.log('3. 检查侧边栏状态...');
// 展开侧边栏(如果是折叠的)
const trigger = await page.locator('.ant-layout-sider-trigger').count();
if (trigger > 0) {
const isCollapsed = await page.locator('.ant-layout-sider-collapsed').count();
if (isCollapsed > 0) {
console.log(' 展开侧边栏...');
await page.click('.ant-layout-sider-trigger');
await page.waitForTimeout(1000);
}
}
console.log('\n4. 获取菜单信息...');
// 获取所有菜单项
const allMenus = await page.locator('.ant-menu .ant-menu-title-content').allTextContents();
console.log('\n所有菜单项按显示顺序:');
console.log('========================');
allMenus.forEach((text, index) => {
console.log(`${index + 1}. ${text}`);
});
// 分类检查
console.log('\n菜单分类检查:');
console.log('-------------');
const expectedMenus = [
'记一笔',
'交易记录',
'统计分析',
'设置',
'贷款管理',
'系统工具'
];
for (const menuName of expectedMenus) {
const found = allMenus.includes(menuName);
console.log(`${found ? '✅' : '❌'} ${menuName}`);
}
// 获取更详细的菜单信息
const detailedMenus = await page.locator('.ant-menu-item, .ant-menu-submenu').evaluateAll(elements => {
return elements.map(el => {
const titleEl = el.querySelector('.ant-menu-title-content');
const isActive = el.classList.contains('ant-menu-item-selected');
const isSubmenu = el.classList.contains('ant-menu-submenu');
const path = el.querySelector('a')?.getAttribute('href') || '';
return {
text: titleEl?.textContent?.trim() || '',
isActive,
isSubmenu,
path,
classes: Array.from(el.classList).join(' ')
};
}).filter(item => item.text);
});
console.log('\n详细菜单信息:');
console.log('============');
detailedMenus.forEach(menu => {
console.log(`- ${menu.text}`);
console.log(` 类型: ${menu.isSubmenu ? '父菜单' : '菜单项'}`);
if (menu.path) console.log(` 路径: ${menu.path}`);
if (menu.isActive) console.log(` 状态: 激活`);
});
// 截图
await page.screenshot({ path: 'menu-after-clear-cache.png', fullPage: true });
console.log('\n截图保存为: menu-after-clear-cache.png');
console.log('\n✅ 完成!');
} catch (error) {
console.error('❌ 错误:', error.message);
await page.screenshot({ path: 'cache-clear-error.png' });
} finally {
await page.waitForTimeout(2000);
await browser.close();
}
})();

234
temp-tests/test-complete.js Normal file
View File

@@ -0,0 +1,234 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false, // 有头模式方便观察
slowMo: 300, // 减慢速度便于观察
});
const page = await browser.newPage();
// 监听控制台
page.on('console', (msg) => {
if (msg.type() === 'error') {
console.log('[错误]', msg.text());
}
});
page.on('pageerror', (error) => {
console.log('[页面错误]', error.message);
});
try {
console.log('========== 开始测试交易管理功能 ==========\n');
// 1. 访问系统
console.log('1. 访问系统首页...');
await page.goto('http://localhost:5667');
await page.waitForTimeout(2000);
// 检查是否需要登录
if (page.url().includes('/login')) {
console.log(' 需要登录,执行登录操作...');
// 选择账号
const selectAccount = await page.locator('.ant-select').first();
if (await selectAccount.isVisible()) {
await selectAccount.click();
await page.locator('.ant-select-item[title="Admin"]').click();
await page.waitForTimeout(500);
}
// 输入用户名密码(应该自动填充)
const usernameInput = await page.locator('input[placeholder*="用户名"]');
const passwordInput = await page.locator('input[type="password"]');
const username = await usernameInput.inputValue();
const password = await passwordInput.inputValue();
if (!username) await usernameInput.fill('admin');
if (!password) await passwordInput.fill('123456');
// 处理滑块验证
const slider = await page.locator('.slider-button');
if (await slider.isVisible()) {
console.log(' 处理滑块验证...');
const box = await slider.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + 300, box.y + box.height / 2);
await page.mouse.up();
}
}
await page.waitForTimeout(500);
// 点击登录
const loginBtn = await page.locator('button[type="submit"]');
await loginBtn.click();
await page.waitForTimeout(2000);
}
console.log(' ✅ 成功进入系统\n');
// 2. 访问交易管理页面
console.log('2. 访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
// 检查页面是否正常加载
const loading = await page.locator('.ant-spin-spinning').count();
if (loading > 0) {
console.log(' ⏳ 页面还在加载中,等待...');
await page.waitForTimeout(3000);
}
// 检查表格
const table = await page.locator('.ant-table');
const tableVisible = await table.isVisible();
console.log(` 表格是否显示: ${tableVisible ? '✅ 是' : '❌ 否'}`);
if (tableVisible) {
const rows = await page.locator('.ant-table-tbody tr').count();
console.log(` 表格数据行数: ${rows}`);
}
// 检查搜索栏
const searchInput = await page.locator('input[placeholder*="关键词"]');
const searchVisible = await searchInput.isVisible();
console.log(` 搜索框是否显示: ${searchVisible ? '✅ 是' : '❌ 否'}`);
// 检查新建按钮
const createBtn = await page.locator('button:has-text("新建交易")');
const createBtnVisible = await createBtn.isVisible();
console.log(
` 新建按钮是否显示: ${createBtnVisible ? '✅ 是' : '❌ 否'}\n`,
);
// 3. 测试新建交易
if (createBtnVisible) {
console.log('3. 测试新建交易功能...');
await createBtn.click();
await page.waitForTimeout(1000);
// 检查弹窗
const modal = await page.locator('.ant-modal');
const modalVisible = await modal.isVisible();
console.log(` 弹窗是否打开: ${modalVisible ? '✅ 是' : '❌ 否'}`);
if (modalVisible) {
// 填写表单
console.log(' 填写交易表单...');
// 选择类型
const typeSelect = await page.locator('.ant-select').first();
await typeSelect.click();
await page.locator('.ant-select-item:has-text("支出")').click();
await page.waitForTimeout(300);
// 选择分类
const categorySelect = await page.locator('.ant-select').nth(1);
await categorySelect.click();
await page.waitForTimeout(500);
const categoryOptions = await page
.locator('.ant-select-dropdown:visible .ant-select-item')
.count();
console.log(` 可选分类数: ${categoryOptions}`);
if (categoryOptions > 0) {
await page
.locator('.ant-select-dropdown:visible .ant-select-item')
.first()
.click();
}
// 输入金额
const amountInput = await page
.locator('input.ant-input-number-input')
.first();
await amountInput.fill('588.88');
console.log(' 输入金额: 588.88');
// 输入描述
const descTextarea = await page.locator(
'textarea[placeholder*="描述"]',
);
if (await descTextarea.isVisible()) {
await descTextarea.fill('Playwright自动测试创建的交易');
console.log(' 输入描述: Playwright自动测试创建的交易');
}
// 提交
console.log(' 提交表单...');
const submitBtn = await page.locator(
'.ant-modal-footer button.ant-btn-primary',
);
await submitBtn.click();
await page.waitForTimeout(2000);
// 检查是否有成功提示
const successMsg = await page.locator('.ant-message-success');
const hasSuccess = await successMsg.isVisible();
console.log(
` 创建结果: ${hasSuccess ? '✅ 成功' : '⚠️ 未检测到成功消息'}`,
);
// 检查新记录
await page.waitForTimeout(1000);
const newRecord = await page.locator('td:has-text("588.88")').first();
const recordFound = await newRecord.isVisible();
console.log(` 新记录是否出现: ${recordFound ? '✅ 是' : '❌ 否'}\n`);
}
}
// 4. 测试搜索功能
if (searchVisible) {
console.log('4. 测试搜索功能...');
await searchInput.fill('测试');
await page.keyboard.press('Enter');
await page.waitForTimeout(1000);
console.log(' ✅ 搜索功能正常\n');
}
// 5. 测试API
console.log('5. 测试API接口...');
await page.goto('http://localhost:5667/finance/test-api');
await page.waitForTimeout(2000);
const apiTestBtn = await page.locator('button:has-text("测试交易API")');
if (await apiTestBtn.isVisible()) {
await apiTestBtn.click();
await page.waitForTimeout(1000);
const preContent = await page.locator('pre');
const hasApiResult = await preContent.isVisible();
console.log(
` API测试结果: ${hasApiResult ? '✅ 有返回数据' : '❌ 无数据'}\n`,
);
}
// 截图
await page.screenshot({
path: 'test-complete-success.png',
fullPage: true,
});
console.log('========== 测试完成 ==========');
console.log('\n测试总结:');
console.log('✅ 系统可以正常访问');
console.log('✅ 交易管理页面正常加载');
console.log('✅ 新建交易功能正常');
console.log('✅ 搜索功能正常');
console.log('✅ API接口正常');
console.log('\n截图已保存为: test-complete-success.png');
} catch (error) {
console.error('\n❌ 测试失败:', error.message);
await page.screenshot({ path: 'test-error.png', fullPage: true });
console.log('错误截图已保存为: test-error.png');
} finally {
console.log('\n浏览器将在5秒后关闭...');
await page.waitForTimeout(5000);
await browser.close();
}
})();

View File

@@ -0,0 +1,46 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
// 监听控制台消息
page.on('console', msg => {
if (msg.type() === 'error') {
console.log('浏览器错误:', msg.text());
}
});
// 监听页面错误
page.on('pageerror', error => {
console.log('页面错误:', error.message);
});
try {
console.log('访问分类统计页面...');
await page.goto('http://localhost:5666/finance/category-stats');
// 等待页面加载
await page.waitForTimeout(5000);
// 获取控制台错误
const errors = await page.evaluate(() => {
const errorElements = document.querySelectorAll('.error-message, .ant-result-title');
return Array.from(errorElements).map(el => el.textContent);
});
if (errors.length > 0) {
console.log('页面错误信息:', errors);
}
// 截图
await page.screenshot({ path: 'console-check.png' });
console.log('截图保存为 console-check.png');
} catch (error) {
console.error('测试失败:', error.message);
} finally {
await page.waitForTimeout(2000);
await browser.close();
}
})();

View File

@@ -0,0 +1,223 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 500,
});
const page = await browser.newPage();
// 监听所有控制台消息
page.on('console', (msg) => {
console.log(`[${msg.type()}]`, msg.text());
});
page.on('pageerror', (error) => {
console.log('[页面错误]', error.message);
});
// 监听网络请求
page.on('response', (response) => {
if (
response.url().includes('/api/finance/transaction') &&
response.status() !== 200
) {
console.log('[API错误]', response.url(), response.status());
}
});
try {
console.log('========== 测试新建交易功能 ==========\n');
// 1. 直接访问交易管理页面(开发模式会自动登录)
console.log('1. 访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
// 检查页面是否正常加载
const table = await page.locator('.ant-table').first();
if (await table.isVisible()) {
console.log(' ✅ 页面加载成功\n');
}
// 2. 查找并点击新建按钮
console.log('2. 查找新建按钮...');
// 尝试多个可能的选择器
let createBtn = await page.locator('button:has-text("新建交易")').first();
if (!(await createBtn.isVisible())) {
createBtn = await page.locator('button:has-text("新建")').first();
}
if (!(await createBtn.isVisible())) {
createBtn = await page.locator('button:has-text("添加")').first();
}
if (!(await createBtn.isVisible())) {
createBtn = await page.locator('button.ant-btn-primary').first();
}
if (await createBtn.isVisible()) {
console.log(' ✅ 找到新建按钮');
await createBtn.click();
console.log(' 点击新建按钮...');
await page.waitForTimeout(1500);
} else {
console.log(' ❌ 未找到新建按钮');
// 截图看看页面
await page.screenshot({ path: 'no-create-button.png' });
console.log(' 已保存截图: no-create-button.png');
}
// 3. 检查弹窗是否打开
console.log('\n3. 检查弹窗状态...');
const modal = await page.locator('.ant-modal').first();
const modalVisible = await modal.isVisible();
if (modalVisible) {
console.log(' ✅ 弹窗已打开');
// 获取弹窗标题
const modalTitle = await page.locator('.ant-modal-title').first();
if (await modalTitle.isVisible()) {
const title = await modalTitle.textContent();
console.log(' 弹窗标题:', title);
}
// 4. 检查表单字段
console.log('\n4. 检查表单字段...');
// 检查各个输入框
const typeSelect = await page.locator('.ant-select').nth(0);
const categorySelect = await page.locator('.ant-select').nth(1);
const amountInput = await page
.locator('input.ant-input-number-input')
.first();
const dateInput = await page.locator('.ant-picker-input input').first();
const descTextarea = await page.locator('textarea').first();
console.log(
' 类型选择器:',
(await typeSelect.isVisible()) ? '✅' : '❌',
);
console.log(
' 分类选择器:',
(await categorySelect.isVisible()) ? '✅' : '❌',
);
console.log(
' 金额输入框:',
(await amountInput.isVisible()) ? '✅' : '❌',
);
console.log(
' 日期选择器:',
(await dateInput.isVisible()) ? '✅' : '❌',
);
console.log(
' 描述输入框:',
(await descTextarea.isVisible()) ? '✅' : '❌',
);
// 5. 尝试填写表单
console.log('\n5. 填写表单...');
// 选择类型
if (await typeSelect.isVisible()) {
await typeSelect.click();
await page.waitForTimeout(500);
const expenseOption = await page
.locator('.ant-select-item:has-text("支出")')
.first();
if (await expenseOption.isVisible()) {
await expenseOption.click();
console.log(' 选择类型: 支出');
}
}
// 选择分类
if (await categorySelect.isVisible()) {
await categorySelect.click();
await page.waitForTimeout(500);
const categoryOptions = await page.locator(
'.ant-select-dropdown:visible .ant-select-item',
);
const optionCount = await categoryOptions.count();
console.log(` 可选分类数: ${optionCount}`);
if (optionCount > 0) {
await categoryOptions.first().click();
console.log(' 选择了第一个分类');
}
}
// 输入金额
if (await amountInput.isVisible()) {
await amountInput.clear();
await amountInput.fill('999.99');
console.log(' 输入金额: 999.99');
}
// 输入描述
if (await descTextarea.isVisible()) {
await descTextarea.fill('测试新建交易功能');
console.log(' 输入描述: 测试新建交易功能');
}
// 6. 提交表单
console.log('\n6. 提交表单...');
const submitBtn = await page
.locator('.ant-modal-footer button.ant-btn-primary')
.first();
if (await submitBtn.isVisible()) {
const btnText = await submitBtn.textContent();
console.log(' 提交按钮文本:', btnText);
await submitBtn.click();
console.log(' 点击提交按钮...');
await page.waitForTimeout(2000);
// 检查是否有错误提示
const errorMsg = await page.locator('.ant-message-error').first();
if (await errorMsg.isVisible()) {
const error = await errorMsg.textContent();
console.log(' ❌ 错误:', error);
}
// 检查是否有成功提示
const successMsg = await page.locator('.ant-message-success').first();
if (await successMsg.isVisible()) {
const success = await successMsg.textContent();
console.log(' ✅ 成功:', success);
}
// 检查弹窗是否关闭
const modalStillVisible = await modal.isVisible();
if (modalStillVisible) {
console.log(' ⚠️ 弹窗仍然显示');
// 可能有验证错误,截图
await page.screenshot({ path: 'form-validation-error.png' });
console.log(' 已保存截图: form-validation-error.png');
} else {
console.log(' ✅ 弹窗已关闭');
}
}
} else {
console.log(' ❌ 弹窗未打开');
// 截图看看页面状态
await page.screenshot({ path: 'no-modal.png' });
console.log(' 已保存截图: no-modal.png');
}
// 最终截图
await page.screenshot({ path: 'test-result.png', fullPage: true });
console.log('\n最终截图: test-result.png');
} catch (error) {
console.error('\n❌ 测试失败:', error.message);
console.error(error.stack);
await page.screenshot({ path: 'error.png' });
} finally {
console.log('\n========== 测试结束 ==========');
console.log('浏览器将在10秒后关闭...');
await page.waitForTimeout(10_000);
await browser.close();
}
})();

181
temp-tests/test-direct.js Normal file
View File

@@ -0,0 +1,181 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 500,
});
const page = await browser.newPage();
// 监听控制台错误
page.on('console', (msg) => {
if (msg.type() === 'error') {
console.log('[浏览器错误]', msg.text());
}
});
page.on('pageerror', (error) => {
console.log('[页面错误]', error.message);
});
try {
console.log('========== 开始测试 ==========\n');
// 1. 直接访问交易管理页面
console.log('1. 访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
// 检查URL是否跳转到登录页
const currentUrl = page.url();
console.log(' 当前URL:', currentUrl);
if (currentUrl.includes('/login')) {
console.log(' 需要登录,执行自动登录...');
// 等待页面完全加载
await page.waitForTimeout(2000);
// 输入用户名密码
const usernameInput = await page
.locator('input[placeholder*="用户名"]')
.first();
const passwordInput = await page
.locator('input[type="password"]')
.first();
if (await usernameInput.isVisible()) {
await usernameInput.fill('admin');
console.log(' 输入用户名: admin');
}
if (await passwordInput.isVisible()) {
await passwordInput.fill('123456');
console.log(' 输入密码: ******');
}
// 处理滑块验证
const slider = await page.locator('.slider-button').first();
if (await slider.isVisible()) {
console.log(' 处理滑块验证...');
const box = await slider.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + 300, box.y + box.height / 2);
await page.mouse.up();
console.log(' 滑块验证完成');
}
}
await page.waitForTimeout(1000);
// 点击登录按钮
const loginBtn = await page.locator('button:has-text("登录")').first();
if (await loginBtn.isVisible()) {
await loginBtn.click();
console.log(' 点击登录按钮');
await page.waitForTimeout(3000);
}
// 检查是否登录成功
const afterLoginUrl = page.url();
if (afterLoginUrl.includes('/login')) {
console.log(' ❌ 登录失败,仍在登录页');
} else {
console.log(' ✅ 登录成功');
// 重新访问交易管理页面
console.log('\n2. 重新访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
}
}
// 检查交易管理页面
const finalUrl = page.url();
if (finalUrl.includes('/finance/transaction')) {
console.log('\n✅ 成功进入交易管理页面');
// 等待页面加载
await page.waitForTimeout(2000);
// 检查关键元素
const table = await page.locator('.ant-table').first();
const searchBox = await page
.locator('input[placeholder*="关键词"]')
.first();
const createBtn = await page.locator('button:has-text("新建")').first();
console.log('\n页面元素检查:');
console.log(
' 表格:',
(await table.isVisible()) ? '✅ 显示' : '❌ 未显示',
);
console.log(
' 搜索框:',
(await searchBox.isVisible()) ? '✅ 显示' : '❌ 未显示',
);
console.log(
' 新建按钮:',
(await createBtn.isVisible()) ? '✅ 显示' : '❌ 未显示',
);
// 尝试新建交易
if (await createBtn.isVisible()) {
console.log('\n3. 测试新建交易...');
await createBtn.click();
await page.waitForTimeout(1500);
const modal = await page.locator('.ant-modal').first();
if (await modal.isVisible()) {
console.log(' ✅ 弹窗打开成功');
// 填写基本信息
const amountInput = await page
.locator('input.ant-input-number-input')
.first();
if (await amountInput.isVisible()) {
await amountInput.fill('99.99');
console.log(' 输入金额: 99.99');
}
// 点击确定
const submitBtn = await page
.locator('.ant-modal-footer button.ant-btn-primary')
.first();
if (await submitBtn.isVisible()) {
await submitBtn.click();
console.log(' 点击提交');
await page.waitForTimeout(2000);
}
// 检查结果
const successMsg = await page.locator('.ant-message-success').first();
if (await successMsg.isVisible()) {
console.log(' ✅ 创建成功');
} else {
console.log(' ⚠️ 未检测到成功消息');
}
}
}
// 截图
await page.screenshot({ path: 'test-success.png', fullPage: true });
console.log('\n截图已保存: test-success.png');
} else {
console.log('\n❌ 未能进入交易管理页面');
console.log('当前页面:', finalUrl);
}
} catch (error) {
console.error('\n❌ 测试出错:', error.message);
await page.screenshot({ path: 'test-error.png', fullPage: true });
console.log('错误截图已保存: test-error.png');
} finally {
console.log('\n========== 测试结束 ==========');
console.log('浏览器将在5秒后关闭...');
await page.waitForTimeout(5000);
await browser.close();
}
})();

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
temp-tests/test-error.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@@ -0,0 +1,103 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('1. 访问系统...');
await page.goto('http://localhost:5670');
await page.waitForTimeout(3000);
// 如果需要登录
if (page.url().includes('login')) {
console.log('2. 登录...');
const usernameInput = await page.locator('input[type="text"]').first();
const passwordInput = await page.locator('input[type="password"]').first();
const loginButton = await page.locator('button[type="submit"]').first();
await usernameInput.fill('admin');
await passwordInput.fill('111111');
await loginButton.click();
await page.waitForTimeout(5000);
}
console.log('3. 展开侧边栏...');
// 点击汉堡菜单图标展开侧边栏
const menuToggle = await page.locator('[class*="menu-toggle"], [class*="sider-trigger"], .ant-layout-sider-trigger, [aria-label*="menu"]').first();
if (await menuToggle.count() > 0) {
await menuToggle.click();
console.log(' 已点击展开按钮');
await page.waitForTimeout(2000);
}
// 再次尝试其他可能的展开按钮
const possibleTriggers = [
'button:has-text("☰")',
'button[class*="hamburger"]',
'[class*="collapsed"] button',
'.ant-layout-sider-collapsed + .ant-layout-sider-trigger',
'.vben-layout-header__menu-toggle'
];
for (const selector of possibleTriggers) {
const trigger = await page.locator(selector).first();
if (await trigger.count() > 0 && await trigger.isVisible()) {
console.log(` 找到展开按钮: ${selector}`);
await trigger.click();
await page.waitForTimeout(2000);
break;
}
}
console.log('4. 获取展开后的菜单...');
// 获取所有菜单项文本
const menuTexts = await page.locator('.ant-menu-title-content, [class*="menu-item"] span').allTextContents();
console.log('\n当前菜单项:');
console.log('===========');
menuTexts.forEach((text, i) => {
if (text.trim()) {
console.log(`${i+1}. ${text}`);
}
});
// 尝试获取带图标的菜单项
const menuItems = await page.locator('.ant-menu-item, .ant-menu-submenu').evaluateAll(items => {
return items.map(item => {
const text = item.textContent?.trim() || '';
const icon = item.querySelector('[class*="icon"]');
const hasIcon = !!icon;
return { text, hasIcon };
}).filter(item => item.text);
});
console.log('\n菜单详情:');
console.log('=========');
menuItems.forEach((item, i) => {
console.log(`${i+1}. ${item.text} ${item.hasIcon ? '[有图标]' : ''}`);
});
// 检查特定菜单
const targetMenus = ['记一笔', '交易记录', '统计分析', '设置', '贷款管理', '系统工具'];
console.log('\n目标菜单检查:');
console.log('============');
for (const menu of targetMenus) {
const found = menuTexts.some(text => text.includes(menu)) ||
menuItems.some(item => item.text.includes(menu));
console.log(`${found ? '✅' : '❌'} ${menu}`);
}
// 截图
await page.screenshot({ path: 'expanded-menu.png', fullPage: true });
console.log('\n截图保存: expanded-menu.png');
} catch (error) {
console.error('错误:', error.message);
} finally {
await page.waitForTimeout(3000);
await browser.close();
}
})();

View File

@@ -0,0 +1,43 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('1. 访问新端口的系统...');
await page.goto('http://localhost:5670');
await page.waitForTimeout(3000);
// 检查是否需要登录
if (page.url().includes('login')) {
console.log('2. 执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
await page.click('button:has-text("登录")');
await page.waitForTimeout(5000);
}
console.log('3. 检查菜单结构...');
// 获取所有菜单文本
const menuTexts = await page.locator('.ant-menu-title-content').allTextContents();
console.log('\n当前菜单项:');
menuTexts.forEach((text, index) => {
console.log(` ${index + 1}. ${text}`);
});
// 截图
await page.screenshot({ path: 'final-menu-structure.png', fullPage: true });
console.log('\n截图保存为: final-menu-structure.png');
console.log('\n✅ 完成!');
} catch (error) {
console.error('❌ 错误:', error.message);
await page.screenshot({ path: 'final-error.png' });
} finally {
await page.waitForTimeout(2000);
await browser.close();
}
})();

View File

@@ -0,0 +1,111 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 300,
});
const page = await browser.newPage();
try {
console.log('========== 最终测试:新建交易功能 ==========\n');
// 1. 访问页面
console.log('1. 访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
console.log(' ✅ 页面加载成功');
// 2. 点击新建
console.log('\n2. 点击新建按钮...');
const createBtn = await page
.locator('button')
.filter({ hasText: '新建' })
.first();
await createBtn.click();
await page.waitForTimeout(1500);
console.log(' ✅ 弹窗打开成功');
// 3. 填写表单
console.log('\n3. 填写交易信息...');
// 金额
const amountInput = await page
.locator('input.ant-input-number-input')
.first();
await amountInput.clear();
await amountInput.fill('2888.88');
console.log(' ✅ 金额: 2888.88');
// 选择分类
const modal = await page.locator('.ant-modal-content');
const categorySelect = await modal.locator('.ant-select').nth(1);
await categorySelect.click();
await page.waitForTimeout(500);
const firstOption = await page
.locator('.ant-select-dropdown:visible .ant-select-item')
.first();
const categoryName = await firstOption.textContent();
await firstOption.click();
console.log(` ✅ 分类: ${categoryName}`);
// 描述
const descInput = await page.locator('textarea').first();
await descInput.fill('新建交易测试 - 功能正常');
console.log(' ✅ 描述: 新建交易测试 - 功能正常');
// 4. 提交
console.log('\n4. 提交交易...');
const submitBtn = await page
.locator('.ant-modal-footer button.ant-btn-primary')
.first();
await submitBtn.click();
await page.waitForTimeout(2000);
// 5. 验证结果
console.log('\n5. 验证结果...');
// 检查成功消息
const successMsg = await page.locator('.ant-message-success').first();
const hasSuccess = await successMsg.isVisible();
if (hasSuccess) {
const msg = await successMsg.textContent();
console.log(` ✅ 成功提示: ${msg}`);
}
// 检查弹窗关闭
const modal2 = await page.locator('.ant-modal').first();
const modalClosed = !(await modal2.isVisible());
if (modalClosed) {
console.log(' ✅ 弹窗已关闭');
}
// 查找新记录
await page.waitForTimeout(1000);
const newRecord = await page.locator('td:has-text("2888.88")').first();
const recordFound = await newRecord.isVisible();
if (recordFound) {
console.log(' ✅ 新记录已创建');
}
// 截图
await page.screenshot({ path: 'success.png', fullPage: true });
console.log('\n========== 测试结果 ==========');
console.log('🎉 新建交易功能完全正常!');
console.log('✅ 弹窗打开正常');
console.log('✅ 表单填写正常');
console.log('✅ 数据提交成功');
console.log('✅ 新记录创建成功');
console.log('\n截图已保存: success.png');
} catch (error) {
console.error('\n❌ 测试失败:', error.message);
await page.screenshot({ path: 'error.png' });
} finally {
console.log('\n浏览器将在5秒后关闭...');
await page.waitForTimeout(5000);
await browser.close();
}
})();

View File

@@ -0,0 +1,59 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext({
// 清除所有存储
storageState: undefined
});
const page = await context.newPage();
try {
console.log('1. 清除缓存并访问系统...');
// 先访问登录页
await page.goto('http://localhost:5666/auth/login');
await page.waitForTimeout(2000);
console.log('2. 执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
await page.click('button:has-text("登录")');
// 等待跳转
await page.waitForTimeout(3000);
console.log('3. 刷新页面以加载新菜单...');
await page.reload();
await page.waitForTimeout(3000);
console.log('\n4. 检查新菜单结构...');
// 展开所有折叠的菜单
const collapsedMenus = await page.locator('.ant-layout-sider-collapsed').count();
if (collapsedMenus > 0) {
console.log(' 展开侧边栏...');
await page.click('.ant-layout-sider-trigger');
await page.waitForTimeout(1000);
}
// 截图当前菜单状态
await page.screenshot({ path: 'current-menu-state.png', fullPage: true });
console.log(' 当前菜单截图: current-menu-state.png');
// 检查菜单文本
const menuTexts = await page.locator('.ant-menu-title-content').allTextContents();
console.log('\n5. 当前显示的菜单项:');
menuTexts.forEach((text, index) => {
console.log(` ${index + 1}. ${text}`);
});
console.log('\n✅ 检查完成!');
} catch (error) {
console.error('❌ 测试失败:', error.message);
await page.screenshot({ path: 'reload-error.png' });
} finally {
await browser.close();
}
})();

View File

@@ -0,0 +1,88 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('1. 访问系统...');
await page.goto('http://localhost:5666');
await page.waitForTimeout(3000);
// 检查是否需要登录
if (page.url().includes('login')) {
console.log('2. 执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
await page.click('button:has-text("登录")');
await page.waitForTimeout(3000);
}
console.log('\n3. 检查新菜单结构...');
// 检查一级菜单是否存在
const menuItems = [
{ text: '仪表板', exists: false },
{ text: '记一笔', exists: false },
{ text: '交易记录', exists: false },
{ text: '统计分析', exists: false },
{ text: '设置', exists: false },
{ text: '贷款管理', exists: false },
{ text: '系统工具', exists: false }
];
for (const item of menuItems) {
const menuItem = await page.locator(`.ant-menu-item:has-text("${item.text}"), .ant-menu-submenu:has-text("${item.text}")`).count();
item.exists = menuItem > 0;
console.log(` - ${item.text}: ${item.exists ? '✅' : '❌'}`);
}
console.log('\n4. 测试"记一笔"快速记账...');
const quickAddMenu = page.locator('.ant-menu-item:has-text("记一笔")');
if (await quickAddMenu.count() > 0) {
await quickAddMenu.click();
await page.waitForTimeout(2000);
// 检查是否弹出了新建交易窗口
const modalVisible = await page.locator('.ant-modal').isVisible();
console.log(` - 新建交易窗口: ${modalVisible ? '✅ 已弹出' : '❌ 未弹出'}`);
if (modalVisible) {
// 关闭弹窗
await page.keyboard.press('Escape');
await page.waitForTimeout(1000);
}
} else {
console.log(' - ❌ 未找到"记一笔"菜单');
}
console.log('\n5. 检查"统计分析"子菜单...');
const statsMenu = page.locator('.ant-menu-submenu:has-text("统计分析")');
if (await statsMenu.count() > 0) {
await statsMenu.click();
await page.waitForTimeout(1000);
const subMenus = ['分类统计', '趋势分析', '月度报表', '年度总结'];
for (const subMenu of subMenus) {
const exists = await page.locator(`.ant-menu-item:has-text("${subMenu}")`).count() > 0;
console.log(` - ${subMenu}: ${exists ? '✅' : '❌'}`);
}
} else {
console.log(' - ❌ 未找到"统计分析"菜单');
}
console.log('\n6. 检查是否去掉了"财务管理"二级菜单...');
const financeMenu = await page.locator('.ant-menu-submenu:has-text("财务管理")').count();
console.log(` - 财务管理菜单: ${financeMenu === 0 ? '✅ 已移除' : '❌ 仍存在'}`);
// 截图
await page.screenshot({ path: 'new-menu-structure.png', fullPage: true });
console.log('\n✅ 测试完成!截图保存为: new-menu-structure.png');
} catch (error) {
console.error('❌ 测试失败:', error.message);
await page.screenshot({ path: 'menu-test-error.png' });
} finally {
await browser.close();
}
})();

110
temp-tests/test-new-ui.js Normal file
View File

@@ -0,0 +1,110 @@
const { chromium } = require('@playwright/test');
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext({
viewport: { width: 1400, height: 900 }
});
const page = await context.newPage();
try {
console.log('1. 访问系统登录页面...');
await page.goto('http://localhost:5666/', { waitUntil: 'networkidle' });
console.log('2. 执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
// 处理可能的滑块验证
const slider = await page.$('.ant-modal-wrap');
if (slider) {
console.log('检测到滑块验证,处理中...');
await page.waitForTimeout(500);
const sliderButton = await page.$('.slider-button');
if (sliderButton) {
const box = await sliderButton.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + 260, box.y + box.height / 2, { steps: 10 });
await page.mouse.up();
}
}
await page.waitForTimeout(500);
}
await page.click('button:has-text("登录")');
await page.waitForTimeout(2000);
console.log('3. 导航到交易管理页面...');
// 点击财务管理菜单
await page.click('text=财务管理');
await page.waitForTimeout(500);
// 点击交易管理
await page.click('a:has-text("交易管理")');
await page.waitForTimeout(2000);
console.log('4. 打开新建交易表单...');
await page.click('button:has-text("新建")');
await page.waitForTimeout(1000);
console.log('5. 测试平铺按钮UI...');
// 测试交易类型切换
console.log(' - 测试交易类型按钮组...');
await page.click('label:has-text("💸 支出")');
await page.waitForTimeout(500);
await page.click('label:has-text("💰 收入")');
await page.waitForTimeout(500);
// 测试分类按钮
console.log(' - 测试分类平铺按钮...');
const categoryButtons = await page.$$('button span:has-text("工资")');
if (categoryButtons.length > 0) {
await categoryButtons[0].click();
console.log(' 选择了"工资"分类');
}
// 测试货币类型
console.log(' - 测试货币类型按钮组...');
await page.click('label:has-text("$ 美元")');
await page.waitForTimeout(500);
await page.click('label:has-text("฿ 泰铢")');
await page.waitForTimeout(500);
await page.click('label:has-text("¥ 人民币")');
await page.waitForTimeout(500);
// 测试状态按钮
console.log(' - 测试状态按钮组...');
await page.click('label:has-text("⏳ 待处理")');
await page.waitForTimeout(500);
await page.click('label:has-text("✅ 已完成")');
await page.waitForTimeout(500);
// 输入金额测试
console.log('6. 输入测试数据...');
await page.fill('.transaction-amount-input input', '1000');
// 截图保存
console.log('7. 截图保存修改后的界面...');
await page.screenshot({
path: 'transaction-form-new-ui.png',
fullPage: false
});
console.log('✅ 测试完成新的平铺按钮UI效果良好');
console.log(' - 交易类型使用了大按钮组,带图标');
console.log(' - 分类使用了平铺按钮,显示图标和名称');
console.log(' - 货币类型使用了按钮组,更直观');
console.log(' - 状态也改为了按钮组,带表情图标');
console.log('\n截图已保存到: transaction-form-new-ui.png');
} catch (error) {
console.error('测试过程中出错:', error);
await page.screenshot({ path: 'transaction-form-error.png' });
}
await browser.close();
})();

View File

@@ -0,0 +1,64 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('访问分类统计页面...');
await page.goto('http://localhost:5666/finance/category-stats');
await page.waitForTimeout(5000);
// 截图当前状态
await page.screenshot({ path: 'current-state.png', fullPage: true });
console.log('\n当前页面截图: current-state.png');
console.log('\n测试快速日期选择按钮...');
// 获取所有Radio.Group
const quickDateGroup = page.locator('.ant-radio-group').nth(0); // 第一个是快速日期选择
// 检查"本月"是否默认选中
const monthChecked = await quickDateGroup.locator('.ant-radio-button-wrapper-checked').filter({ hasText: '本月' }).count();
console.log('1. 本月按钮默认选中:', monthChecked > 0 ? '✅' : '❌');
// 点击"本年"
await quickDateGroup.locator('.ant-radio-button-wrapper').filter({ hasText: '本年' }).click();
await page.waitForTimeout(2000);
const yearChecked = await quickDateGroup.locator('.ant-radio-button-wrapper-checked').filter({ hasText: '本年' }).count();
console.log('2. 切换到本年:', yearChecked > 0 ? '✅' : '❌');
// 点击"今天"
await quickDateGroup.locator('.ant-radio-button-wrapper').filter({ hasText: '今天' }).click();
await page.waitForTimeout(2000);
const todayChecked = await quickDateGroup.locator('.ant-radio-button-wrapper-checked').filter({ hasText: '今天' }).count();
console.log('3. 切换到今天:', todayChecked > 0 ? '✅' : '❌');
console.log('\n测试图表切换...');
// 获取图表切换按钮组 (第三个Radio.Group)
const chartGroup = page.locator('.ant-radio-group').nth(2);
// 点击柱状图
await chartGroup.locator('.ant-radio-button-wrapper').filter({ hasText: '柱状图' }).click();
await page.waitForTimeout(3000);
await page.screenshot({ path: 'bar-chart-view.png' });
console.log('4. 柱状图视图: bar-chart-view.png');
// 点击趋势图
await chartGroup.locator('.ant-radio-button-wrapper').filter({ hasText: '趋势图' }).click();
await page.waitForTimeout(3000);
await page.screenshot({ path: 'trend-chart-view.png' });
console.log('5. 趋势图视图: trend-chart-view.png');
console.log('\n✅ 测试完成!');
} catch (error) {
console.error('\n❌ 错误:', error.message);
await page.screenshot({ path: 'error-state.png' });
} finally {
await browser.close();
}
})();

BIN
temp-tests/test-result.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

View File

@@ -0,0 +1,4 @@
{
"status": "failed",
"failedTests": []
}

View File

@@ -0,0 +1,56 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('访问系统...');
await page.goto('http://localhost:5670');
// 等待页面加载
await page.waitForTimeout(5000);
// 尝试获取当前URL
console.log('当前URL:', page.url());
// 如果在登录页,执行登录
if (page.url().includes('login')) {
console.log('需要登录...');
// 等待登录表单出现
await page.waitForSelector('input[type="text"]', { timeout: 5000 });
// 使用更通用的选择器
const usernameInput = await page.locator('input[type="text"]').first();
const passwordInput = await page.locator('input[type="password"]').first();
const loginButton = await page.locator('button[type="submit"]').first();
await usernameInput.fill('admin');
await passwordInput.fill('111111');
await loginButton.click();
await page.waitForTimeout(5000);
}
console.log('检查菜单...');
// 获取所有菜单文本
const menuTexts = await page.locator('.ant-menu-title-content').allTextContents();
console.log('\n当前菜单:');
menuTexts.forEach((text, i) => {
console.log(`${i+1}. ${text}`);
});
// 截图
await page.screenshot({ path: 'simple-menu-test.png', fullPage: true });
console.log('\n截图: simple-menu-test.png');
} catch (error) {
console.error('错误:', error.message);
} finally {
await page.waitForTimeout(3000);
await browser.close();
}
})();

51
temp-tests/test-simple.js Normal file
View File

@@ -0,0 +1,51 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 500,
});
const page = await browser.newPage();
try {
console.log('访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
console.log('点击新建按钮...');
const createBtn = await page
.locator('button')
.filter({ hasText: '新建' })
.first();
await createBtn.click();
console.log('等待弹窗...');
await page.waitForTimeout(2000);
console.log('填写金额...');
const amountInput = await page
.locator('input.ant-input-number-input')
.first();
await amountInput.clear();
await amountInput.fill('100');
console.log('点击提交...');
const submitBtn = await page
.locator('button')
.filter({ hasText: '确定' })
.first();
await submitBtn.click();
console.log('等待结果...');
await page.waitForTimeout(3000);
console.log('测试完成!');
} catch (error) {
console.error('错误:', error.message);
} finally {
console.log('浏览器将保持打开10秒请手动检查...');
await page.waitForTimeout(10_000);
await browser.close();
}
})();

View File

@@ -0,0 +1,86 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('1. 访问分类统计页面...');
await page.goto('http://localhost:5666/finance/category-stats');
await page.waitForTimeout(5000); // 给更多时间加载
// 检查是否需要登录
if (page.url().includes('login')) {
console.log('需要登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
await page.click('button:has-text("登录")');
await page.waitForTimeout(3000);
await page.goto('http://localhost:5666/finance/category-stats');
await page.waitForTimeout(5000);
}
console.log('\n2. 检查页面元素...');
// 等待页面完全加载
await page.waitForSelector('.ant-card', { timeout: 10000 });
// 检查快速选择按钮组
const radioGroup = await page.locator('.ant-radio-group').first().isVisible();
console.log(' - 快速选择按钮组:', radioGroup ? '✓' : '✗');
// 检查选中状态使用Ant Design的选中类
const checkedButton = await page.locator('.ant-radio-button-wrapper-checked').textContent();
console.log(' - 当前选中:', checkedButton || '无');
console.log('\n3. 测试快速日期切换...');
// 点击"本年"
const yearButton = page.locator('.ant-radio-button-wrapper').filter({ hasText: '本年' });
await yearButton.click();
await page.waitForTimeout(2000);
const yearChecked = await page.locator('.ant-radio-button-wrapper-checked').filter({ hasText: '本年' }).count();
console.log(' - 本年按钮选中:', yearChecked > 0 ? '✓' : '✗');
// 点击"今天"
const todayButton = page.locator('.ant-radio-button-wrapper').filter({ hasText: '今天' });
await todayButton.click();
await page.waitForTimeout(2000);
const todayChecked = await page.locator('.ant-radio-button-wrapper-checked').filter({ hasText: '今天' }).count();
console.log(' - 今天按钮选中:', todayChecked > 0 ? '✓' : '✗');
console.log('\n4. 测试图表切换...');
// 切换到柱状图
await page.locator('.ant-radio-button-wrapper').filter({ hasText: '柱状图' }).click();
await page.waitForTimeout(3000);
await page.screenshot({ path: 'test-bar-chart.png' });
console.log(' - 柱状图截图: test-bar-chart.png');
// 切换到趋势图
await page.locator('.ant-radio-button-wrapper').filter({ hasText: '趋势图' }).click();
await page.waitForTimeout(3000);
await page.screenshot({ path: 'test-trend-chart.png' });
console.log(' - 趋势图截图: test-trend-chart.png');
// 切换到表格视图
await page.locator('.ant-radio-button-wrapper').filter({ hasText: '表格' }).click();
await page.waitForTimeout(2000);
const tableVisible = await page.locator('.ant-table').isVisible();
console.log(' - 表格视图:', tableVisible ? '✓' : '✗');
// 最终全页截图
await page.screenshot({ path: 'category-stats-final.png', fullPage: true });
console.log('\n✅ 所有测试完成!');
} catch (error) {
console.error('❌ 测试出错:', error.message);
await page.screenshot({ path: 'test-error-final.png' });
} finally {
await page.waitForTimeout(2000);
await browser.close();
}
})();

View File

@@ -0,0 +1,53 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
console.log('1. 直接访问分类统计页面使用已登录的session...');
await page.goto('http://localhost:5666/finance/category-stats', { waitUntil: 'networkidle' });
// 等待一下让页面完全加载
await page.waitForTimeout(3000);
// 检查是否在登录页面
const currentUrl = page.url();
console.log('当前URL:', currentUrl);
if (currentUrl.includes('login')) {
console.log('2. 需要登录,执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
await page.click('button:has-text("登录")');
// 等待跳转
await page.waitForTimeout(2000);
// 重新访问分类统计页面
await page.goto('http://localhost:5666/finance/category-stats', { waitUntil: 'networkidle' });
await page.waitForTimeout(2000);
}
// 截图
await page.screenshot({ path: 'category-stats-page.png', fullPage: true });
console.log('页面截图已保存为 category-stats-page.png');
// 检查页面标题或内容
const pageContent = await page.content();
if (pageContent.includes('总收入') || pageContent.includes('总支出')) {
console.log('✅ 分类统计页面加载成功!');
} else if (pageContent.includes('error') || pageContent.includes('Error')) {
console.log('❌ 页面有错误');
} else {
console.log('⚠️ 页面内容未知,请查看截图');
}
} catch (error) {
console.error('测试失败:', error.message);
await page.screenshot({ path: 'error-screenshot.png' });
} finally {
await browser.close();
}
})();

View File

@@ -0,0 +1,115 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 300,
});
const page = await browser.newPage();
// 只监听错误
page.on('pageerror', (error) => {
console.log('[页面错误]', error.message);
});
try {
console.log('========== 测试新建交易 ==========\n');
// 1. 访问页面
console.log('1. 访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
// 2. 点击新建
console.log('2. 点击新建按钮...');
const createBtn = await page
.locator('button')
.filter({ hasText: '新建' })
.first();
await createBtn.click();
await page.waitForTimeout(1500);
// 3. 填写表单
console.log('3. 填写交易信息...');
// 金额
const amountInput = await page
.locator('input.ant-input-number-input')
.first();
await amountInput.clear();
await amountInput.fill('888.88');
console.log(' 金额: 888.88');
// 选择分类
const categorySelect = await page.locator('.ant-select').nth(1);
await categorySelect.click();
await page.waitForTimeout(500);
const categoryOption = await page
.locator('.ant-select-dropdown:visible .ant-select-item')
.first();
if (await categoryOption.isVisible()) {
await categoryOption.click();
console.log(' 分类: 已选择');
}
// 描述
const descInput = await page.locator('textarea').first();
if (await descInput.isVisible()) {
await descInput.fill(`测试交易 - ${new Date().toLocaleTimeString()}`);
console.log(' 描述: 已填写');
}
// 4. 提交
console.log('4. 提交交易...');
const submitBtn = await page
.locator('.ant-modal-footer button.ant-btn-primary')
.first();
await submitBtn.click();
await page.waitForTimeout(2000);
// 5. 检查结果
console.log('5. 检查结果...');
// 检查成功消息
const successMsg = await page.locator('.ant-message-success').first();
const hasSuccess = await successMsg.isVisible();
// 检查弹窗是否关闭
const modal = await page.locator('.ant-modal').first();
const modalClosed = !(await modal.isVisible());
// 检查新记录
await page.waitForTimeout(1000);
const newRecord = await page.locator('td:has-text("888.88")').first();
const recordFound = await newRecord.isVisible();
console.log('\n========== 测试结果 ==========');
console.log(`✅ 弹窗打开: 成功`);
console.log(
`${hasSuccess ? '✅' : '❌'} 成功提示: ${hasSuccess ? '显示' : '未显示'}`,
);
console.log(
`${modalClosed ? '✅' : '❌'} 弹窗关闭: ${modalClosed ? '已关闭' : '未关闭'}`,
);
console.log(
`${recordFound ? '✅' : '❌'} 新记录: ${recordFound ? '已创建' : '未找到'}`,
);
if (hasSuccess && modalClosed && recordFound) {
console.log('\n🎉 新建交易功能正常!');
} else {
console.log('\n⚠ 新建交易功能存在问题');
await page.screenshot({ path: 'transaction-issue.png' });
console.log('已保存截图: transaction-issue.png');
}
} catch (error) {
console.error('\n❌ 测试失败:', error.message);
await page.screenshot({ path: 'error.png' });
} finally {
console.log('\n浏览器将在5秒后关闭...');
await page.waitForTimeout(5000);
await browser.close();
}
})();

View File

@@ -0,0 +1,127 @@
const { chromium } = require('@playwright/test');
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext({
viewport: { width: 1400, height: 900 }
});
const page = await context.newPage();
try {
console.log('1. 访问系统登录页面...');
await page.goto('http://localhost:5666/', { waitUntil: 'networkidle' });
console.log('2. 执行登录...');
await page.fill('input[placeholder*="账号"]', 'admin');
await page.fill('input[placeholder*="密码"]', '111111');
// 处理可能的滑块验证
await page.waitForTimeout(500);
const slider = await page.$('.ant-modal-wrap');
if (slider) {
console.log('检测到滑块验证,处理中...');
const sliderButton = await page.$('.slider-button');
if (sliderButton) {
const box = await sliderButton.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + 260, box.y + box.height / 2, { steps: 10 });
await page.mouse.up();
}
}
await page.waitForTimeout(500);
}
await page.click('button:has-text("登录")');
await page.waitForTimeout(2000);
console.log('3. 导航到交易管理页面...');
await page.click('text=财务管理');
await page.waitForTimeout(500);
await page.click('a:has-text("交易管理")');
await page.waitForTimeout(2000);
console.log('4. 检查当前列表的第一条记录...');
const firstRowBefore = await page.locator('tbody tr').first();
const firstDateBefore = await firstRowBefore.locator('td:nth-child(2)').textContent();
console.log(' 当前第一条记录的日期:', firstDateBefore);
console.log('5. 创建新交易...');
await page.click('button:has-text("新建")');
await page.waitForTimeout(1000);
// 选择收入类型
await page.click('label:has-text("💰 收入")');
await page.waitForTimeout(300);
// 输入金额
await page.fill('.transaction-amount-input input', '5000');
// 选择分类(假设有工资分类)
const salaryButton = await page.$('button span:has-text("工资")');
if (salaryButton) {
await salaryButton.click();
} else {
// 如果没有工资分类,选择第一个可用分类
const firstCategory = await page.$('.ant-form-item:has-text("分类") button:not(:has-text("添加"))');
if (firstCategory) {
await firstCategory.click();
}
}
// 设置今天的日期
const today = new Date().toISOString().split('T')[0];
console.log(' 设置日期为今天:', today);
// 填写描述
await page.fill('textarea[placeholder*="描述"]', `测试交易 - ${new Date().toLocaleTimeString()}`);
console.log('6. 提交新交易...');
await page.click('button:has-text("确定")');
await page.waitForTimeout(2000);
console.log('7. 验证新交易是否在第一页第一条...');
const firstRowAfter = await page.locator('tbody tr').first();
const firstDateAfter = await firstRowAfter.locator('td:nth-child(2)').textContent();
const firstDescAfter = await firstRowAfter.locator('td:nth-child(8)').textContent();
console.log(' 新列表第一条记录的日期:', firstDateAfter);
console.log(' 新列表第一条记录的描述:', firstDescAfter);
// 检查是否包含刚才创建的测试交易
if (firstDescAfter && firstDescAfter.includes('测试交易')) {
console.log('✅ 测试成功!新创建的交易显示在第一页第一条');
} else {
console.log('⚠️ 新交易可能不在第一条,让我检查前几条...');
// 检查前5条记录
for (let i = 0; i < 5; i++) {
const row = await page.locator(`tbody tr:nth-child(${i + 1})`);
const desc = await row.locator('td:nth-child(8)').textContent();
if (desc && desc.includes('测试交易')) {
console.log(` 找到了!新交易在第 ${i + 1}`);
break;
}
}
}
console.log('\n📊 排序测试结果:');
console.log(' - 默认按日期倒序排序 ✅');
console.log(' - 新交易自动跳转到第一页 ✅');
console.log(' - 最新的交易显示在最前面 ✅');
// 截图保存
await page.screenshot({
path: 'transaction-order-test.png',
fullPage: false
});
console.log('\n截图已保存到: transaction-order-test.png');
} catch (error) {
console.error('测试过程中出错:', error);
await page.screenshot({ path: 'transaction-order-error.png' });
}
await browser.close();
})();

View File

@@ -0,0 +1,99 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 500,
});
const page = await browser.newPage();
// 监听控制台消息
page.on('console', (msg) => {
console.log(`[${msg.type()}]`, msg.text());
});
// 监听页面错误
page.on('pageerror', (error) => {
console.log('[PAGE ERROR]', error.message);
});
try {
console.log('1. 访问系统...');
await page.goto('http://localhost:5667');
await page.waitForTimeout(2000);
console.log('2. 测试API页面...');
await page.goto('http://localhost:5667/finance/test-api');
await page.waitForTimeout(2000);
// 测试分类API
console.log('3. 测试分类API...');
const categoryBtn = await page.locator('button:has-text("测试分类API")');
await categoryBtn.click();
await page.waitForTimeout(2000);
// 检查结果
const preElement = await page.locator('pre');
if (await preElement.isVisible()) {
const content = await preElement.textContent();
console.log('分类API结果:', `${content?.slice(0, 100)}...`);
}
// 测试交易页面
console.log('4. 访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
// 检查是否还在加载
const spinners = await page.locator('.ant-spin').count();
console.log(`找到 ${spinners} 个加载指示器`);
// 检查表格是否加载
const table = await page.locator('.ant-table');
if (await table.isVisible()) {
console.log('✅ 表格已加载');
// 统计行数
const rows = await page.locator('.ant-table-tbody tr').count();
console.log(`表格中有 ${rows} 行数据`);
} else {
console.log('❌ 表格未加载');
}
// 检查新建按钮
const createBtn = await page.locator('button:has-text("新建交易")');
if (await createBtn.isVisible()) {
console.log('✅ 新建交易按钮存在');
// 点击新建按钮
await createBtn.click();
await page.waitForTimeout(1000);
// 检查弹窗
const modal = await page.locator('.ant-modal');
if (await modal.isVisible()) {
console.log('✅ 新建交易弹窗已打开');
// 关闭弹窗
await page.locator('.ant-modal-close').click();
}
}
// 截图
await page.screenshot({
path: 'transaction-page-test.png',
fullPage: true,
});
console.log('截图已保存');
console.log('\n测试完成');
} catch (error) {
console.error('测试失败:', error);
await page.screenshot({ path: 'test-error.png', fullPage: true });
} finally {
await page.waitForTimeout(5000);
await browser.close();
console.log('浏览器已关闭');
}
})();

View File

@@ -0,0 +1,117 @@
import { chromium } from 'playwright';
(async () => {
// 启动浏览器
const browser = await chromium.launch({
headless: false, // 使用有头模式方便观察
slowMo: 500, // 减慢操作速度,方便观察
});
const context = await browser.newContext({
viewport: { width: 1280, height: 720 },
});
const page = await context.newPage();
try {
console.log('1. 访问系统...');
await page.goto('http://localhost:5667');
// 等待页面加载完成(通过等待某个元素出现)
await page.waitForTimeout(3000);
// 检查是否已自动登录
const url = page.url();
console.log('当前URL:', url);
if (url.includes('/login')) {
console.log('需要登录,执行登录操作...');
// 如果还在登录页,说明自动登录没生效
await page.waitForTimeout(1000);
}
// 导航到交易管理页面
console.log('2. 导航到交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(2000);
// 点击新建按钮
console.log('3. 点击新建交易按钮...');
const createButton = await page
.locator('button:has-text("新建交易")')
.first();
await createButton.click();
await page.waitForTimeout(1000);
// 填写表单
console.log('4. 填写交易表单...');
// 选择交易类型(支出)
await page.locator('.ant-select').first().click();
await page.locator('.ant-select-item:has-text("支出")').click();
await page.waitForTimeout(500);
// 选择分类(等待分类加载)
console.log(' 选择分类...');
await page.locator('.ant-select').nth(1).click();
await page.waitForTimeout(500);
const categoryOption = await page.locator('.ant-select-item').first();
if (await categoryOption.isVisible()) {
await categoryOption.click();
}
// 输入金额
console.log(' 输入金额...');
await page.locator('input.ant-input-number-input').first().fill('299.99');
// 选择货币
console.log(' 选择货币...');
await page.locator('.ant-select').nth(2).click();
await page.locator('.ant-select-item:has-text("CNY")').click();
// 输入项目名称
console.log(' 输入项目名称...');
const projectInput = await page.locator('input[placeholder*="项目"]');
await projectInput.fill('测试项目');
// 输入描述
console.log(' 输入描述...');
const descTextarea = await page.locator('textarea[placeholder*="描述"]');
await descTextarea.fill('这是通过Playwright自动测试创建的交易记录');
// 提交表单
console.log('5. 提交表单...');
await page.locator('.ant-modal-footer button.ant-btn-primary').click();
// 等待提交完成
await page.waitForTimeout(2000);
// 检查是否有成功提示
const successMessage = await page.locator('.ant-message-success');
if (await successMessage.isVisible()) {
console.log('✅ 创建成功!');
} else {
console.log('⚠️ 未检测到成功消息,检查页面状态...');
}
// 验证新记录是否出现在列表中
console.log('6. 验证新记录是否在列表中...');
const newRecord = await page.locator('text=测试项目').first();
if (await newRecord.isVisible()) {
console.log('✅ 新记录已出现在列表中!');
} else {
console.log('⚠️ 未在列表中找到新记录');
}
console.log('\n测试完成保持浏览器打开10秒供查看...');
await page.waitForTimeout(10_000);
} catch (error) {
console.error('测试失败:', error);
// 截图保存错误状态
await page.screenshot({ path: 'test-error.png', fullPage: true });
console.log('错误截图已保存为 test-error.png');
} finally {
await browser.close();
console.log('浏览器已关闭');
}
})();

View File

@@ -0,0 +1,192 @@
import { chromium } from 'playwright';
(async () => {
const browser = await chromium.launch({
headless: false,
slowMo: 300,
});
const page = await browser.newPage();
// 监听控制台
page.on('console', (msg) => {
if (msg.type() === 'error') {
console.log('[错误]', msg.text());
}
});
try {
console.log('========== 测试交易管理系统 ==========\n');
// 1. 访问登录页
console.log('1. 访问登录页面...');
await page.goto('http://localhost:5667/auth/login');
await page.waitForTimeout(2000);
// 2. 填写登录信息
console.log('2. 填写登录信息...');
// 输入用户名
const usernameInput = await page.locator('input[placeholder*="用户名"]');
await usernameInput.fill('admin');
console.log(' 用户名: admin');
// 输入密码
const passwordInput = await page.locator('input[type="password"]');
await passwordInput.fill('123456');
console.log(' 密码: ******');
// 3. 处理滑块验证
console.log('3. 处理滑块验证...');
// 等待滑块出现
await page.waitForTimeout(1000);
// 尝试多个可能的滑块选择器
let sliderBtn = await page.locator('.slider-button');
let sliderTrack = await page.locator('.slider-track');
// 如果第一组选择器不存在,尝试其他选择器
if (!(await sliderBtn.isVisible())) {
sliderBtn = await page.locator('[class*="slider"][class*="btn"]');
sliderTrack = await page.locator('[class*="slider"][class*="track"]');
}
// 如果还是找不到,尝试更通用的选择器
if (!(await sliderBtn.isVisible())) {
sliderBtn = await page.locator('[draggable="true"]');
sliderTrack = await page.locator('[class*="verify"]');
}
if (await sliderBtn.isVisible()) {
console.log(' 找到滑块,开始拖动...');
// 获取滑块位置
const btnBox = await sliderBtn.boundingBox();
if (btnBox) {
// 计算起点和终点
const startX = btnBox.x + btnBox.width / 2;
const startY = btnBox.y + btnBox.height / 2;
const endX = startX + 300; // 向右拖动300像素
// 执行拖动
await page.mouse.move(startX, startY);
await page.mouse.down();
// 缓慢拖动到终点
const steps = 30;
for (let i = 1; i <= steps; i++) {
const x = startX + (endX - startX) * (i / steps);
await page.mouse.move(x, startY);
await page.waitForTimeout(10);
}
await page.mouse.up();
console.log(' ✅ 滑块验证完成');
await page.waitForTimeout(1000);
}
} else {
console.log(' 未找到滑块验证,可能需要手动处理');
console.log(' 请在浏览器中手动完成滑块验证...');
// 给用户10秒时间手动完成滑块验证
await page.waitForTimeout(10_000);
}
// 4. 点击登录
console.log('4. 点击登录按钮...');
const loginBtn = await page.locator('button[aria-label="login"]');
await loginBtn.click();
// 等待登录完成
await page.waitForTimeout(3000);
// 5. 检查是否登录成功
const currentUrl = page.url();
if (currentUrl.includes('/login')) {
console.log(' ❌ 登录失败');
await page.screenshot({ path: 'login-failed.png' });
} else {
console.log(' ✅ 登录成功\n');
// 6. 访问交易管理页面
console.log('5. 访问交易管理页面...');
await page.goto('http://localhost:5667/finance/transaction');
await page.waitForTimeout(3000);
// 检查页面元素
const table = await page.locator('.ant-table');
const createBtn = await page.locator('button:has-text("新建")');
if (await table.isVisible()) {
console.log(' ✅ 交易列表显示正常');
const rows = await page.locator('.ant-table-tbody tr').count();
console.log(` 当前有 ${rows} 条交易记录`);
}
// 7. 测试新建交易
if (await createBtn.isVisible()) {
console.log('\n6. 测试新建交易功能...');
await createBtn.click();
await page.waitForTimeout(1000);
const modal = await page.locator('.ant-modal');
if (await modal.isVisible()) {
console.log(' ✅ 新建交易弹窗打开');
// 选择类型
const typeSelect = await page.locator('.ant-select').nth(0);
await typeSelect.click();
await page.locator('.ant-select-item:has-text("支出")').click();
console.log(' 选择类型: 支出');
// 输入金额
const amountInput = await page.locator(
'input.ant-input-number-input',
);
await amountInput.fill('188.88');
console.log(' 输入金额: 188.88');
// 输入描述
const descInput = await page.locator('textarea[placeholder*="描述"]');
if (await descInput.isVisible()) {
await descInput.fill('Playwright测试交易');
console.log(' 输入描述: Playwright测试交易');
}
// 提交
const submitBtn = await page.locator(
'.ant-modal-footer button.ant-btn-primary',
);
await submitBtn.click();
console.log(' 点击提交...');
await page.waitForTimeout(2000);
// 检查结果
const successMsg = await page.locator('.ant-message-success');
if (await successMsg.isVisible()) {
console.log(' ✅ 交易创建成功!');
}
}
}
// 截图
await page.screenshot({ path: 'test-final.png', fullPage: true });
console.log('\n截图保存: test-final.png');
console.log('\n========== 测试完成 ==========');
console.log('✅ 系统运行正常');
console.log('✅ 登录功能正常');
console.log('✅ 交易管理页面正常');
console.log('✅ 新建交易功能正常');
}
} catch (error) {
console.error('\n❌ 测试失败:', error.message);
await page.screenshot({ path: 'error.png' });
} finally {
console.log('\n浏览器将在5秒后关闭...');
await page.waitForTimeout(5000);
await browser.close();
}
})();