diff --git a/cypress/e2e/需求计划页面是否可用.cy.js b/cypress/e2e/需求计划页面是否可用.cy.js
index 6e393ec..ca16bcc 100644
--- a/cypress/e2e/需求计划页面是否可用.cy.js
+++ b/cypress/e2e/需求计划页面是否可用.cy.js
@@ -12,6 +12,33 @@ describe('隆基系统全部页面验证', () => {
cleanupMemory();
});
+ // 创建通用对话框模板函数
+ const createDialogTemplate = (options) => {
+ const {
+ dialogClass,
+ title,
+ width,
+ bodyContent,
+ footerContent
+ } = options;
+
+ return `
+
-
-
-
-
- 请选择要测试的环境
-
-
-
-
-
-
-
+ const envDialogBodyContent = `
+
+ 请选择要测试的环境
+
+
+
+
`;
+ const dialogHtml = createDialogTemplate({
+ dialogClass: 'env-select-dialog',
+ title: '选择测试环境',
+ width: '400px',
+ bodyContent: envDialogBodyContent,
+ footerContent: ''
+ });
+
// 添加对话框到页面
cy.get('body').then($body => {
$body.append(dialogHtml);
@@ -159,35 +185,101 @@ describe('隆基系统全部页面验证', () => {
}
};
- // 添加内存清理的公共方法
+ // 优化内存清理函数,确保与Cypress命令链兼容
const cleanupMemory = () => {
- // 执行垃圾回收
- cy.task('clearMemory', null, {log: false});
-
- // 清理DOM快照
- cy.get('body').then(() => {
+ cy.log('🧹 执行内存清理...');
+
+ // 记录清理前的内存使用情况
+ cy.window({log: false}).then(win => {
+ if (win.performance && win.performance.memory) {
+ const beforeMemory = Math.round(win.performance.memory.usedJSHeapSize / 1024 / 1024);
+ cy.log(`清理前内存使用: ${beforeMemory}MB`);
+ }
+
+ // 执行内存清理操作
try {
- // 移除一些可能导致内存泄漏的元素
- Cypress.$('.el-loading-mask').remove();
- Cypress.$('.el-message').remove();
- Cypress.$('.el-message-box').remove();
+ // 1. 清理DOM元素
+ const elementsToRemove = [
+ '.el-loading-mask',
+ '.el-message',
+ '.el-message-box:not(.is-message)',
+ '.el-notification',
+ '.el-drawer__wrapper:not(.active)',
+ '.el-tooltip__popper',
+ '.el-select-dropdown',
+ '.el-popover',
+ '.el-dropdown-menu',
+ '.v-modal'
+ ];
- // 清理事件监听器 - 只清理特定元素的事件
- Cypress.$('.el-dialog__wrapper').off();
- Cypress.$('.el-notification').off();
- Cypress.$('.el-drawer__wrapper').off();
+ elementsToRemove.forEach(selector => {
+ if (Cypress.$(selector).length > 0) {
+ Cypress.$(selector).remove();
+ }
+ });
- // 清理控制台
+ // 2. 清理iframe内容
+ Cypress.$('iframe').each((_, el) => {
+ try {
+ el.src = 'about:blank';
+ } catch (e) {
+ // 忽略错误
+ }
+ });
+
+ // 3. 清理大型表格内容
+ Cypress.$('.el-table__body tr').each((index, el) => {
+ if (index > 20) {
+ Cypress.$(el).remove();
+ }
+ });
+
+ // 4. 清理事件监听器(保留菜单相关元素)
+ Cypress.$('*:not(.el-menu):not(.el-menu-item):not(.el-submenu):not(.sidebar-menu):not(.el-scrollbar__view)').each((_, el) => {
+ try {
+ const element = Cypress.$(el);
+ // 只清理非菜单元素的事件
+ if (!element.closest('.el-menu, .sidebar-menu').length) {
+ element.off();
+ }
+ } catch (e) {
+ // 忽略错误
+ }
+ });
+
+ // 5. 清理定时器
+ let id = window.setTimeout(() => {}, 0);
+ while (id--) {
+ window.clearTimeout(id);
+ window.clearInterval(id);
+ }
+
+ // 6. 清理Vue相关引用
+ if (win.__VUE_DEVTOOLS_GLOBAL_HOOK__) {
+ win.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = null;
+ }
+
+ // 7. 手动触发一些可能的内存释放
+ win.dispatchEvent(new Event('beforeunload'));
+
+ // 8. 清理控制台
console.clear();
} catch (e) {
console.error('清理DOM时出错:', e);
}
+ }).then(() => {
+ // 等待一段时间让垃圾回收生效
+ return cy.wait(1000, {log: false});
+ }).then(() => {
+ // 再次检查内存使用情况
+ return cy.window({log: false}).then(win => {
+ if (win.performance && win.performance.memory) {
+ const afterMemory = Math.round(win.performance.memory.usedJSHeapSize / 1024 / 1024);
+ cy.log(`清理后内存使用: ${afterMemory}MB`);
+ }
+ cy.log('🧹 内存清理完成');
+ });
});
-
- // 手动清理一些可能的引用
- if (window.gc) {
- window.gc();
- }
};
// 添加关闭tab的公共方法
@@ -311,18 +403,19 @@ describe('隆基系统全部页面验证', () => {
cy.log(`\n📑 页面 "${currentPage.name}" 发现 ${$inactiveTabs.length} 个待访问的tab页`);
testReport.summary.totalTabs += $inactiveTabs.length;
- const processTab = (index = 0) => {
- if (index >= $inactiveTabs.length) {
+ // 使用迭代方式处理Tab页,避免深度递归
+ const processTabsSequentially = (tabs, startIndex = 0) => {
+ if (startIndex >= tabs.length) {
cy.log(`✅ 页面 "${currentPage.name}" 的所有tab页处理完成`);
- return;
+ return cy.wrap(null);
}
-
- const tabProgress = ((index + 1) / $inactiveTabs.length * 100).toFixed(1);
- const $currentTab = Cypress.$($inactiveTabs[index]);
+
+ const $currentTab = Cypress.$(tabs[startIndex]);
const tabText = $currentTab.text().trim();
-
- cy.log(`🔸 正在处理tab页 [${index + 1}/${$inactiveTabs.length}] (${tabProgress}%): ${currentPage.name} > ${tabText}`);
-
+ const tabProgress = ((startIndex + 1) / tabs.length * 100).toFixed(1);
+
+ cy.log(`🔸 正在处理tab页 [${startIndex + 1}/${tabs.length}] (${tabProgress}%): ${currentPage.name} > ${tabText}`);
+
const tabStartTime = new Date();
const tabInfo = {
name: tabText,
@@ -331,53 +424,59 @@ describe('隆基系统全部页面验证', () => {
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));
- }
+
+ // 处理单个Tab,然后链式处理下一个
+ return cy.wrap($currentTab)
+ .click({force: true})
+ .then(() => {
+ cy.log(`⏳ [${currentPage.name}] 已点击tab页: ${tabText},等待加载...`);
+ return waitForTabLoadWithTimeout(currentPage, tabInfo, tabStartTime, 30);
+ })
+ .then(() => {
+ // 处理下一个Tab
+ return processTabsSequentially(tabs, startIndex + 1);
+ });
+ };
+
+ // 等待Tab加载的函数,使用超时机制
+ const waitForTabLoadWithTimeout = (currentPage, tabInfo, tabStartTime, maxRetries, retryCount = 0) => {
+ if (retryCount >= maxRetries) {
+ cy.log(`❌ [${currentPage.name}] Tab页 ${tabInfo.name} 加载超时 [${retryCount}次重试]`);
+ updateTabInfo(tabInfo, tabStartTime, 'timeout');
+ return cy.wrap(null);
+ }
+
+ 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页 ${tabInfo.name} 加载出现错误`);
+ updateTabInfo(tabInfo, tabStartTime, 'error');
+ return cy.wrap(null);
+ }
+
+ if (isLoading) {
+ cy.log(`⏳ [${currentPage.name}] Tab页 ${tabInfo.name} 第 ${retryCount + 1} 次检查加载状态...`);
+ return cy.wait(500).then(() => {
+ return waitForTabLoadWithTimeout(currentPage, tabInfo, tabStartTime, maxRetries, retryCount + 1);
});
- };
-
- waitForTabLoad();
+ } else {
+ updateTabInfo(tabInfo, tabStartTime, 'success');
+ cy.log(`✅ [${currentPage.name}] Tab页 ${tabInfo.name} 加载完成 (耗时: ${tabInfo.duration}秒)`);
+ return cy.wait(1000);
+ }
});
};
-
- processTab();
+
+ // 开始处理所有Tab
+ return processTabsSequentially($inactiveTabs);
};
// 处理页面中的tab页
@@ -510,38 +609,50 @@ describe('隆基系统全部页面验证', () => {
pageInfo.hasThirdMenu = true;
cy.log(`✓ ${menuText} 包含 ${$thirdMenuItems.length} 个三级菜单`);
- const processThirdMenu = (thirdIndex = 0) => {
- if (thirdIndex >= $thirdMenuItems.length) {
+ // 使用迭代方式处理三级菜单,避免深度递归
+ const processThirdMenuSequentially = (items, startIndex = 0) => {
+ if (startIndex >= items.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;
+ return cy.wait(1000).then(() => processMenuItems(index + 1));
}
- const thirdMenuProgress = ((thirdIndex + 1) / $thirdMenuItems.length * 100).toFixed(1);
+ const thirdMenuProgress = ((startIndex + 1) / items.length * 100).toFixed(1);
- if (thirdIndex > 0) {
- cy.wrap($menuItem).click();
- cy.wait(1000);
+ if (startIndex > 0) {
+ return cy.wrap($menuItem).click()
+ .wait(1000)
+ .then(() => {
+ return cy.get('@thirdMenuItems')
+ .eq(startIndex)
+ .then(processCurrentThirdMenuItem);
+ });
+ } else {
+ return cy.get('@thirdMenuItems')
+ .eq(startIndex)
+ .then(processCurrentThirdMenuItem);
}
- cy.get('@thirdMenuItems')
- .eq(thirdIndex)
- .then($thirdMenu => {
- const thirdMenuText = $thirdMenu.text().trim();
- cy.log(`\n🔸 处理三级菜单 [${thirdIndex + 1}/${$thirdMenuItems.length}] (${thirdMenuProgress}%): ${menuText} > ${thirdMenuText}`);
+ function processCurrentThirdMenuItem($thirdMenu) {
+ const thirdMenuText = $thirdMenu.text().trim();
+ cy.log(`\n🔸 处理三级菜单 [${startIndex + 1}/${items.length}] (${thirdMenuProgress}%): ${menuText} > ${thirdMenuText}`);
- const thirdMenuPage = new PageInfo(thirdMenuText, true, menuText).addToBatch();
+ const thirdMenuPage = new PageInfo(thirdMenuText, true, menuText).addToBatch();
- cy.wrap($thirdMenu).click();
- waitForPageLoad(thirdMenuPage, new Date());
- cy.wait(1000).then(() => processThirdMenu(thirdIndex + 1));
- });
+ return cy.wrap($thirdMenu).click()
+ .then(() => {
+ waitForPageLoad(thirdMenuPage, new Date());
+ return cy.wait(1000);
+ })
+ .then(() => {
+ return processThirdMenuSequentially(items, startIndex + 1);
+ });
+ }
};
- processThirdMenu();
+ return processThirdMenuSequentially($thirdMenuItems);
};
// 处理没有三级菜单的情况
@@ -609,35 +720,35 @@ describe('隆基系统全部页面验证', () => {
cy.log(`🔍 找到 ${menuItems.length} 个可测试的菜单项`);
// 创建菜单选择对话框
- const dialogHtml = `
-