You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haoliang-net/test-production-full.js

280 lines
11 KiB
JavaScript

const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
const results = [];
function log(category, name, pass, detail) {
const status = pass ? '✅' : '❌';
console.log(`${status} [${category}] ${name}: ${detail}`);
results.push({ category, name, pass, detail });
}
// === 登录 ===
await page.goto('http://127.0.0.1/admin/login');
await page.waitForTimeout(500);
await page.fill('input[type="text"]', 'admin');
await page.fill('input[type="password"]', 'admin123');
await page.click('button:has-text("登录")');
await page.waitForTimeout(2000);
// === 导航到产量报表 ===
await page.goto('http://127.0.0.1/admin/production');
await page.waitForTimeout(3000);
// =====================
// 1. 页面基本加载
// =====================
console.log('\n========== 1. 页面基本加载 ==========');
const title = await page.title();
log('页面', '页面标题', title.length > 0, `标题: ${title}`);
const url = page.url();
log('页面', 'URL正确', url.includes('production'), `URL: ${url}`);
// =====================
// 2. 日期选择器
// =====================
console.log('\n========== 2. 日期选择器 ==========');
const dateInputs = await page.$$eval('.el-date-editor input', els => els.map(e => e.value));
const today = new Date();
const todayStr = `${today.getFullYear()}-${String(today.getMonth()+1).padStart(2,'0')}-${String(today.getDate()).padStart(2,'0')}`;
log('日期', '默认日期是今天', dateInputs[0] === todayStr && dateInputs[1] === todayStr, `开始=${dateInputs[0]}, 结束=${dateInputs[1]}, 今天=${todayStr}`);
// =====================
// 3. 汇总卡片
// =====================
console.log('\n========== 3. 汇总卡片 ==========');
const summaryCards = await page.evaluate(() => {
const cards = document.querySelectorAll('.el-card');
const results = [];
for (const card of cards) {
const text = card.textContent.trim();
if (text.includes('总产量') || text.includes('运行机床') || text.includes('切削总时') || text.includes('平均产量')) {
results.push(text.replace(/\n/g, ' ').substring(0, 80));
}
}
return results;
});
log('汇总', '总产量卡片有数据', summaryCards.some(c => c.includes('总产量')), summaryCards.filter(c => c.includes('总产量')).join(' | ') || '未找到');
log('汇总', '运行机床卡片', summaryCards.some(c => c.includes('运行机床')), summaryCards.filter(c => c.includes('运行机床')).join(' | ') || '未找到');
log('汇总', '切削总时卡片', summaryCards.some(c => c.includes('切削总时')), summaryCards.filter(c => c.includes('切削总时')).join(' | ') || '未找到');
log('汇总', '平均产量卡片', summaryCards.some(c => c.includes('平均产量')), summaryCards.filter(c => c.includes('平均产量')).join(' | ') || '未找到');
// =====================
// 4. 筛选控件
// =====================
console.log('\n========== 4. 筛选控件 ==========');
// 车间下拉
const workshopOptions = await page.evaluate(() => {
const sel = document.querySelectorAll('.el-select');
// 第一个是车间
return sel.length;
});
log('筛选', '下拉控件存在', workshopOptions >= 3, `找到${workshopOptions}个下拉`);
// 查询按钮
const queryBtn = await page.$('button:has-text("查询")');
log('筛选', '查询按钮存在', queryBtn !== null, queryBtn ? '存在' : '不存在');
// 重置按钮
const resetBtn = await page.$('button:has-text("重置")');
log('筛选', '重置按钮存在', resetBtn !== null, resetBtn ? '存在' : '不存在');
// =====================
// 5. 数据表格
// =====================
console.log('\n========== 5. 数据表格 ==========');
const tableHeaders = await page.$$eval('.el-table__header th .cell', els => els.map(e => e.textContent.trim()));
log('表格', '列头完整', tableHeaders.length >= 7, `列头: ${tableHeaders.join(', ')}`);
const expectedHeaders = ['日期', '机床', '程序名', '产量', '运行时间', '切削时间', '日状态'];
expectedHeaders.forEach(h => {
log('表格', `列头含"${h}"`, tableHeaders.includes(h), tableHeaders.includes(h) ? '存在' : `缺失! 现有: ${tableHeaders.join(',')}`);
});
// 检查表格数据
const tableRows = await page.$$eval('.el-table__body tr', trs =>
trs.slice(0, 5).map(tr => {
const cells = tr.querySelectorAll('td .cell');
return Array.from(cells).map(c => c.textContent.trim());
})
);
log('表格', '有数据行', tableRows.length > 0, `${tableRows.length}`);
if (tableRows.length > 0) {
// 检查每列是否有数据
const dateCol = tableRows.map(r => r[0]).filter(v => v && v !== '');
log('表格', '日期列有数据', dateCol.length > 0, `${dateCol.length}/${tableRows.length}行有日期, 样例: ${dateCol[0]}`);
const machineCol = tableRows.map(r => r[1]).filter(v => v && v !== '');
log('表格', '机床列有数据', machineCol.length > 0, `${machineCol.length}/${tableRows.length}行有机床, 样例: ${machineCol[0]}`);
const programCol = tableRows.map(r => r[2]).filter(v => v && v !== '');
log('表格', '程序名列有数据', programCol.length > 0, `${programCol.length}/${tableRows.length}行有程序名, 样例: ${programCol[0]}`);
const qtyCol = tableRows.map(r => r[3]).filter(v => v && v !== '' && v !== '-');
log('表格', '产量列有数据', qtyCol.length > 0, `${qtyCol.length}/${tableRows.length}行有产量, 样例: ${qtyCol.slice(0, 3).join(',')}`);
const statusCol = tableRows.map(r => r[6]).filter(v => v && v !== '');
log('表格', '日状态列有数据', statusCol.length > 0, `${statusCol.length}/${tableRows.length}行有状态, 样例: ${statusCol.slice(0, 3).join(',')}`);
// 打印前3行完整数据
console.log('\n 前3行完整数据:');
tableRows.slice(0, 3).forEach((row, i) => console.log(`${i+1}: ${JSON.stringify(row)}`));
}
// =====================
// 6. 分页
// =====================
console.log('\n========== 6. 分页 ==========');
const pagination = await page.$('.el-pagination');
log('分页', '分页组件存在', pagination !== null, pagination ? '存在' : '不存在');
const totalText = await page.evaluate(() => {
const total = document.querySelector('.el-pagination__total');
return total ? total.textContent.trim() : '未找到';
});
log('分页', '总数显示', totalText !== '未找到', totalText);
// =====================
// 7. 操作按钮
// =====================
console.log('\n========== 7. 操作按钮 ==========');
const adjustBtns = await page.$$('button:has-text("修正")');
log('操作', '修正按钮存在', adjustBtns.length > 0, `${adjustBtns.length}个修正按钮`);
const historyBtns = await page.$$('button:has-text("修正历史")');
log('操作', '修正历史按钮存在', historyBtns.length > 0, `${historyBtns.length}个修正历史按钮`);
// =====================
// 8. 交互测试:点击修正
// =====================
console.log('\n========== 8. 交互测试:修正 ==========');
if (adjustBtns.length > 0) {
await adjustBtns[0].click();
await page.waitForTimeout(1000);
const dialog = await page.$('.el-dialog');
const dialogVisible = dialog && await dialog.isVisible();
log('交互', '点击修正弹出弹窗', dialogVisible, dialogVisible ? '弹窗可见' : '弹窗不可见');
if (dialogVisible) {
const dialogTitle = await page.evaluate(() => {
const t = document.querySelector('.el-dialog__title');
return t ? t.textContent.trim() : '无标题';
});
log('交互', '弹窗标题', true, dialogTitle);
// 检查弹窗内的表单元素
const dialogInputs = await page.$$eval('.el-dialog input', els => els.map(e => ({ type: e.type, placeholder: e.placeholder, value: e.value })));
log('交互', '弹窗表单元素', dialogInputs.length > 0, `${JSON.stringify(dialogInputs)}`);
// 关闭弹窗
const closeBtn = await page.$('.el-dialog__headerbtn');
if (closeBtn) { await closeBtn.click(); await page.waitForTimeout(500); }
}
}
// =====================
// 9. 交互测试:点击修正历史
// =====================
console.log('\n========== 9. 交互测试:修正历史 ==========');
if (historyBtns.length > 0) {
await historyBtns[0].click();
await page.waitForTimeout(1000);
const dialog = await page.$('.el-dialog');
const dialogVisible = dialog && await dialog.isVisible();
log('交互', '点击修正历史弹出弹窗', dialogVisible, dialogVisible ? '弹窗可见' : '弹窗不可见');
if (dialogVisible) {
const dialogTitle = await page.evaluate(() => {
const t = document.querySelector('.el-dialog__title');
return t ? t.textContent.trim() : '无标题';
});
log('交互', '弹窗标题', true, dialogTitle);
// 关闭
const closeBtn = await page.$('.el-dialog__headerbtn');
if (closeBtn) { await closeBtn.click(); await page.waitForTimeout(500); }
}
}
// =====================
// 10. 交互测试:重置按钮
// =====================
console.log('\n========== 10. 交互测试:重置 ==========');
if (resetBtn) {
await resetBtn.click();
await page.waitForTimeout(3000);
const dateAfterReset = await page.$$eval('.el-date-editor input', els => els.map(e => e.value));
log('交互', '重置后日期变化', true, `重置后: ${dateAfterReset.join(' - ')}`);
const rowsAfterReset = await page.$$eval('.el-table__body tr', trs => trs.length);
log('交互', '重置后有数据', rowsAfterReset > 0, `${rowsAfterReset}`);
}
// =====================
// 11. 交互测试:查询按钮
// =====================
console.log('\n========== 11. 交互测试:查询 ==========');
if (queryBtn) {
await queryBtn.click();
await page.waitForTimeout(3000);
const rowsAfterQuery = await page.$$eval('.el-table__body tr', trs => trs.length);
log('交互', '查询后有数据', rowsAfterQuery > 0, `${rowsAfterQuery}`);
}
// =====================
// 12. 交互测试:分页切换
// // =====================
console.log('\n========== 12. 交互测试:分页 ==========');
const nextBtn = await page.$('.el-pagination .btn-next');
if (nextBtn) {
const isEnabled = await nextBtn.isEnabled();
if (isEnabled) {
await nextBtn.click();
await page.waitForTimeout(2000);
const page2Rows = await page.$$eval('.el-table__body tr', trs => trs.length);
log('交互', '翻页后有数据', page2Rows > 0, `第2页${page2Rows}`);
} else {
log('交互', '翻页', false, '下一页按钮不可用(可能只有1页)');
}
}
// =====================
// 汇总
// =====================
console.log('\n========================================');
const passed = results.filter(r => r.pass).length;
const failed = results.filter(r => !r.pass).length;
console.log(`总计: ${results.length}项, 通过: ${passed}, 失败: ${failed}`);
if (failed > 0) {
console.log('\n失败项:');
results.filter(r => !r.pass).forEach(r => console.log(` ❌ [${r.category}] ${r.name}: ${r.detail}`));
}
// 截图
await page.screenshot({ path: 'test-screenshots/production-full-test.png', fullPage: true });
console.log('\n截图已保存');
await browser.close();
})();