describe('隆基系统全部页面验证', () => { // 格式化时间的辅助函数 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 = `
选择测试环境
请选择要测试的环境
`; // 添加对话框到页面 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('.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 = () => { if (activeTabLoadRetry >= 30) { cy.log(`❌ [${currentPage.name}] 活动Tab页 ${activeTabText} 加载超时`); updateTabInfo(tabInfo, pageStartTime, 'timeout'); 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页 ${activeTabText} 加载出现错误`); updateTabInfo(tabInfo, pageStartTime, 'error'); return; } if (isLoading) { activeTabLoadRetry++; cy.log(`⏳ [${currentPage.name}] 活动Tab页 ${activeTabText} 第 ${activeTabLoadRetry} 次检查加载状态...`); cy.wait(500).then(waitForActiveTabLoad); } else { updateTabInfo(tabInfo, pageStartTime, 'success'); cy.log(`✅ [${currentPage.name}] 活动Tab页 ${activeTabText} 加载完成 (耗时: ${tabInfo.duration}秒)`); } }); }; 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`); } }); }; // 记录失败页面 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 = ` `; // 添加对话框到页面 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 = ` 系统页面可用性测试报告

系统页面可用性测试报告

测试摘要

测试环境: ${environment}

总页面数: ${combinedReport.pages.length}

总Tab页数: ${testReport.summary.totalTabs}

失败页面数: ${combinedReport.failedPages.length}

开始时间: ${testReport.summary.startTime}

结束时间: ${testReport.summary.endTime}

总耗时: ${calculateDuration(new Date(testReport.summary.startTime), new Date(testReport.summary.endTime))}秒

${combinedReport.failedPages.length > 0 ? `

失败页面列表

${combinedReport.failedPages.map(page => `

${page.name}

失败时间: ${page.time}

错误信息: ${page.error}

耗时: ${page.duration}秒

`).join('')}
` : ''}

详细测试结果

${combinedReport.pages.map(page => { if (!page.tabs || page.tabs.length === 0) { return ` `; } return page.tabs.map((tab, index) => ` `).join('') }).join('')}
页面名称 开始时间 Tab页名称 Tab开始时间 Tab结束时间 加载时长(秒) 状态
${page.name} ${page.startTime} 无Tab页
${index === 0 ? page.name : ''} ${index === 0 ? page.startTime : ''} ${tab.name} ${tab.startTime} ${tab.endTime} ${tab.duration} ${tab.status}
`; // 将报告写入到时间戳目录中 cy.writeFile(`${reportDir}/${environment}-test-report-${timestamp}.html`, htmlReport).then(() => { cy.log(`✅ 已生成测试报告: ${reportDir}/${environment}-test-report-${timestamp}.html`); // 添加完成提示对话框 const completionDialogHtml = `
✅ 测试完成

测试报告已生成完成!

报告目录:
${reportDir}

报告文件:
${environment}-test-report-${timestamp}.html

`; // 添加对话框到页面 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(); }); });