cypress-longi/cypress/e2e/需求计划页面是否可用.cy.js
2025-03-03 18:10:29 +08:00

944 lines
39 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

describe('隆基系统全部页面验证', () => {
// 在所有测试开始前清除localStorage
beforeEach(() => {
// 清除localStorage
cy.window().then((win) => {
win.localStorage.clear();
});
});
// 格式化时间的辅助函数
const formatTime = (date) => {
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
};
// 计算时间差(返回秒数)
const calculateDuration = (startTime, endTime) => {
return ((endTime - startTime) / 1000).toFixed(2);
};
// 添加全局变量用于存储选择的环境
let selectedEnvironment = null;
// 添加环境配置
const ENV_CONFIG = {
DEV: {
url: 'https://ibp-dev.longi.com/main/#/login',
needCredentials: false
},
UAT: {
url: 'https://ibp-test.longi.com/main/#/login?debug=ly',
needCredentials: true,
username: 'qichenadmin',
password: '123456'
}
};
// 添加环境选择和登录处理函数
const handleLogin = (environment) => {
const envConfig = ENV_CONFIG[environment];
cy.visit(envConfig.url);
// 忽略未捕获的异常
Cypress.on('uncaught:exception', (err, runnable) => false);
cy.get('#app', {timeout: 3000}).should('exist');
if (envConfig.needCredentials) {
// 清空输入框
cy.get('input[name="username"]').clear();
cy.get('input[name="passWord"]').clear();
// 输入账号密码
cy.get('input[name="username"]').type(envConfig.username);
cy.get('input[name="passWord"]').type(envConfig.password);
}
// 执行登录
cy.get('.container-button').click();
// 等待登录完成
cy.wait(3000);
};
// 在整个测试套件开始前先选择环境
before(() => {
// 添加一个变量来控制环境选择流程
let envSelected = false;
cy.visit('https://ibp-dev.longi.com/main/#/login');
// 忽略未捕获的异常
Cypress.on('uncaught:exception', (err, runnable) => false);
// 创建环境选择对话框
const dialogHtml = `
<div class="el-dialog__wrapper env-select-dialog" style="position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: auto; margin: 0; z-index: 2000; background: rgba(0, 0, 0, 0.5);">
<div class="el-dialog" style="margin: 15vh auto 50px; width: 400px; background: #fff; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);">
<div class="el-dialog__header" style="padding: 20px; border-bottom: 1px solid #eee;">
<span class="el-dialog__title" style="font-size: 18px; color: #303133;">选择测试环境</span>
</div>
<div class="el-dialog__body" style="padding: 20px;">
<div class="env-selection-status" style="margin-bottom: 15px; padding: 10px; background-color: #f0f9eb; border-radius: 4px; color: #67c23a;">
请选择要测试的环境
</div>
<div class="env-list" style="display: flex; gap: 10px;">
<button class="env-btn el-button el-button--primary" data-env="DEV" style="flex: 1; padding: 12px; height: 40px; line-height: 1;">
DEV环境
</button>
<button class="env-btn el-button el-button--success" data-env="UAT" style="flex: 1; padding: 12px; height: 40px; line-height: 1;">
UAT环境
</button>
</div>
</div>
</div>
</div>
`;
// 添加对话框到页面
cy.get('body').then($body => {
$body.append(dialogHtml);
});
// 等待环境选择
cy.get('.env-btn').then($buttons => {
// 为每个按钮添加点击事件
$buttons.each((_, button) => {
Cypress.$(button).on('click', () => {
const env = Cypress.$(button).data('env');
selectedEnvironment = env;
envSelected = true;
Cypress.$('.env-select-dialog').remove();
});
});
});
// 使用递归函数等待环境选择
function waitForEnvSelection() {
if (envSelected) {
cy.log(`已选择 ${selectedEnvironment} 环境`);
// 如果是UAT环境则需要重新访问对应的URL
if (selectedEnvironment === 'UAT') {
cy.visit(ENV_CONFIG.UAT.url);
}
// 执行登录
handleLogin(selectedEnvironment);
} else {
cy.wait(1000).then(waitForEnvSelection);
}
}
// 开始等待环境选择
waitForEnvSelection();
});
// 修改测试报告数据结构,使用更轻量的格式
let testReport = {
summary: {
totalPages: 0,
totalTabs: 0,
failedCount: 0,
startTime: formatTime(new Date()),
endTime: ''
},
currentBatch: {
pages: [],
failedPages: []
}
};
// 每个测试用例前不再重新访问登录页
// beforeEach(() => {
// // 只设置异常处理
// Cypress.on('uncaught:exception', (err, runnable) => false);
// });
// 添加内存清理的公共方法
const cleanupMemory = () => {
// 执行垃圾回收
cy.task('clearMemory', null, {log: false});
// 清理DOM快照
cy.get('body').then(() => {
Cypress.$(document).find('*').off();
Cypress.$('.el-loading-mask').remove();
Cypress.$('.el-message').remove();
Cypress.$('.el-message-box').remove();
// 清理可能的内存泄漏
Cypress.$('iframe').remove(); // 移除所有iframe
Cypress.$('img').remove(); // 移除所有图片
Cypress.$('video').remove(); // 移除所有视频
// 清理事件监听器
const win = Cypress.$(window);
win.off();
win.find('*').off();
});
// 手动清理一些可能的引用
if (window.gc) {
window.gc();
}
};
// 添加关闭tab的公共方法
const closeActiveTab = (pageName) => {
cy.log(`🗑️ 正在关闭页面 "${pageName}" 的tab...`);
cy.get('body').then($body => {
// 检查是否存在活动的tab和关闭按钮
const $activeTab = $body.find('.vab-tabs .el-tabs--card .el-tabs__item.is-active');
const $closeButton = $activeTab.find('.el-icon.is-icon-close');
if ($activeTab.length > 0 && $closeButton.length > 0) {
cy.get('.vab-tabs .el-tabs--card .el-tabs__item.is-active .el-icon.is-icon-close')
.should('be.visible')
.click({force: true})
.then(() => {
cy.wait(500); // 等待关闭动画完成
cleanupMemory(); // 在关闭tab后清理内存
});
} else {
cy.log(`⚠️ [${pageName}] 没有找到可关闭的tab继续执行...`);
}
});
};
// 添加报告写入方法
const writeReportBatch = () => {
const batchNumber = Math.floor(testReport.summary.totalPages / 20); // 每20个页面写入一次
const fileName = `cypress/reports/${selectedEnvironment}-menu-test-report-batch-${batchNumber}.json`;
cy.log(`📊 写入批次报告 ${batchNumber}:`);
cy.log(`当前批次页面数: ${testReport.currentBatch.pages.length}`);
cy.log(`当前批次失败页面数: ${testReport.currentBatch.failedPages.length}`);
cy.writeFile(fileName, testReport.currentBatch).then(() => {
cy.log(`✅ 批次报告已写入: ${fileName}`);
// 清空当前批次数据,释放内存
testReport.currentBatch = {
pages: [],
failedPages: []
};
cleanupMemory();
});
};
// 页面信息管理类
class PageInfo {
constructor(name, isThirdMenu = false, parentMenu = null) {
this.name = isThirdMenu ? `${parentMenu} > ${name}` : name;
this.startTime = formatTime(new Date());
this.endTime = '';
this.tabs = [];
this.hasThirdMenu = false;
this.parentMenu = parentMenu;
}
addToBatch() {
testReport.currentBatch.pages.push(this);
testReport.summary.totalPages++;
return this;
}
setAsThirdMenu() {
this.hasThirdMenu = true;
return this;
}
complete() {
this.endTime = formatTime(new Date());
return this;
}
addTab(tabInfo) {
if (!this.tabs) {
this.tabs = [];
}
this.tabs.push(tabInfo);
return this;
}
}
// 处理单个tab页
const processSingleTab = (currentPage, $allTabs) => {
const tabText = $allTabs.text().trim();
cy.log(`📑 页面 "${currentPage.name}" 只有一个tab页: ${tabText}`);
const tabStartTime = new Date();
const tabInfo = {
name: tabText,
startTime: formatTime(tabStartTime),
endTime: formatTime(tabStartTime),
duration: '0.00',
status: 'success'
};
if (!currentPage.tabs) {
currentPage.tabs = [];
}
currentPage.tabs.push(tabInfo);
testReport.summary.totalTabs += 1;
};
// 更新tab信息
const updateTabInfo = (tabInfo, startTime, status) => {
const endTime = new Date();
tabInfo.endTime = formatTime(endTime);
tabInfo.duration = calculateDuration(startTime, endTime);
tabInfo.status = status;
};
// 处理多个tab页
const processMultipleTabs = (currentPage, $inactiveTabs) => {
cy.log(`\n📑 页面 "${currentPage.name}" 发现 ${$inactiveTabs.length} 个待访问的tab页`);
testReport.summary.totalTabs += $inactiveTabs.length;
const processTab = (index = 0) => {
if (index >= $inactiveTabs.length) {
cy.log(`✅ 页面 "${currentPage.name}" 的所有tab页处理完成`);
return;
}
const tabProgress = ((index + 1) / $inactiveTabs.length * 100).toFixed(1);
const $currentTab = Cypress.$($inactiveTabs[index]);
const tabText = $currentTab.text().trim();
cy.log(`🔸 正在处理tab页 [${index + 1}/${$inactiveTabs.length}] (${tabProgress}%): ${currentPage.name} > ${tabText}`);
const tabStartTime = new Date();
const tabInfo = {
name: tabText,
startTime: formatTime(tabStartTime),
endTime: '',
duration: '',
status: 'pending'
};
if (!currentPage.tabs) {
currentPage.tabs = [];
}
currentPage.tabs.push(tabInfo);
cy.wrap($currentTab).click({force: true}).then(() => {
cy.log(`⏳ [${currentPage.name}] 已点击tab页: ${tabText},等待加载...`);
let tabLoadRetry = 0;
const waitForTabLoad = () => {
if (tabLoadRetry >= 30) {
cy.log(`❌ [${currentPage.name}] Tab页 ${tabText} 加载超时 [${tabLoadRetry}次重试],继续下一个`);
updateTabInfo(tabInfo, tabStartTime, 'timeout');
processTab(index + 1);
return;
}
cy.get('@pageBody').then($body => {
const isLoading = $body.find('.el-loading-mask').length > 0;
const hasTabError = $body.find('.el-message-box__message').length > 0 ||
$body.find('.el-message--error').length > 0;
if (hasTabError) {
cy.log(`❌ [${currentPage.name}] Tab页 ${tabText} 加载出现错误`);
updateTabInfo(tabInfo, tabStartTime, 'error');
processTab(index + 1);
return;
}
if (isLoading) {
tabLoadRetry++;
cy.log(`⏳ [${currentPage.name}] Tab页 ${tabText}${tabLoadRetry} 次检查加载状态...`);
cy.wait(500).then(waitForTabLoad);
} else {
updateTabInfo(tabInfo, tabStartTime, 'success');
cy.log(`✅ [${currentPage.name}] Tab页 ${tabText} 加载完成 (耗时: ${tabInfo.duration}秒)`);
cy.wait(1000).then(() => processTab(index + 1));
}
});
};
waitForTabLoad();
});
};
processTab();
};
// 处理页面中的tab页
const processPageTabs = (currentPage, pageStartTime) => {
return cy.get('body').then($body => {
const hasWorkTabs = $body.find('.workSpaceBaseTab').length > 0;
if (hasWorkTabs) {
// 如果存在 .workSpaceBaseTab则按原来的逻辑处理
return cy.get('.workSpaceBaseTab').as('workTabs').then($tabs => {
if ($tabs.length > 0) {
return cy.get('@workTabs').find('.el-tabs__item').as('allTabs').then($allTabs => {
const $activeTab = $allTabs.filter('.is-active');
const $inactiveTabs = $allTabs.filter(':not(.is-active)').toArray();
// 首先处理活动的Tab页使用页面开始时间
if ($activeTab.length > 0) {
const activeTabText = $activeTab.text().trim();
const tabInfo = {
name: activeTabText,
startTime: formatTime(pageStartTime), // 使用页面开始时间作为Tab开始时间
endTime: '',
duration: '',
status: 'pending'
};
if (!currentPage.tabs) {
currentPage.tabs = [];
}
currentPage.tabs.push(tabInfo);
testReport.summary.totalTabs += 1;
// 检查活动Tab页的加载状态
let activeTabLoadRetry = 0;
const waitForActiveTabLoad = () => {
// ... 原有代码 ...
};
waitForActiveTabLoad();
}
// 然后处理其他Tab页
if ($inactiveTabs.length > 0) {
processMultipleTabs(currentPage, $inactiveTabs);
} else if ($allTabs.length === 1) {
cy.log(` [${currentPage.name}] 只有一个活动的tab页`);
}
closeActiveTab(currentPage.name);
});
} else {
cy.log(` [${currentPage.name}] 页面中没有找到workSpaceBaseTab的内容`);
closeActiveTab(currentPage.name);
}
});
} else {
// 如果不存在 .workSpaceBaseTab记录信息并继续
cy.log(` [${currentPage.name}] 页面中没有找到workSpaceBaseTab元素可能是不同类型的页面`);
// 尝试查找页面中可能存在的其他tab结构
const hasOtherTabs = $body.find('.el-tabs__item').length > 0;
if (hasOtherTabs) {
cy.log(` [${currentPage.name}] 找到其他类型的tab元素尝试处理`);
return cy.get('.el-tabs__item').as('otherTabs').then($otherTabs => {
const $activeTab = $otherTabs.filter('.is-active');
const $inactiveTabs = $otherTabs.filter(':not(.is-active)').toArray();
// 处理这些tab类似于原来的逻辑
// ...
});
} else {
cy.log(` [${currentPage.name}] 页面中没有找到任何tab元素记录为单页面`);
// 将页面记录为没有tab的单页面
const tabInfo = {
name: "页面内容",
startTime: formatTime(pageStartTime),
endTime: formatTime(new Date()),
duration: calculateDuration(pageStartTime, new Date()),
status: 'success'
};
if (!currentPage.tabs) {
currentPage.tabs = [];
}
currentPage.tabs.push(tabInfo);
testReport.summary.totalTabs += 1;
closeActiveTab(currentPage.name);
}
}
});
};
// 记录失败页面
const recordFailedPage = (pageName, error, startTime) => {
testReport.currentBatch.failedPages.push({
name: pageName,
time: formatTime(new Date()),
error: error,
duration: calculateDuration(startTime, new Date())
});
cleanupMemory();
};
// 修改 waitForPageLoad 函数,接收开始时间参数
const waitForPageLoad = (currentPage, pageStartTime) => {
cy.log('等待页面数据加载...');
let retryCount = 0;
const maxRetries = 30;
function check() {
if (retryCount >= maxRetries) {
cy.log('页面加载超时,记录失败并继续执行...');
recordFailedPage(currentPage.name, '页面加载超时', pageStartTime);
return;
}
cy.get('@pageBody').then($body => {
const hasLoadingMask = $body.find('.el-loading-mask').length > 0;
const hasError = $body.find('.el-message-box__message').length > 0 ||
$body.find('.el-message--error').length > 0;
if (hasError) {
cy.log('页面加载出现错误');
recordFailedPage(currentPage.name, '页面加载出现错误', pageStartTime);
return;
}
if (hasLoadingMask) {
retryCount++;
cy.wait(500).then(check);
} else {
cy.log('页面数据加载完成');
cy.wait(1000).then(() => {
// 修改处理Tab页的逻辑传入页面开始时间
processPageTabs(currentPage, pageStartTime);
});
}
});
}
check();
};
// 处理有三级菜单的情况
const processWithThirdMenu = (pageInfo, $thirdMenuItems, $menuItem, menuText, processMenuItems, index) => {
pageInfo.hasThirdMenu = true;
cy.log(`${menuText} 包含 ${$thirdMenuItems.length} 个三级菜单`);
const processThirdMenu = (thirdIndex = 0) => {
if (thirdIndex >= $thirdMenuItems.length) {
pageInfo.endTime = formatTime(new Date());
const thirdMenuProgress = (100).toFixed(1);
cy.log(`✅ 完成菜单 "${menuText}" 的所有三级菜单处理 (${thirdMenuProgress}%)`);
closeActiveTab(menuText);
cy.wait(1000).then(() => processMenuItems(index + 1));
return;
}
const thirdMenuProgress = ((thirdIndex + 1) / $thirdMenuItems.length * 100).toFixed(1);
if (thirdIndex > 0) {
cy.wrap($menuItem).click();
cy.wait(1000);
}
cy.get('@thirdMenuItems')
.eq(thirdIndex)
.then($thirdMenu => {
const thirdMenuText = $thirdMenu.text().trim();
cy.log(`\n🔸 处理三级菜单 [${thirdIndex + 1}/${$thirdMenuItems.length}] (${thirdMenuProgress}%): ${menuText} > ${thirdMenuText}`);
const thirdMenuPage = new PageInfo(thirdMenuText, true, menuText).addToBatch();
cy.wrap($thirdMenu).click();
waitForPageLoad(thirdMenuPage, new Date());
cy.wait(1000).then(() => processThirdMenu(thirdIndex + 1));
});
};
processThirdMenu();
};
// 处理没有三级菜单的情况
const processWithoutThirdMenu = (pageInfo, menuText, processMenuItems, index) => {
cy.log(`× ${menuText} 点击后没有显示三级菜单`);
const pageStartTime = new Date(); // 记录页面开始加载的时间
// 修改 waitForPageLoad 函数的调用,传入开始时间
waitForPageLoad(pageInfo, pageStartTime);
pageInfo.endTime = formatTime(new Date());
closeActiveTab(menuText);
cy.wait(1000).then(() => processMenuItems(index + 1));
};
it('验证菜单操作', () => {
// 初始化时清理内存
cleanupMemory();
// 添加一个全局变量来控制测试流程
let testStarted = false;
let selectedMenuItems = null;
cy.wait(3000);
cy.log('开始菜单验证测试');
// 为常用元素创建别名
cy.get('body').as('pageBody');
cy.get('.ly-side-nav').as('sideNav');
cy.get('.el-scrollbar__view > .el-menu').as('mainMenu');
cy.get('.vab-content .toggle-icon').as('menuToggle');
// 确保菜单展开
cy.get('@sideNav').then(($el) => {
cy.log(`菜单现在的偏移量是:${$el.css('left')}`)
const leftValue = $el.css('left');
if (leftValue !== '0px') {
cy.log('菜单未展开,点击展开');
cy.get('@menuToggle').click();
cy.log('已点击展开菜单');
} else {
cy.log('菜单已经处于展开状态');
}
});
cy.log('开始获取菜单结构');
cy.get('@mainMenu').then(($elMenu) => {
const allMenuItems = $elMenu.find('.el-sub-menu__title, .el-menu-item');
const menuItems = [];
// 过滤并整理菜单项
allMenuItems.each((index, el) => {
const $item = Cypress.$(el);
const menuText = $item.find('.titleSpan').text().trim() || $item.text().trim();
const isFirstLevel = $item.find('.menuIcon').length > 0;
if (!isFirstLevel) {
menuItems.push({
index,
text: menuText,
element: el
});
}
});
cy.log(`🔍 找到 ${menuItems.length} 个可测试的菜单项`);
// 创建菜单选择对话框
const dialogHtml = `
<div class="el-dialog__wrapper menu-select-dialog" style="position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: auto; margin: 0; z-index: 2000; background: rgba(0, 0, 0, 0.5);">
<div class="el-dialog" style="margin: 15vh auto 50px; width: 600px; background: #fff; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);">
<div class="el-dialog__header" style="padding: 20px; border-bottom: 1px solid #eee;">
<span class="el-dialog__title" style="font-size: 18px; color: #303133;">选择要测试的菜单</span>
</div>
<div class="el-dialog__body" style="padding: 20px; max-height: 50vh; overflow-y: auto;">
<div class="menu-selection-status" style="margin-bottom: 15px; padding: 10px; background-color: #f0f9eb; border-radius: 4px; color: #67c23a;">
请选择需要测试的菜单项,然后点击"开始测试"按钮开始测试。
</div>
<div class="menu-list">
${menuItems.map((item, idx) => `
<div class="menu-item" style="margin-bottom: 10px;">
<label style="display: flex; align-items: center;">
<input type="checkbox" value="${idx}" style="margin-right: 8px;">
<span>${item.text}</span>
</label>
</div>
`).join('')}
</div>
</div>
<div class="el-dialog__footer" style="padding: 20px; text-align: right; border-top: 1px solid #eee;">
<button class="select-all-btn el-button el-button--default" style="margin-right: 10px;">全选</button>
<button class="start-test-btn el-button el-button--primary" disabled>开始测试</button>
</div>
</div>
</div>
`;
// 添加对话框到页面
Cypress.$('body').append(dialogHtml);
// 更新开始测试按钮状态的函数
const updateStartButtonState = () => {
const checkedCount = Cypress.$('.menu-list input[type="checkbox"]:checked').length;
Cypress.$('.start-test-btn').prop('disabled', checkedCount === 0);
Cypress.$('.menu-selection-status').text(
checkedCount === 0 ?
'请选择需要测试的菜单项,然后点击"开始测试"按钮开始测试。' :
`已选择 ${checkedCount} 个菜单项,点击"开始测试"按钮开始测试。`
);
};
// 绑定事件
Cypress.$('.select-all-btn').on('click', function () {
const checkboxes = Cypress.$('.menu-list input[type="checkbox"]');
const allChecked = checkboxes.length === checkboxes.filter(':checked').length;
checkboxes.prop('checked', !allChecked);
updateStartButtonState();
});
// 为每个复选框添加change事件
Cypress.$('.menu-list input[type="checkbox"]').on('change', updateStartButtonState);
// 绑定开始测试按钮事件
Cypress.$('.start-test-btn').on('click', function () {
const selectedIndexes = [];
Cypress.$('.menu-list input[type="checkbox"]:checked').each(function () {
selectedIndexes.push(parseInt(Cypress.$(this).val()));
});
if (selectedIndexes.length > 0) {
selectedMenuItems = selectedIndexes.map(index => menuItems[index]);
testStarted = true;
Cypress.$('.menu-select-dialog').remove();
}
});
});
// 使用递归检查测试是否开始
function checkTestStarted() {
if (testStarted) {
cy.log(`选中了 ${selectedMenuItems.length} 个菜单项进行测试`);
startTesting(selectedMenuItems);
} else {
cy.wait(1000).then(checkTestStarted);
}
}
// 开始测试的函数
function startTesting(selectedMenus) {
let processedCount = 0;
const processMenuItems = (index = 0) => {
if (index >= selectedMenus.length) {
cy.log('🎉 所有菜单项处理完成!');
writeReportBatch();
testReport.summary.endTime = formatTime(new Date());
// 生成时间戳
const timestamp = new Date().toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
}).replace(/[\/\s:]/g, '');
// 创建以时间戳命名的报告目录
const reportDir = `cypress/reports/report-${timestamp}`;
// 创建报告目录并生成最终报告
cy.task('createReportDir', reportDir).then(() => {
// 将摘要信息写入到时间戳目录中
cy.writeFile(`${reportDir}/test-summary-${timestamp}.json`, testReport.summary).then(() => {
generateFinalReport(reportDir, timestamp, selectedEnvironment);
});
});
return;
}
if (testReport.currentBatch.pages.length >= 20) {
writeReportBatch();
}
if (index > 0 && index % 3 === 0) {
cleanupMemory();
}
const totalMenuItems = selectedMenus.length;
const progress = ((index + 1) / totalMenuItems * 100).toFixed(1);
const menuItem = selectedMenus[index];
cy.log(`\n===== 📍 正在处理菜单项 [${index + 1}/${totalMenuItems}] (${progress}%): ${menuItem.text} =====`);
const pageInfo = new PageInfo(menuItem.text).addToBatch();
cy.wrap(menuItem.element).click().then(() => {
cy.wait(1000);
cy.get('@pageBody').then($body => {
// 修改检查三级菜单的逻辑
cy.get('body').then($body => {
const hasThirdMenu = $body.find('.el-popper.is-light.el-popover .menuTitle.canClick').length > 0;
if (hasThirdMenu) {
cy.get('.el-popper.is-light.el-popover .menuTitle.canClick').as('thirdMenuItems').then($thirdMenuItems => {
processWithThirdMenu(pageInfo, $thirdMenuItems, Cypress.$(menuItem.element), menuItem.text, processMenuItems, index);
});
} else {
processWithoutThirdMenu(pageInfo, menuItem.text, processMenuItems, index);
}
});
});
});
};
cy.log('开始遍历选中的菜单项');
processMenuItems();
}
// 开始检查是否可以开始测试
checkTestStarted();
});
// 在每个测试用例结束后清理内存
afterEach(() => {
cleanupMemory();
});
// 修改生成HTML报告的方法接收环境参数
const generateFinalReport = (reportDir, timestamp, environment) => {
// 读取所有批次报告
cy.task('readAllReports', environment).then((allBatches) => {
cy.log(`📊 读取到 ${allBatches.length} 个批次报告`);
// 合并所有批次数据
const combinedReport = {
pages: [],
failedPages: []
};
if (Array.isArray(allBatches)) {
allBatches.forEach(batch => {
if (batch.pages) {
cy.log(`合并批次报告: ${batch.pages.length} 个页面`);
combinedReport.pages.push(...batch.pages);
}
if (batch.failedPages) {
combinedReport.failedPages.push(...batch.failedPages);
}
});
}
// 添加当前批次的数据
if (testReport.currentBatch.pages.length > 0) {
cy.log(`添加当前批次: ${testReport.currentBatch.pages.length} 个页面`);
combinedReport.pages.push(...testReport.currentBatch.pages);
}
if (testReport.currentBatch.failedPages.length > 0) {
combinedReport.failedPages.push(...testReport.currentBatch.failedPages);
}
cy.log(`📊 总计: ${combinedReport.pages.length} 个页面, ${testReport.summary.totalTabs} 个Tab页`);
const htmlReport = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>系统页面可用性测试报告</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.summary { margin-bottom: 20px; }
table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f4f4f4; }
.success { color: green; }
.error { color: red; }
.timeout { color: orange; }
.pending { color: gray; }
.tab-row { background-color: #f9f9f9; }
.failed-pages { margin-top: 20px; }
.failed-page { background-color: #fff0f0; margin-bottom: 10px; padding: 10px; border-left: 4px solid #ff0000; }
</style>
</head>
<body>
<h1>系统页面可用性测试报告</h1>
<div class="summary">
<h2>测试摘要</h2>
<p>测试环境: ${environment}</p>
<p>总页面数: ${combinedReport.pages.length}</p>
<p>总Tab页数: ${testReport.summary.totalTabs}</p>
<p>失败页面数: ${combinedReport.failedPages.length}</p>
<p>开始时间: ${testReport.summary.startTime}</p>
<p>结束时间: ${testReport.summary.endTime}</p>
<p>总耗时: ${calculateDuration(new Date(testReport.summary.startTime), new Date(testReport.summary.endTime))}秒</p>
</div>
${combinedReport.failedPages.length > 0 ? `
<div class="failed-pages">
<h2>失败页面列表</h2>
${combinedReport.failedPages.map(page => `
<div class="failed-page">
<h3>${page.name}</h3>
<p>失败时间: ${page.time}</p>
<p>错误信息: ${page.error}</p>
<p>耗时: ${page.duration}秒</p>
</div>
`).join('')}
</div>
` : ''}
<h2>详细测试结果</h2>
<table>
<tr>
<th>页面名称</th>
<th>开始时间</th>
<th>Tab页名称</th>
<th>Tab开始时间</th>
<th>Tab结束时间</th>
<th>加载时长(秒)</th>
<th>状态</th>
</tr>
${combinedReport.pages.map(page => {
if (!page.tabs || page.tabs.length === 0) {
return `
<tr>
<td>${page.name}</td>
<td>${page.startTime}</td>
<td colspan="5">无Tab页</td>
</tr>`;
}
return page.tabs.map((tab, index) => `
<tr class="tab-row">
<td>${index === 0 ? page.name : ''}</td>
<td>${index === 0 ? page.startTime : ''}</td>
<td>${tab.name}</td>
<td>${tab.startTime}</td>
<td>${tab.endTime}</td>
<td>${tab.duration}</td>
<td class="${tab.status}">${tab.status}</td>
</tr>`).join('')
}).join('')}
</table>
</body>
</html>`;
// 将报告写入到时间戳目录中
cy.writeFile(`${reportDir}/${environment}-test-report-${timestamp}.html`, htmlReport).then(() => {
cy.log(`✅ 已生成测试报告: ${reportDir}/${environment}-test-report-${timestamp}.html`);
// 添加完成提示对话框
const completionDialogHtml = `
<div class="el-dialog__wrapper completion-dialog" style="position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: auto; margin: 0; z-index: 2001; background: rgba(0, 0, 0, 0.5);">
<div class="el-dialog" style="margin: 15vh auto 50px; width: 500px; background: #fff; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);">
<div class="el-dialog__header" style="padding: 20px; border-bottom: 1px solid #eee;">
<span class="el-dialog__title" style="font-size: 18px; color: #303133;">✅ 测试完成</span>
</div>
<div class="el-dialog__body" style="padding: 30px 20px;">
<div style="margin-bottom: 15px;">
<p style="margin: 0 0 15px 0;">测试报告已生成完成!</p>
<p style="margin: 0; color: #666;">报告目录:<br><span style="color: #409EFF; word-break: break-all;">${reportDir}</span></p>
<p style="margin: 10px 0 0 0; color: #666;">报告文件:<br><span style="color: #409EFF; word-break: break-all;">${environment}-test-report-${timestamp}.html</span></p>
</div>
</div>
<div class="el-dialog__footer" style="padding: 20px; text-align: right; border-top: 1px solid #eee;">
<button class="close-dialog-btn el-button el-button--primary" style="padding: 9px 15px;">确定</button>
</div>
</div>
</div>
`;
// 添加对话框到页面
cy.get('body').then($body => {
$body.append(completionDialogHtml);
// 绑定关闭按钮事件
Cypress.$('.close-dialog-btn').on('click', function() {
Cypress.$('.completion-dialog').remove();
});
});
});
// 清理批次报告文件
cy.task('cleanupReports', environment);
});
};
// 删除重复的after钩子
after(() => {
cleanupMemory();
});
});