ectrol 0.0.4 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +41 -15
- package/dist/index.mjs +145 -126
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -41,7 +41,6 @@ interface ISize {
|
|
|
41
41
|
declare class ElementHandle {
|
|
42
42
|
readonly contents: WebContents;
|
|
43
43
|
readonly selector: string;
|
|
44
|
-
isNotFound: boolean;
|
|
45
44
|
constructor(contents: WebContents, selector: string);
|
|
46
45
|
/**
|
|
47
46
|
* 生成在 renderer 端执行的查找脚本。
|
|
@@ -53,7 +52,9 @@ declare class ElementHandle {
|
|
|
53
52
|
/**
|
|
54
53
|
* 触发元素 mouseover 事件(不移动真实鼠标)。
|
|
55
54
|
*/
|
|
56
|
-
hover(
|
|
55
|
+
hover(options?: {
|
|
56
|
+
timeout?: number;
|
|
57
|
+
}): Promise<any>;
|
|
57
58
|
/**
|
|
58
59
|
* 点击
|
|
59
60
|
* - 通过 WebContents.sendInputEvent 发送 mouseDown/mouseUp 事件
|
|
@@ -83,7 +84,9 @@ declare class ElementHandle {
|
|
|
83
84
|
/**
|
|
84
85
|
* 将复选框或单选按钮设为选中,并派发 change 事件。
|
|
85
86
|
*/
|
|
86
|
-
check(
|
|
87
|
+
check(options?: {
|
|
88
|
+
timeout?: number;
|
|
89
|
+
}): Promise<any>;
|
|
87
90
|
/**
|
|
88
91
|
* 填充输入框内容。
|
|
89
92
|
* - 适用于 `<input>`、`<textarea>` 或 `contenteditable` 元素。
|
|
@@ -131,55 +134,77 @@ declare class ElementHandle {
|
|
|
131
134
|
* @param value 选项的值
|
|
132
135
|
* @returns
|
|
133
136
|
*/
|
|
134
|
-
selectOption(value: string
|
|
137
|
+
selectOption(value: string, options?: {
|
|
138
|
+
timeout?: number;
|
|
139
|
+
}): Promise<any>;
|
|
135
140
|
/**
|
|
136
141
|
* 获取元素的 HTML 内容。
|
|
137
142
|
*/
|
|
138
|
-
innerHTML(
|
|
143
|
+
innerHTML(options?: {
|
|
144
|
+
timeout?: number;
|
|
145
|
+
}): Promise<any>;
|
|
139
146
|
/**
|
|
140
147
|
* 获取元素的文本内容。
|
|
141
148
|
*/
|
|
142
|
-
innerText(
|
|
149
|
+
innerText(options?: {
|
|
150
|
+
timeout?: number;
|
|
151
|
+
}): Promise<any>;
|
|
143
152
|
/**
|
|
144
153
|
* 获取元素的文本内容。
|
|
145
154
|
* @returns 元素的文本内容
|
|
146
155
|
*/
|
|
147
|
-
textContent(
|
|
156
|
+
textContent(options?: {
|
|
157
|
+
timeout?: number;
|
|
158
|
+
}): Promise<any>;
|
|
148
159
|
/**
|
|
149
160
|
* 获取元素的输入值。
|
|
150
161
|
* @returns 元素的输入值
|
|
151
162
|
*/
|
|
152
|
-
inputValue(
|
|
163
|
+
inputValue(options?: {
|
|
164
|
+
timeout?: number;
|
|
165
|
+
}): Promise<any>;
|
|
153
166
|
/**
|
|
154
167
|
* 获取元素的选中状态。
|
|
155
168
|
* @returns 元素的选中状态
|
|
156
169
|
*/
|
|
157
|
-
isChecked(
|
|
170
|
+
isChecked(options?: {
|
|
171
|
+
timeout?: number;
|
|
172
|
+
}): Promise<any>;
|
|
158
173
|
/**
|
|
159
174
|
* 获取元素的禁用状态。
|
|
160
175
|
* @returns 元素的禁用状态
|
|
161
176
|
*/
|
|
162
|
-
isDisabled(
|
|
177
|
+
isDisabled(options?: {
|
|
178
|
+
timeout?: number;
|
|
179
|
+
}): Promise<any>;
|
|
163
180
|
/**
|
|
164
181
|
* 获取元素的可见状态。
|
|
165
182
|
* @returns 元素的可见状态
|
|
166
183
|
*/
|
|
167
|
-
isVisible(
|
|
184
|
+
isVisible(options?: {
|
|
185
|
+
timeout?: number;
|
|
186
|
+
}): Promise<any>;
|
|
168
187
|
/**
|
|
169
188
|
* 获取元素的可用状态。
|
|
170
189
|
* @returns 元素的可用状态
|
|
171
190
|
*/
|
|
172
|
-
isEnabled(
|
|
191
|
+
isEnabled(options?: {
|
|
192
|
+
timeout?: number;
|
|
193
|
+
}): Promise<any>;
|
|
173
194
|
/**
|
|
174
195
|
* 获取元素的可编辑状态。
|
|
175
196
|
* @returns 元素的可编辑状态
|
|
176
197
|
*/
|
|
177
|
-
isEditable(
|
|
198
|
+
isEditable(options?: {
|
|
199
|
+
timeout?: number;
|
|
200
|
+
}): Promise<any>;
|
|
178
201
|
/**
|
|
179
202
|
* 获取元素的隐藏状态。
|
|
180
203
|
* @returns 元素的隐藏状态
|
|
181
204
|
*/
|
|
182
|
-
isHidden(
|
|
205
|
+
isHidden(options?: {
|
|
206
|
+
timeout?: number;
|
|
207
|
+
}): Promise<any>;
|
|
183
208
|
/**
|
|
184
209
|
* 选中元素的文本内容。
|
|
185
210
|
*/
|
|
@@ -245,6 +270,7 @@ declare class SessionStorage {
|
|
|
245
270
|
}
|
|
246
271
|
//#endregion
|
|
247
272
|
//#region src/utils.d.ts
|
|
273
|
+
declare function randomInRange(min: number, max: number, integer?: boolean): number;
|
|
248
274
|
declare function getHumanTypingDelay(index: number, text: string): number;
|
|
249
275
|
declare function sleep(ms: number): Promise<unknown>;
|
|
250
276
|
//#endregion
|
|
@@ -272,4 +298,4 @@ declare class Ectrol {
|
|
|
272
298
|
$(selector: string): ElementHandle;
|
|
273
299
|
}
|
|
274
300
|
//#endregion
|
|
275
|
-
export { Ectrol, Ectrol as default, ElementHandle, IBoundingClientRect, ISize, IVector2D, LocalStorage, SessionStorage, getHumanTypingDelay, sleep };
|
|
301
|
+
export { Ectrol, Ectrol as default, ElementHandle, IBoundingClientRect, ISize, IVector2D, LocalStorage, SessionStorage, getHumanTypingDelay, randomInRange, sleep };
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
//#region src/utils.ts
|
|
2
|
+
function randomInRange(min, max, integer = false) {
|
|
3
|
+
if (min > max) [min, max] = [max, min];
|
|
4
|
+
const value = Math.random() * (max - min) + min;
|
|
5
|
+
return integer ? Math.floor(value) : value;
|
|
6
|
+
}
|
|
2
7
|
function getHumanTypingDelay(index, text) {
|
|
3
8
|
const char = text[index];
|
|
4
|
-
let delay =
|
|
9
|
+
let delay = randomInRange(16, 100);
|
|
5
10
|
const progress = index / text.length;
|
|
6
11
|
if (progress < .15) delay *= 1.3;
|
|
7
12
|
else if (progress > .85) delay *= 1.25;
|
|
8
|
-
if (char === " ") delay +=
|
|
9
|
-
if (/[,.!?;:]/.test(char)) delay +=
|
|
10
|
-
if (Math.random() < .03) delay +=
|
|
13
|
+
if (char === " ") delay += 16;
|
|
14
|
+
if (/[,.!?;:]/.test(char)) delay += randomInRange(16, 50);
|
|
15
|
+
if (Math.random() < .03) delay += randomInRange(100, 200);
|
|
11
16
|
return Math.max(40, Math.round(delay));
|
|
12
17
|
}
|
|
13
18
|
async function sleep(ms) {
|
|
@@ -24,7 +29,6 @@ async function sleep(ms) {
|
|
|
24
29
|
* - 大多数 API 接受 `timeout`,轮询查找元素直到超时
|
|
25
30
|
*/
|
|
26
31
|
var ElementHandle = class {
|
|
27
|
-
isNotFound = false;
|
|
28
32
|
constructor(contents, selector) {
|
|
29
33
|
this.contents = contents;
|
|
30
34
|
this.selector = selector;
|
|
@@ -37,104 +41,116 @@ var ElementHandle = class {
|
|
|
37
41
|
*/
|
|
38
42
|
_getElement(timeout = 0) {
|
|
39
43
|
return `
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
new Promise((resolve) => {
|
|
45
|
+
function getElement() {
|
|
46
|
+
const selector = "${this.selector}";
|
|
47
|
+
if (!selector) return null;
|
|
48
|
+
|
|
49
|
+
window.__ELECTROL__ = window.__ELECTROL__ || {};
|
|
50
|
+
if (window.__ELECTROL__[selector]) {
|
|
51
|
+
return window.__ELECTROL__[selector];
|
|
52
|
+
}
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return
|
|
49
|
-
}
|
|
54
|
+
// 分层选择器,支持 iframe 穿越
|
|
55
|
+
const parts = selector.split('|>').map(s => s.trim());
|
|
56
|
+
if (!parts.length) return null;
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
58
|
+
let currentDocument = document;
|
|
59
|
+
let offsetLeft = 0;
|
|
60
|
+
let offsetTop = 0;
|
|
61
|
+
let element = null;
|
|
54
62
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
let offsetTop = 0;
|
|
58
|
-
let element = null;
|
|
63
|
+
for (let i = 0; i < parts.length; i++) {
|
|
64
|
+
if (!currentDocument) return null;
|
|
59
65
|
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
const part = parts[i];
|
|
67
|
+
// 在当前文档查找该层选择器
|
|
68
|
+
const el = currentDocument.querySelector(part);
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
if (!el) {
|
|
71
|
+
console.warn('未找到元素:', part);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
66
74
|
|
|
67
|
-
|
|
68
|
-
console.warn('未找到元素:', part);
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
75
|
+
const rect = el.getBoundingClientRect();
|
|
71
76
|
|
|
72
|
-
|
|
77
|
+
// 累加当前层级偏移
|
|
78
|
+
offsetLeft += rect.left;
|
|
79
|
+
offsetTop += rect.top;
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
offsetLeft += rect.left;
|
|
76
|
-
offsetTop += rect.top;
|
|
81
|
+
element = el;
|
|
77
82
|
|
|
78
|
-
|
|
83
|
+
const isLast = i === parts.length - 1;
|
|
84
|
+
if (!isLast) {
|
|
85
|
+
if (el.tagName !== 'IFRAME') {
|
|
86
|
+
console.warn('非 iframe 元素却尝试进入下一层:', part);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
79
89
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
90
|
+
const nextDoc = el.contentDocument || el.contentWindow?.document;
|
|
91
|
+
if (!nextDoc) {
|
|
92
|
+
console.warn('无法访问 iframe.contentDocument(可能跨域)');
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
86
95
|
|
|
87
|
-
|
|
88
|
-
if (!nextDoc) {
|
|
89
|
-
console.warn('无法访问 iframe.contentDocument(可能跨域)');
|
|
90
|
-
return null;
|
|
96
|
+
currentDocument = nextDoc;
|
|
91
97
|
}
|
|
92
|
-
|
|
93
|
-
currentDocument = nextDoc;
|
|
94
98
|
}
|
|
95
|
-
}
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
if (!element) return null;
|
|
98
101
|
|
|
99
|
-
|
|
102
|
+
const finalRect = element.getBoundingClientRect();
|
|
100
103
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
// 缓存元素
|
|
105
|
+
// 缓存以避免重复查找
|
|
106
|
+
window.__ELECTROL__[selector] = {
|
|
107
|
+
element,
|
|
108
|
+
rect: new DOMRect(
|
|
109
|
+
offsetLeft,
|
|
110
|
+
offsetTop,
|
|
111
|
+
finalRect.width,
|
|
112
|
+
finalRect.height
|
|
113
|
+
)
|
|
114
|
+
};
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
116
|
+
return window.__ELECTROL__[selector]
|
|
117
|
+
}
|
|
115
118
|
|
|
116
|
-
|
|
119
|
+
const timeout = ${timeout}
|
|
117
120
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
// 轮询查找元素
|
|
122
|
+
const interval = setInterval(() => {
|
|
123
|
+
const element = getElement();
|
|
124
|
+
if (element) {
|
|
125
|
+
clearInterval(interval);
|
|
126
|
+
clearTimeout(timeoutId);
|
|
127
|
+
resolve(element);
|
|
128
|
+
}
|
|
129
|
+
}, 100);
|
|
130
|
+
|
|
131
|
+
// 超时处理
|
|
132
|
+
const timeoutId = setTimeout(() => {
|
|
133
|
+
clearInterval(interval);
|
|
134
|
+
resolve(null);
|
|
135
|
+
}, timeout);
|
|
121
136
|
|
|
122
|
-
const startTime = Date.now()
|
|
123
|
-
while (Date.now() - startTime < timeout) {
|
|
124
137
|
const element = getElement();
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
138
|
+
|
|
139
|
+
if (element) {
|
|
140
|
+
clearInterval(interval);
|
|
141
|
+
clearTimeout(timeoutId);
|
|
142
|
+
resolve(element);
|
|
143
|
+
}
|
|
144
|
+
})
|
|
129
145
|
`;
|
|
130
146
|
}
|
|
131
147
|
/**
|
|
132
148
|
* 触发元素 mouseover 事件(不移动真实鼠标)。
|
|
133
149
|
*/
|
|
134
|
-
hover() {
|
|
150
|
+
hover(options) {
|
|
135
151
|
return this.contents.executeJavaScript(`
|
|
136
|
-
(
|
|
137
|
-
const target = ${this._getElement()};
|
|
152
|
+
(async () => {
|
|
153
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
138
154
|
if (!target) return null;
|
|
139
155
|
|
|
140
156
|
const event = new MouseEvent('mouseover', {
|
|
@@ -197,10 +213,10 @@ var ElementHandle = class {
|
|
|
197
213
|
/**
|
|
198
214
|
* 将复选框或单选按钮设为选中,并派发 change 事件。
|
|
199
215
|
*/
|
|
200
|
-
check() {
|
|
216
|
+
check(options) {
|
|
201
217
|
return this.contents.executeJavaScript(`
|
|
202
|
-
(
|
|
203
|
-
const target = ${this._getElement()};
|
|
218
|
+
(async () => {
|
|
219
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
204
220
|
if (!target) return null;
|
|
205
221
|
|
|
206
222
|
// 验证输入框是否是复选框或单选按钮
|
|
@@ -226,8 +242,8 @@ var ElementHandle = class {
|
|
|
226
242
|
let interval;
|
|
227
243
|
if (typeof options?.interval === "number") interval = options?.interval;
|
|
228
244
|
if (!options?.append) await this.contents.executeJavaScript(`
|
|
229
|
-
(
|
|
230
|
-
const target = ${this._getElement(options?.timeout)};
|
|
245
|
+
(async () => {
|
|
246
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
231
247
|
if (target && target.element) {
|
|
232
248
|
if (target.element.tagName !== 'INPUT' && target.element.tagName !== 'TEXTAREA' && !target.element.isContentEditable) return null;
|
|
233
249
|
target.element.value = "";
|
|
@@ -268,8 +284,8 @@ var ElementHandle = class {
|
|
|
268
284
|
*/
|
|
269
285
|
async focus(options) {
|
|
270
286
|
return this.contents.executeJavaScript(`
|
|
271
|
-
(
|
|
272
|
-
const target = ${this._getElement(options?.timeout)};
|
|
287
|
+
(async () => {
|
|
288
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
273
289
|
if (!target) return null;
|
|
274
290
|
|
|
275
291
|
// 验证输入框是否是文本类型
|
|
@@ -283,18 +299,21 @@ var ElementHandle = class {
|
|
|
283
299
|
* 检查元素是否存在(支持超时轮询)。
|
|
284
300
|
*/
|
|
285
301
|
async exist(timeout) {
|
|
286
|
-
return await this.contents.executeJavaScript(
|
|
302
|
+
return await this.contents.executeJavaScript(`
|
|
303
|
+
(async () => {
|
|
304
|
+
const target = await ${this._getElement(timeout)};
|
|
305
|
+
return !!target;
|
|
306
|
+
})()
|
|
307
|
+
`);
|
|
287
308
|
}
|
|
288
309
|
/**
|
|
289
310
|
* 获取元素的位置信息。
|
|
290
311
|
* - 返回扩展的 DOMRect 信息并包含元素中心点坐标。
|
|
291
312
|
*/
|
|
292
313
|
getBoundingClientRect(timeout = 0) {
|
|
293
|
-
if (this.isNotFound) return Promise.resolve(null);
|
|
294
314
|
return this.contents.executeJavaScript(`
|
|
295
|
-
(
|
|
296
|
-
const target = ${this._getElement(timeout)};
|
|
297
|
-
|
|
315
|
+
(async () => {
|
|
316
|
+
const target = await ${this._getElement(timeout)};
|
|
298
317
|
if (!target) return null;
|
|
299
318
|
|
|
300
319
|
const rect = target.rect;
|
|
@@ -318,10 +337,10 @@ var ElementHandle = class {
|
|
|
318
337
|
* @param value 选项的值
|
|
319
338
|
* @returns
|
|
320
339
|
*/
|
|
321
|
-
async selectOption(value) {
|
|
340
|
+
async selectOption(value, options) {
|
|
322
341
|
return this.contents.executeJavaScript(`
|
|
323
|
-
(
|
|
324
|
-
const target = ${this._getElement()};
|
|
342
|
+
(async () => {
|
|
343
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
325
344
|
if (!target) return null;
|
|
326
345
|
|
|
327
346
|
// 验证元素是否为选择框
|
|
@@ -335,10 +354,10 @@ var ElementHandle = class {
|
|
|
335
354
|
/**
|
|
336
355
|
* 获取元素的 HTML 内容。
|
|
337
356
|
*/
|
|
338
|
-
async innerHTML() {
|
|
357
|
+
async innerHTML(options) {
|
|
339
358
|
return this.contents.executeJavaScript(`
|
|
340
|
-
(
|
|
341
|
-
const target = ${this._getElement()};
|
|
359
|
+
(async () => {
|
|
360
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
342
361
|
if (!target) return null;
|
|
343
362
|
|
|
344
363
|
return target.element.innerHTML;
|
|
@@ -348,10 +367,10 @@ var ElementHandle = class {
|
|
|
348
367
|
/**
|
|
349
368
|
* 获取元素的文本内容。
|
|
350
369
|
*/
|
|
351
|
-
async innerText() {
|
|
370
|
+
async innerText(options) {
|
|
352
371
|
return this.contents.executeJavaScript(`
|
|
353
|
-
(
|
|
354
|
-
const target = ${this._getElement()};
|
|
372
|
+
(async () => {
|
|
373
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
355
374
|
if (!target) return null;
|
|
356
375
|
|
|
357
376
|
return target.element.innerText;
|
|
@@ -362,10 +381,10 @@ var ElementHandle = class {
|
|
|
362
381
|
* 获取元素的文本内容。
|
|
363
382
|
* @returns 元素的文本内容
|
|
364
383
|
*/
|
|
365
|
-
async textContent() {
|
|
384
|
+
async textContent(options) {
|
|
366
385
|
return this.contents.executeJavaScript(`
|
|
367
|
-
(
|
|
368
|
-
const target = ${this._getElement()};
|
|
386
|
+
(async () => {
|
|
387
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
369
388
|
if (!target) return null;
|
|
370
389
|
|
|
371
390
|
return target.element.textContent;
|
|
@@ -376,10 +395,10 @@ var ElementHandle = class {
|
|
|
376
395
|
* 获取元素的输入值。
|
|
377
396
|
* @returns 元素的输入值
|
|
378
397
|
*/
|
|
379
|
-
async inputValue() {
|
|
398
|
+
async inputValue(options) {
|
|
380
399
|
return this.contents.executeJavaScript(`
|
|
381
|
-
(
|
|
382
|
-
const target = ${this._getElement()};
|
|
400
|
+
(async () => {
|
|
401
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
383
402
|
if (!target) return null;
|
|
384
403
|
|
|
385
404
|
// 验证输入框是否是文本类型
|
|
@@ -393,10 +412,10 @@ var ElementHandle = class {
|
|
|
393
412
|
* 获取元素的选中状态。
|
|
394
413
|
* @returns 元素的选中状态
|
|
395
414
|
*/
|
|
396
|
-
async isChecked() {
|
|
415
|
+
async isChecked(options) {
|
|
397
416
|
return this.contents.executeJavaScript(`
|
|
398
|
-
(
|
|
399
|
-
const target = ${this._getElement()};
|
|
417
|
+
(async () => {
|
|
418
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
400
419
|
if (!target) return null;
|
|
401
420
|
|
|
402
421
|
// 验证输入框是否是复选框或单选框
|
|
@@ -410,10 +429,10 @@ var ElementHandle = class {
|
|
|
410
429
|
* 获取元素的禁用状态。
|
|
411
430
|
* @returns 元素的禁用状态
|
|
412
431
|
*/
|
|
413
|
-
async isDisabled() {
|
|
432
|
+
async isDisabled(options) {
|
|
414
433
|
return this.contents.executeJavaScript(`
|
|
415
|
-
(
|
|
416
|
-
const target = ${this._getElement()};
|
|
434
|
+
(async () => {
|
|
435
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
417
436
|
if (!target) return null;
|
|
418
437
|
|
|
419
438
|
return target.element.disabled;
|
|
@@ -424,10 +443,10 @@ var ElementHandle = class {
|
|
|
424
443
|
* 获取元素的可见状态。
|
|
425
444
|
* @returns 元素的可见状态
|
|
426
445
|
*/
|
|
427
|
-
async isVisible() {
|
|
446
|
+
async isVisible(options) {
|
|
428
447
|
return this.contents.executeJavaScript(`
|
|
429
|
-
(
|
|
430
|
-
const target = ${this._getElement()};
|
|
448
|
+
(async () => {
|
|
449
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
431
450
|
if (!target) return null;
|
|
432
451
|
|
|
433
452
|
return target.element.offsetParent !== null;
|
|
@@ -438,10 +457,10 @@ var ElementHandle = class {
|
|
|
438
457
|
* 获取元素的可用状态。
|
|
439
458
|
* @returns 元素的可用状态
|
|
440
459
|
*/
|
|
441
|
-
async isEnabled() {
|
|
460
|
+
async isEnabled(options) {
|
|
442
461
|
return this.contents.executeJavaScript(`
|
|
443
|
-
(
|
|
444
|
-
const target = ${this._getElement()};
|
|
462
|
+
(async () => {
|
|
463
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
445
464
|
if (!target) return null;
|
|
446
465
|
|
|
447
466
|
return !target.element.disabled;
|
|
@@ -452,10 +471,10 @@ var ElementHandle = class {
|
|
|
452
471
|
* 获取元素的可编辑状态。
|
|
453
472
|
* @returns 元素的可编辑状态
|
|
454
473
|
*/
|
|
455
|
-
async isEditable() {
|
|
474
|
+
async isEditable(options) {
|
|
456
475
|
return this.contents.executeJavaScript(`
|
|
457
|
-
(
|
|
458
|
-
const target = ${this._getElement()};
|
|
476
|
+
(async () => {
|
|
477
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
459
478
|
if (!target) return null;
|
|
460
479
|
|
|
461
480
|
return target.element.isContentEditable;
|
|
@@ -466,10 +485,10 @@ var ElementHandle = class {
|
|
|
466
485
|
* 获取元素的隐藏状态。
|
|
467
486
|
* @returns 元素的隐藏状态
|
|
468
487
|
*/
|
|
469
|
-
async isHidden() {
|
|
488
|
+
async isHidden(options) {
|
|
470
489
|
return this.contents.executeJavaScript(`
|
|
471
|
-
(
|
|
472
|
-
const target = ${this._getElement()};
|
|
490
|
+
(async () => {
|
|
491
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
473
492
|
if (!target) return null;
|
|
474
493
|
|
|
475
494
|
return target.element.offsetParent === null;
|
|
@@ -481,8 +500,8 @@ var ElementHandle = class {
|
|
|
481
500
|
*/
|
|
482
501
|
async selectText(options) {
|
|
483
502
|
return this.contents.executeJavaScript(`
|
|
484
|
-
(
|
|
485
|
-
const target = ${this._getElement(options.timeout)};
|
|
503
|
+
(async () => {
|
|
504
|
+
const target = await ${this._getElement(options.timeout)};
|
|
486
505
|
if (!target) return null;
|
|
487
506
|
|
|
488
507
|
// 选中元素的文本内容
|
|
@@ -501,8 +520,8 @@ var ElementHandle = class {
|
|
|
501
520
|
*/
|
|
502
521
|
async uncheck(options) {
|
|
503
522
|
return this.contents.executeJavaScript(`
|
|
504
|
-
(
|
|
505
|
-
const target = ${this._getElement(options?.timeout)};
|
|
523
|
+
(async () => {
|
|
524
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
506
525
|
if (!target) return null;
|
|
507
526
|
|
|
508
527
|
// 验证输入框是否是复选框或单选框
|
|
@@ -614,4 +633,4 @@ var Ectrol = class {
|
|
|
614
633
|
var src_default = Ectrol;
|
|
615
634
|
|
|
616
635
|
//#endregion
|
|
617
|
-
export { Ectrol, ElementHandle, LocalStorage, SessionStorage, src_default as default, getHumanTypingDelay, sleep };
|
|
636
|
+
export { Ectrol, ElementHandle, LocalStorage, SessionStorage, src_default as default, getHumanTypingDelay, randomInRange, sleep };
|
package/package.json
CHANGED