diff --git a/tests/pages/BasePage.js b/tests/pages/BasePage.js index b220dd7..1ed3140 100644 --- a/tests/pages/BasePage.js +++ b/tests/pages/BasePage.js @@ -115,6 +115,49 @@ class BasePage { await element.click(options); } + /** + * 安全点击元素 + * @param {Object} element Playwright元素对象 + * @returns {Promise} 是否点击成功 + */ + async safeClick(element) { + try { + await element.click(); + return true; + } catch (error) { + console.error(`点击失败:`, error.message); + return false; + } + } + + /** + * 点击元素并等待页面加载完成 + * @param {string} selector 要点击的元素选择器 + * @returns {Promise} 操作是否成功 + */ + async clickAndWaitForLoad(selector) { + try { + const element = await this.waitForElement(selector); + await element.click(); + await this.waitForPageLoad(); + return true; + } catch (error) { + console.error(`点击元素并等待页面加载失败: ${error.message}`); + return false; + } + } + + async safeClickAndWaitForLoad(element) { + try { + await this.click(element); + await this.waitForPageLoad(); + return true; + } catch (error) { + console.error(`点击元素并等待页面加载失败: ${error.message}`); + return false; + } + } + /** * 填写表单字段 * @param {string} selector 元素选择器 @@ -126,39 +169,11 @@ class BasePage { await element.fill(value); } - /** - * 获取元素文本 - * @param {string} selector 元素选择器 - * @param {Object} options 选项 - * @returns {Promise} 元素文本 - */ - async getText(selector, options = {}) { - const element = await this.waitForElement(selector, options); - return element.textContent(); - } - - /** - * 检查元素是否可见 - * @param {string} selector 元素选择器 - * @param {Object} options 选项 - * @returns {Promise} 元素是否可见 - */ - async isVisible(selector, options = {}) { - try { - await this.waitForElement(selector, { - timeout: options.timeout || 1000 - }); - return true; - } catch (error) { - return false; - } - } - /** * 等待页面加载完成 */ async waitForPageLoad() { - await this.page.waitForLoadState('networkidle', { + await this.page.waitForLoadState('networkidle', { timeout: 30000 }); } @@ -169,7 +184,7 @@ class BasePage { * 1. 检查el-loading-mask是否存在 * 2. 检查系统特定的错误提示 * 3. 等待页面稳定 - * + * * @param {string} pageName 页面名称,用于日志显示 * @returns {Promise} 页面是否加载成功 */ @@ -186,15 +201,15 @@ class BasePage { if (hasError) return false; // 检查加载状态 - const isLoading = await this.elementExists(this.selectors.loadingMask); + const isLoading = await this.elementExistsBySelector(this.selectors.loadingMask); if (!isLoading) { - await this.wait(stabilityDelay); + await this.waitForTimeout(stabilityDelay); console.log(`✅ 页面 ${pageName} 加载完成`); return true; } retryCount++; - await this.wait(retryInterval); + await this.waitForTimeout(retryInterval); } console.error(`页面加载超时: ${pageName}, 重试次数: ${maxRetries}`); @@ -226,28 +241,6 @@ class BasePage { return false; } - /** - * 获取上下文名称 - * @param {Object} context 上下文信息对象 - * @param {string} [subContext] 子上下文信息 - * @returns {string} 格式化的上下文名称 - * @private - */ - getContextName(context, subContext = '') { - if (typeof context === 'string') { - return context; - } - const mainText = context.text || context.path || 'Unknown'; - return subContext ? `${mainText} > ${subContext}` : mainText; - } - - /** - * 获取页面标题 - * @returns {Promise} 页面标题 - */ - async getTitle() { - return this.page.title(); - } /** * 获取当前URL @@ -257,62 +250,12 @@ class BasePage { return this.page.url(); } - /** - * 截取页面截图 - * @param {string} name 截图名称 - * @param {Object} options 截图选项 - */ - async takeScreenshot(name, options = {}) { - const screenshotPath = options.path || `./screenshots/${name}_${Date.now()}.png`; - await this.page.screenshot({ - path: screenshotPath, - fullPage: options.fullPage || false, - ...options - }); - return screenshotPath; - } - - /** - * 选择下拉菜单选项 - * @param {string} selector 下拉菜单选择器 - * @param {string} value 要选择的值 - */ - async selectOption(selector, value) { - const element = await this.waitForElement(selector); - await element.selectOption(value); - } - - /** - * 获取元素属性值 - * @param {string} selector 元素选择器 - * @param {string} attributeName 属性名 - * @returns {Promise} 属性值 - */ - async getAttribute(selector, attributeName) { - const element = await this.waitForElement(selector); - return element.getAttribute(attributeName); - } - - /** - * 安全点击元素 - * @param {Object} element Playwright元素对象 - * @returns {Promise} 是否点击成功 - */ - async safeClick(element) { - try { - await element.click(); - return true; - } catch (error) { - console.error(`点击失败:`, error.message); - return false; - } - } /** * 等待指定时间 * @param {number} ms 等待时间(毫秒) */ - async wait(ms) { + async waitForTimeout(ms) { await this.page.waitForTimeout(ms); } @@ -321,7 +264,7 @@ class BasePage { * @param {string} selector 元素选择器 * @returns {Promise} 是否存在 */ - async elementExists(selector) { + async elementExistsBySelector(selector) { const count = await this.page.locator(selector).count(); return count > 0; } @@ -340,6 +283,7 @@ class BasePage { return ''; } } + } module.exports = BasePage; \ No newline at end of file diff --git a/tests/pages/LongiLoginPage.js b/tests/pages/LongiLoginPage.js index 4114927..e05bbff 100644 --- a/tests/pages/LongiLoginPage.js +++ b/tests/pages/LongiLoginPage.js @@ -61,26 +61,17 @@ class LongiLoginPage extends BasePage { */ async clickLoginButton() { try { - // 方法1: 使用更精确的选择器,指定包含特定类的按钮 - await this.click(this.selectors.loginButton); - // console.log('使用 container-button 类选择器成功点击登录按钮'); - await this.waitForPageLoad(); + await this.clickAndWaitForLoad(this.selectors.loginButton) return true; } catch (error) { console.log('第一种方法失败,尝试备用方法...'); try { - // 方法2: 使用精确文本匹配 - await this.safeClick(await this.page.locator(this.selectors.loginButtonByText)); - // console.log('使用精确文本匹配成功点击登录按钮'); - await this.waitForPageLoad(); + await this.clickAndWaitForLoad(this.selectors.loginButtonByText) return true; } catch (secondError) { console.log('第二种方法也失败,尝试第三种方法...'); try { - // 方法3: 使用first()选择第一个匹配的按钮 - await this.safeClick(await this.page.locator(this.selectors.loginButtonFirst).first()); - // console.log('使用first()方法成功点击登录按钮'); - await this.waitForPageLoad(); + await this.safeClickAndWaitForLoad(await this.page.locator(this.selectors.loginButtonFirst).first()); return true; } catch (thirdError) { console.error('所有方法都失败,无法点击登录按钮', thirdError); diff --git a/tests/pages/LongiMainPage.js b/tests/pages/LongiMainPage.js index 6171659..5a1de25 100644 --- a/tests/pages/LongiMainPage.js +++ b/tests/pages/LongiMainPage.js @@ -404,7 +404,7 @@ class LongiMainPage extends BasePage { * @param {Object} parentMenu 父级菜单(可选) */ async handleMenuClick(menuInfo, parentMenu = null) { - const menuPath = await this.getMenuPath(menuInfo, parentMenu); + const menuPath = this.getMenuPath(menuInfo, parentMenu); console.log(`点击菜单: ${menuPath}`); if (!await this.safeClick(menuInfo.element)) { @@ -444,7 +444,7 @@ class LongiMainPage extends BasePage { */ async handleAllTabs(menu) { try { - await this.wait(1000); + await this.waitForTimeout(1000); const tabs = await this.page.locator(this.selectors.tabContainer).all(); if (tabs.length === 0) { @@ -496,7 +496,7 @@ class LongiMainPage extends BasePage { if (await this.canCloseTab(activeTab, closeButton)) { await closeButton.waitFor({state: 'visible', timeout: 5000}); await this.safeClick(closeButton); - await this.wait(500); + await this.waitForTimeout(500); } else { console.log(`⚠️ [${parentMenu.text}] 没有找到可关闭的tab,继续执行...`); }