dasdasd
This commit is contained in:
parent
8ebb7779e0
commit
ae1720c866
@ -1,5 +1,6 @@
|
|||||||
const BaseAction = require('../core/base-action');
|
const BaseAction = require('../core/base-action');
|
||||||
const SmartSelector = require('../core/smart-selector');
|
const SmartSelector = require('../core/smart-selector');
|
||||||
|
const { ConfigurationError, ElementNotFoundError, ValidationError } = require('../core/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 点击动作
|
* 点击动作
|
||||||
@ -9,7 +10,11 @@ class ClickAction extends BaseAction {
|
|||||||
const selector = this.config.selector || this.config.find;
|
const selector = this.config.selector || this.config.find;
|
||||||
|
|
||||||
if (!selector) {
|
if (!selector) {
|
||||||
throw new Error('缺少选择器配置');
|
throw new ConfigurationError(
|
||||||
|
'缺少选择器配置',
|
||||||
|
'selector',
|
||||||
|
{ action: 'click', config: this.config }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('info', '执行点击');
|
this.log('info', '执行点击');
|
||||||
@ -19,7 +24,10 @@ class ClickAction extends BaseAction {
|
|||||||
const element = await smartSelector.find(this.config.timeout || 10000);
|
const element = await smartSelector.find(this.config.timeout || 10000);
|
||||||
|
|
||||||
if (!element) {
|
if (!element) {
|
||||||
throw new Error(`无法找到元素: ${JSON.stringify(selector)}`);
|
throw new ElementNotFoundError(selector, {
|
||||||
|
action: 'click',
|
||||||
|
timeout: this.config.timeout || 10000
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待元素变为可点击状态(参考旧框架)
|
// 等待元素变为可点击状态(参考旧框架)
|
||||||
@ -169,7 +177,11 @@ class ClickAction extends BaseAction {
|
|||||||
const element = await smartSelector.find(5000);
|
const element = await smartSelector.find(5000);
|
||||||
|
|
||||||
if (!element) {
|
if (!element) {
|
||||||
throw new Error(`重新查找元素失败: ${JSON.stringify(selectorConfig)}`);
|
throw new ElementNotFoundError(selectorConfig, {
|
||||||
|
action: 'click',
|
||||||
|
operation: 'humanClick',
|
||||||
|
reason: '重新定位失败'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('debug', '✓ 已重新定位元素');
|
this.log('debug', '✓ 已重新定位元素');
|
||||||
@ -250,7 +262,12 @@ class ClickAction extends BaseAction {
|
|||||||
await this.page.waitForSelector(selector, { timeout, visible: true });
|
await this.page.waitForSelector(selector, { timeout, visible: true });
|
||||||
this.log('debug', `✓ 新元素已出现: ${selector}`);
|
this.log('debug', `✓ 新元素已出现: ${selector}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`点击后验证失败: 元素 "${selector}" 未出现`);
|
throw new ValidationError(
|
||||||
|
`点击后验证失败: 元素未出现`,
|
||||||
|
'元素出现',
|
||||||
|
'元素未找到',
|
||||||
|
{ selector, timeout }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,7 +280,12 @@ class ClickAction extends BaseAction {
|
|||||||
await this.page.waitForSelector(selector, { timeout, hidden: true });
|
await this.page.waitForSelector(selector, { timeout, hidden: true });
|
||||||
this.log('debug', `✓ 旧元素已消失: ${selector}`);
|
this.log('debug', `✓ 旧元素已消失: ${selector}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`点击后验证失败: 元素 "${selector}" 未消失`);
|
throw new ValidationError(
|
||||||
|
`点击后验证失败: 元素未消失`,
|
||||||
|
'元素消失',
|
||||||
|
'元素仍存在',
|
||||||
|
{ selector, timeout }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,7 +317,11 @@ class ClickAction extends BaseAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cssSelector) {
|
if (!cssSelector) {
|
||||||
throw new Error('无法从选择器配置中提取 CSS 选择器');
|
throw new ConfigurationError(
|
||||||
|
'无法从选择器配置中提取 CSS 选择器',
|
||||||
|
'selector',
|
||||||
|
{ verifyAfter, selectorConfig }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isChecked = await this.page.evaluate((sel) => {
|
const isChecked = await this.page.evaluate((sel) => {
|
||||||
@ -305,7 +331,12 @@ class ClickAction extends BaseAction {
|
|||||||
|
|
||||||
const expectedState = checked === true;
|
const expectedState = checked === true;
|
||||||
if (isChecked !== expectedState) {
|
if (isChecked !== expectedState) {
|
||||||
throw new Error(`点击后验证失败: 元素 checked 状态为 ${isChecked},期望 ${expectedState}`);
|
throw new ValidationError(
|
||||||
|
`点击后验证失败: checked 状态不符`,
|
||||||
|
expectedState,
|
||||||
|
isChecked,
|
||||||
|
{ cssSelector }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('debug', `✓ checked 状态验证通过: ${isChecked}`);
|
this.log('debug', `✓ checked 状态验证通过: ${isChecked}`);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
const BaseAction = require('../core/base-action');
|
const BaseAction = require('../core/base-action');
|
||||||
const SmartSelector = require('../core/smart-selector');
|
const SmartSelector = require('../core/smart-selector');
|
||||||
|
const { ConfigurationError, ElementNotFoundError, TimeoutError } = require('../core/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 填充表单动作
|
* 填充表单动作
|
||||||
@ -10,7 +11,11 @@ class FillFormAction extends BaseAction {
|
|||||||
const humanLike = this.config.humanLike !== false; // 默认使用人类行为
|
const humanLike = this.config.humanLike !== false; // 默认使用人类行为
|
||||||
|
|
||||||
if (!fields || typeof fields !== 'object') {
|
if (!fields || typeof fields !== 'object') {
|
||||||
throw new Error('表单字段配置无效');
|
throw new ConfigurationError(
|
||||||
|
'表单字段配置无效',
|
||||||
|
'fields',
|
||||||
|
{ provided: typeof fields, config: this.config }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('info', `填写表单,共 ${Object.keys(fields).length} 个字段`);
|
this.log('info', `填写表单,共 ${Object.keys(fields).length} 个字段`);
|
||||||
@ -71,7 +76,11 @@ class FillFormAction extends BaseAction {
|
|||||||
const element = await smartSelector.find(10000);
|
const element = await smartSelector.find(10000);
|
||||||
|
|
||||||
if (!element) {
|
if (!element) {
|
||||||
throw new Error(`无法找到字段: ${JSON.stringify(selector)}`);
|
throw new ElementNotFoundError(selector, {
|
||||||
|
action: 'fillForm',
|
||||||
|
field: key,
|
||||||
|
value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('debug', ` → 填写字段: ${key}`);
|
this.log('debug', ` → 填写字段: ${key}`);
|
||||||
@ -85,7 +94,11 @@ class FillFormAction extends BaseAction {
|
|||||||
// 下拉框选择(需要 CSS 选择器)
|
// 下拉框选择(需要 CSS 选择器)
|
||||||
const cssSelector = selector.css || selector[0]?.css;
|
const cssSelector = selector.css || selector[0]?.css;
|
||||||
if (!cssSelector) {
|
if (!cssSelector) {
|
||||||
throw new Error(`select 类型字段需要 css 选择器: ${JSON.stringify(selector)}`);
|
throw new ConfigurationError(
|
||||||
|
`select 类型字段需要 css 选择器`,
|
||||||
|
'selector',
|
||||||
|
{ field: key, selector, fieldType }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
await this.page.select(cssSelector, value);
|
await this.page.select(cssSelector, value);
|
||||||
this.log('debug', ` → 已选择: ${value}`);
|
this.log('debug', ` → 已选择: ${value}`);
|
||||||
@ -146,7 +159,10 @@ class FillFormAction extends BaseAction {
|
|||||||
const button = await smartSelector.find(10000);
|
const button = await smartSelector.find(10000);
|
||||||
|
|
||||||
if (!button) {
|
if (!button) {
|
||||||
throw new Error(`无法找到提交按钮: ${JSON.stringify(selector)}`);
|
throw new ElementNotFoundError(selector, {
|
||||||
|
action: 'fillForm',
|
||||||
|
operation: 'submitForm'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待按钮可点击
|
// 等待按钮可点击
|
||||||
@ -179,7 +195,10 @@ class FillFormAction extends BaseAction {
|
|||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('按钮未启用(超时)');
|
throw new TimeoutError('等待按钮启用', timeout, {
|
||||||
|
action: 'fillForm',
|
||||||
|
selector
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
const BaseAction = require('../core/base-action');
|
const BaseAction = require('../core/base-action');
|
||||||
|
const { ValidationError, ElementNotFoundError } = require('../core/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导航动作 - 打开页面
|
* 导航动作 - 打开页面
|
||||||
@ -39,7 +40,12 @@ class NavigateAction extends BaseAction {
|
|||||||
// 验证页面URL是否正确(避免重定向到会员中心等)
|
// 验证页面URL是否正确(避免重定向到会员中心等)
|
||||||
const currentUrl = this.page.url();
|
const currentUrl = this.page.url();
|
||||||
if (this.config.verifyUrl && !currentUrl.includes(this.config.verifyUrl)) {
|
if (this.config.verifyUrl && !currentUrl.includes(this.config.verifyUrl)) {
|
||||||
throw new Error(`页面跳转异常: 期望包含 "${this.config.verifyUrl}", 实际为 "${currentUrl}"`);
|
throw new ValidationError(
|
||||||
|
`页面跳转异常`,
|
||||||
|
`URL包含: ${this.config.verifyUrl}`,
|
||||||
|
`实际URL: ${currentUrl}`,
|
||||||
|
{ expectedUrl: this.config.verifyUrl, actualUrl: currentUrl }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证关键元素存在(确保页面加载正确)
|
// 验证关键元素存在(确保页面加载正确)
|
||||||
@ -86,7 +92,11 @@ class NavigateAction extends BaseAction {
|
|||||||
try {
|
try {
|
||||||
await this.page.waitForSelector(selector, { timeout: 10000 });
|
await this.page.waitForSelector(selector, { timeout: 10000 });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(`页面元素验证失败: 找不到 "${selector}"`);
|
throw new ElementNotFoundError(selector, {
|
||||||
|
action: 'navigate',
|
||||||
|
operation: 'verifyElements',
|
||||||
|
url: this.page.url()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user