优化文件路径
This commit is contained in:
parent
d793563006
commit
6b263fc83f
@ -115,6 +115,49 @@ class BasePage {
|
|||||||
await element.click(options);
|
await element.click(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全点击元素
|
||||||
|
* @param {Object} element Playwright元素对象
|
||||||
|
* @returns {Promise<boolean>} 是否点击成功
|
||||||
|
*/
|
||||||
|
async safeClick(element) {
|
||||||
|
try {
|
||||||
|
await element.click();
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`点击失败:`, error.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击元素并等待页面加载完成
|
||||||
|
* @param {string} selector 要点击的元素选择器
|
||||||
|
* @returns {Promise<boolean>} 操作是否成功
|
||||||
|
*/
|
||||||
|
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 元素选择器
|
* @param {string} selector 元素选择器
|
||||||
@ -126,34 +169,6 @@ class BasePage {
|
|||||||
await element.fill(value);
|
await element.fill(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取元素文本
|
|
||||||
* @param {string} selector 元素选择器
|
|
||||||
* @param {Object} options 选项
|
|
||||||
* @returns {Promise<string>} 元素文本
|
|
||||||
*/
|
|
||||||
async getText(selector, options = {}) {
|
|
||||||
const element = await this.waitForElement(selector, options);
|
|
||||||
return element.textContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查元素是否可见
|
|
||||||
* @param {string} selector 元素选择器
|
|
||||||
* @param {Object} options 选项
|
|
||||||
* @returns {Promise<boolean>} 元素是否可见
|
|
||||||
*/
|
|
||||||
async isVisible(selector, options = {}) {
|
|
||||||
try {
|
|
||||||
await this.waitForElement(selector, {
|
|
||||||
timeout: options.timeout || 1000
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 等待页面加载完成
|
* 等待页面加载完成
|
||||||
*/
|
*/
|
||||||
@ -186,15 +201,15 @@ class BasePage {
|
|||||||
if (hasError) return false;
|
if (hasError) return false;
|
||||||
|
|
||||||
// 检查加载状态
|
// 检查加载状态
|
||||||
const isLoading = await this.elementExists(this.selectors.loadingMask);
|
const isLoading = await this.elementExistsBySelector(this.selectors.loadingMask);
|
||||||
if (!isLoading) {
|
if (!isLoading) {
|
||||||
await this.wait(stabilityDelay);
|
await this.waitForTimeout(stabilityDelay);
|
||||||
console.log(`✅ 页面 ${pageName} 加载完成`);
|
console.log(`✅ 页面 ${pageName} 加载完成`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
retryCount++;
|
retryCount++;
|
||||||
await this.wait(retryInterval);
|
await this.waitForTimeout(retryInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(`页面加载超时: ${pageName}, 重试次数: ${maxRetries}`);
|
console.error(`页面加载超时: ${pageName}, 重试次数: ${maxRetries}`);
|
||||||
@ -226,28 +241,6 @@ class BasePage {
|
|||||||
return false;
|
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<string>} 页面标题
|
|
||||||
*/
|
|
||||||
async getTitle() {
|
|
||||||
return this.page.title();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前URL
|
* 获取当前URL
|
||||||
@ -257,62 +250,12 @@ class BasePage {
|
|||||||
return this.page.url();
|
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<string>} 属性值
|
|
||||||
*/
|
|
||||||
async getAttribute(selector, attributeName) {
|
|
||||||
const element = await this.waitForElement(selector);
|
|
||||||
return element.getAttribute(attributeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 安全点击元素
|
|
||||||
* @param {Object} element Playwright元素对象
|
|
||||||
* @returns {Promise<boolean>} 是否点击成功
|
|
||||||
*/
|
|
||||||
async safeClick(element) {
|
|
||||||
try {
|
|
||||||
await element.click();
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`点击失败:`, error.message);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 等待指定时间
|
* 等待指定时间
|
||||||
* @param {number} ms 等待时间(毫秒)
|
* @param {number} ms 等待时间(毫秒)
|
||||||
*/
|
*/
|
||||||
async wait(ms) {
|
async waitForTimeout(ms) {
|
||||||
await this.page.waitForTimeout(ms);
|
await this.page.waitForTimeout(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +264,7 @@ class BasePage {
|
|||||||
* @param {string} selector 元素选择器
|
* @param {string} selector 元素选择器
|
||||||
* @returns {Promise<boolean>} 是否存在
|
* @returns {Promise<boolean>} 是否存在
|
||||||
*/
|
*/
|
||||||
async elementExists(selector) {
|
async elementExistsBySelector(selector) {
|
||||||
const count = await this.page.locator(selector).count();
|
const count = await this.page.locator(selector).count();
|
||||||
return count > 0;
|
return count > 0;
|
||||||
}
|
}
|
||||||
@ -340,6 +283,7 @@ class BasePage {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = BasePage;
|
module.exports = BasePage;
|
||||||
@ -61,26 +61,17 @@ class LongiLoginPage extends BasePage {
|
|||||||
*/
|
*/
|
||||||
async clickLoginButton() {
|
async clickLoginButton() {
|
||||||
try {
|
try {
|
||||||
// 方法1: 使用更精确的选择器,指定包含特定类的按钮
|
await this.clickAndWaitForLoad(this.selectors.loginButton)
|
||||||
await this.click(this.selectors.loginButton);
|
|
||||||
// console.log('使用 container-button 类选择器成功点击登录按钮');
|
|
||||||
await this.waitForPageLoad();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('第一种方法失败,尝试备用方法...');
|
console.log('第一种方法失败,尝试备用方法...');
|
||||||
try {
|
try {
|
||||||
// 方法2: 使用精确文本匹配
|
await this.clickAndWaitForLoad(this.selectors.loginButtonByText)
|
||||||
await this.safeClick(await this.page.locator(this.selectors.loginButtonByText));
|
|
||||||
// console.log('使用精确文本匹配成功点击登录按钮');
|
|
||||||
await this.waitForPageLoad();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (secondError) {
|
} catch (secondError) {
|
||||||
console.log('第二种方法也失败,尝试第三种方法...');
|
console.log('第二种方法也失败,尝试第三种方法...');
|
||||||
try {
|
try {
|
||||||
// 方法3: 使用first()选择第一个匹配的按钮
|
await this.safeClickAndWaitForLoad(await this.page.locator(this.selectors.loginButtonFirst).first());
|
||||||
await this.safeClick(await this.page.locator(this.selectors.loginButtonFirst).first());
|
|
||||||
// console.log('使用first()方法成功点击登录按钮');
|
|
||||||
await this.waitForPageLoad();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (thirdError) {
|
} catch (thirdError) {
|
||||||
console.error('所有方法都失败,无法点击登录按钮', thirdError);
|
console.error('所有方法都失败,无法点击登录按钮', thirdError);
|
||||||
|
|||||||
@ -404,7 +404,7 @@ class LongiMainPage extends BasePage {
|
|||||||
* @param {Object} parentMenu 父级菜单(可选)
|
* @param {Object} parentMenu 父级菜单(可选)
|
||||||
*/
|
*/
|
||||||
async handleMenuClick(menuInfo, parentMenu = null) {
|
async handleMenuClick(menuInfo, parentMenu = null) {
|
||||||
const menuPath = await this.getMenuPath(menuInfo, parentMenu);
|
const menuPath = this.getMenuPath(menuInfo, parentMenu);
|
||||||
console.log(`点击菜单: ${menuPath}`);
|
console.log(`点击菜单: ${menuPath}`);
|
||||||
|
|
||||||
if (!await this.safeClick(menuInfo.element)) {
|
if (!await this.safeClick(menuInfo.element)) {
|
||||||
@ -444,7 +444,7 @@ class LongiMainPage extends BasePage {
|
|||||||
*/
|
*/
|
||||||
async handleAllTabs(menu) {
|
async handleAllTabs(menu) {
|
||||||
try {
|
try {
|
||||||
await this.wait(1000);
|
await this.waitForTimeout(1000);
|
||||||
|
|
||||||
const tabs = await this.page.locator(this.selectors.tabContainer).all();
|
const tabs = await this.page.locator(this.selectors.tabContainer).all();
|
||||||
if (tabs.length === 0) {
|
if (tabs.length === 0) {
|
||||||
@ -496,7 +496,7 @@ class LongiMainPage extends BasePage {
|
|||||||
if (await this.canCloseTab(activeTab, closeButton)) {
|
if (await this.canCloseTab(activeTab, closeButton)) {
|
||||||
await closeButton.waitFor({state: 'visible', timeout: 5000});
|
await closeButton.waitFor({state: 'visible', timeout: 5000});
|
||||||
await this.safeClick(closeButton);
|
await this.safeClick(closeButton);
|
||||||
await this.wait(500);
|
await this.waitForTimeout(500);
|
||||||
} else {
|
} else {
|
||||||
console.log(`⚠️ [${parentMenu.text}] 没有找到可关闭的tab,继续执行...`);
|
console.log(`⚠️ [${parentMenu.text}] 没有找到可关闭的tab,继续执行...`);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user