ectrol 0.0.4 → 0.1.0
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 +139 -125
- 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
|
-
|
|
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
|
+
}
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
// 分层选择器,支持 iframe 穿越
|
|
55
|
+
const parts = selector.split('|>').map(s => s.trim());
|
|
56
|
+
if (!parts.length) return null;
|
|
45
57
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
58
|
+
let currentDocument = document;
|
|
59
|
+
let offsetLeft = 0;
|
|
60
|
+
let offsetTop = 0;
|
|
61
|
+
let element = null;
|
|
50
62
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (!parts.length) return null;
|
|
63
|
+
for (let i = 0; i < parts.length; i++) {
|
|
64
|
+
if (!currentDocument) return null;
|
|
54
65
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let element = null;
|
|
66
|
+
const part = parts[i];
|
|
67
|
+
// 在当前文档查找该层选择器
|
|
68
|
+
const el = currentDocument.querySelector(part);
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
if (!el) {
|
|
71
|
+
console.warn('未找到元素:', part);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
// 在当前文档查找该层选择器
|
|
65
|
-
const el = currentDocument.querySelector(part);
|
|
75
|
+
const rect = el.getBoundingClientRect();
|
|
66
76
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
77
|
+
// 累加当前层级偏移
|
|
78
|
+
offsetLeft += rect.left;
|
|
79
|
+
offsetTop += rect.top;
|
|
71
80
|
|
|
72
|
-
|
|
81
|
+
element = el;
|
|
73
82
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
const isLast = i === parts.length - 1;
|
|
84
|
+
if (!isLast) {
|
|
85
|
+
if (el.tagName !== 'IFRAME') {
|
|
86
|
+
console.warn('非 iframe 元素却尝试进入下一层:', part);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
77
89
|
|
|
78
|
-
|
|
90
|
+
const nextDoc = el.contentDocument || el.contentWindow?.document;
|
|
91
|
+
if (!nextDoc) {
|
|
92
|
+
console.warn('无法访问 iframe.contentDocument(可能跨域)');
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
79
95
|
|
|
80
|
-
|
|
81
|
-
if (!isLast) {
|
|
82
|
-
if (el.tagName !== 'IFRAME') {
|
|
83
|
-
console.warn('非 iframe 元素却尝试进入下一层:', part);
|
|
84
|
-
return null;
|
|
96
|
+
currentDocument = nextDoc;
|
|
85
97
|
}
|
|
86
|
-
|
|
87
|
-
const nextDoc = el.contentDocument || el.contentWindow?.document;
|
|
88
|
-
if (!nextDoc) {
|
|
89
|
-
console.warn('无法访问 iframe.contentDocument(可能跨域)');
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
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
|
// 验证输入框是否是文本类型
|
|
@@ -290,11 +306,9 @@ var ElementHandle = class {
|
|
|
290
306
|
* - 返回扩展的 DOMRect 信息并包含元素中心点坐标。
|
|
291
307
|
*/
|
|
292
308
|
getBoundingClientRect(timeout = 0) {
|
|
293
|
-
if (this.isNotFound) return Promise.resolve(null);
|
|
294
309
|
return this.contents.executeJavaScript(`
|
|
295
|
-
(
|
|
296
|
-
const target = ${this._getElement(timeout)};
|
|
297
|
-
|
|
310
|
+
(async () => {
|
|
311
|
+
const target = await ${this._getElement(timeout)};
|
|
298
312
|
if (!target) return null;
|
|
299
313
|
|
|
300
314
|
const rect = target.rect;
|
|
@@ -318,10 +332,10 @@ var ElementHandle = class {
|
|
|
318
332
|
* @param value 选项的值
|
|
319
333
|
* @returns
|
|
320
334
|
*/
|
|
321
|
-
async selectOption(value) {
|
|
335
|
+
async selectOption(value, options) {
|
|
322
336
|
return this.contents.executeJavaScript(`
|
|
323
|
-
(
|
|
324
|
-
const target = ${this._getElement()};
|
|
337
|
+
(async () => {
|
|
338
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
325
339
|
if (!target) return null;
|
|
326
340
|
|
|
327
341
|
// 验证元素是否为选择框
|
|
@@ -335,10 +349,10 @@ var ElementHandle = class {
|
|
|
335
349
|
/**
|
|
336
350
|
* 获取元素的 HTML 内容。
|
|
337
351
|
*/
|
|
338
|
-
async innerHTML() {
|
|
352
|
+
async innerHTML(options) {
|
|
339
353
|
return this.contents.executeJavaScript(`
|
|
340
|
-
(
|
|
341
|
-
const target = ${this._getElement()};
|
|
354
|
+
(async () => {
|
|
355
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
342
356
|
if (!target) return null;
|
|
343
357
|
|
|
344
358
|
return target.element.innerHTML;
|
|
@@ -348,10 +362,10 @@ var ElementHandle = class {
|
|
|
348
362
|
/**
|
|
349
363
|
* 获取元素的文本内容。
|
|
350
364
|
*/
|
|
351
|
-
async innerText() {
|
|
365
|
+
async innerText(options) {
|
|
352
366
|
return this.contents.executeJavaScript(`
|
|
353
|
-
(
|
|
354
|
-
const target = ${this._getElement()};
|
|
367
|
+
(async () => {
|
|
368
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
355
369
|
if (!target) return null;
|
|
356
370
|
|
|
357
371
|
return target.element.innerText;
|
|
@@ -362,10 +376,10 @@ var ElementHandle = class {
|
|
|
362
376
|
* 获取元素的文本内容。
|
|
363
377
|
* @returns 元素的文本内容
|
|
364
378
|
*/
|
|
365
|
-
async textContent() {
|
|
379
|
+
async textContent(options) {
|
|
366
380
|
return this.contents.executeJavaScript(`
|
|
367
|
-
(
|
|
368
|
-
const target = ${this._getElement()};
|
|
381
|
+
(async () => {
|
|
382
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
369
383
|
if (!target) return null;
|
|
370
384
|
|
|
371
385
|
return target.element.textContent;
|
|
@@ -376,10 +390,10 @@ var ElementHandle = class {
|
|
|
376
390
|
* 获取元素的输入值。
|
|
377
391
|
* @returns 元素的输入值
|
|
378
392
|
*/
|
|
379
|
-
async inputValue() {
|
|
393
|
+
async inputValue(options) {
|
|
380
394
|
return this.contents.executeJavaScript(`
|
|
381
|
-
(
|
|
382
|
-
const target = ${this._getElement()};
|
|
395
|
+
(async () => {
|
|
396
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
383
397
|
if (!target) return null;
|
|
384
398
|
|
|
385
399
|
// 验证输入框是否是文本类型
|
|
@@ -393,10 +407,10 @@ var ElementHandle = class {
|
|
|
393
407
|
* 获取元素的选中状态。
|
|
394
408
|
* @returns 元素的选中状态
|
|
395
409
|
*/
|
|
396
|
-
async isChecked() {
|
|
410
|
+
async isChecked(options) {
|
|
397
411
|
return this.contents.executeJavaScript(`
|
|
398
|
-
(
|
|
399
|
-
const target = ${this._getElement()};
|
|
412
|
+
(async () => {
|
|
413
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
400
414
|
if (!target) return null;
|
|
401
415
|
|
|
402
416
|
// 验证输入框是否是复选框或单选框
|
|
@@ -410,10 +424,10 @@ var ElementHandle = class {
|
|
|
410
424
|
* 获取元素的禁用状态。
|
|
411
425
|
* @returns 元素的禁用状态
|
|
412
426
|
*/
|
|
413
|
-
async isDisabled() {
|
|
427
|
+
async isDisabled(options) {
|
|
414
428
|
return this.contents.executeJavaScript(`
|
|
415
|
-
(
|
|
416
|
-
const target = ${this._getElement()};
|
|
429
|
+
(async () => {
|
|
430
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
417
431
|
if (!target) return null;
|
|
418
432
|
|
|
419
433
|
return target.element.disabled;
|
|
@@ -424,10 +438,10 @@ var ElementHandle = class {
|
|
|
424
438
|
* 获取元素的可见状态。
|
|
425
439
|
* @returns 元素的可见状态
|
|
426
440
|
*/
|
|
427
|
-
async isVisible() {
|
|
441
|
+
async isVisible(options) {
|
|
428
442
|
return this.contents.executeJavaScript(`
|
|
429
|
-
(
|
|
430
|
-
const target = ${this._getElement()};
|
|
443
|
+
(async () => {
|
|
444
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
431
445
|
if (!target) return null;
|
|
432
446
|
|
|
433
447
|
return target.element.offsetParent !== null;
|
|
@@ -438,10 +452,10 @@ var ElementHandle = class {
|
|
|
438
452
|
* 获取元素的可用状态。
|
|
439
453
|
* @returns 元素的可用状态
|
|
440
454
|
*/
|
|
441
|
-
async isEnabled() {
|
|
455
|
+
async isEnabled(options) {
|
|
442
456
|
return this.contents.executeJavaScript(`
|
|
443
|
-
(
|
|
444
|
-
const target = ${this._getElement()};
|
|
457
|
+
(async () => {
|
|
458
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
445
459
|
if (!target) return null;
|
|
446
460
|
|
|
447
461
|
return !target.element.disabled;
|
|
@@ -452,10 +466,10 @@ var ElementHandle = class {
|
|
|
452
466
|
* 获取元素的可编辑状态。
|
|
453
467
|
* @returns 元素的可编辑状态
|
|
454
468
|
*/
|
|
455
|
-
async isEditable() {
|
|
469
|
+
async isEditable(options) {
|
|
456
470
|
return this.contents.executeJavaScript(`
|
|
457
|
-
(
|
|
458
|
-
const target = ${this._getElement()};
|
|
471
|
+
(async () => {
|
|
472
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
459
473
|
if (!target) return null;
|
|
460
474
|
|
|
461
475
|
return target.element.isContentEditable;
|
|
@@ -466,10 +480,10 @@ var ElementHandle = class {
|
|
|
466
480
|
* 获取元素的隐藏状态。
|
|
467
481
|
* @returns 元素的隐藏状态
|
|
468
482
|
*/
|
|
469
|
-
async isHidden() {
|
|
483
|
+
async isHidden(options) {
|
|
470
484
|
return this.contents.executeJavaScript(`
|
|
471
|
-
(
|
|
472
|
-
const target = ${this._getElement()};
|
|
485
|
+
(async () => {
|
|
486
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
473
487
|
if (!target) return null;
|
|
474
488
|
|
|
475
489
|
return target.element.offsetParent === null;
|
|
@@ -481,8 +495,8 @@ var ElementHandle = class {
|
|
|
481
495
|
*/
|
|
482
496
|
async selectText(options) {
|
|
483
497
|
return this.contents.executeJavaScript(`
|
|
484
|
-
(
|
|
485
|
-
const target = ${this._getElement(options.timeout)};
|
|
498
|
+
(async () => {
|
|
499
|
+
const target = await ${this._getElement(options.timeout)};
|
|
486
500
|
if (!target) return null;
|
|
487
501
|
|
|
488
502
|
// 选中元素的文本内容
|
|
@@ -501,8 +515,8 @@ var ElementHandle = class {
|
|
|
501
515
|
*/
|
|
502
516
|
async uncheck(options) {
|
|
503
517
|
return this.contents.executeJavaScript(`
|
|
504
|
-
(
|
|
505
|
-
const target = ${this._getElement(options?.timeout)};
|
|
518
|
+
(async () => {
|
|
519
|
+
const target = await ${this._getElement(options?.timeout)};
|
|
506
520
|
if (!target) return null;
|
|
507
521
|
|
|
508
522
|
// 验证输入框是否是复选框或单选框
|
|
@@ -614,4 +628,4 @@ var Ectrol = class {
|
|
|
614
628
|
var src_default = Ectrol;
|
|
615
629
|
|
|
616
630
|
//#endregion
|
|
617
|
-
export { Ectrol, ElementHandle, LocalStorage, SessionStorage, src_default as default, getHumanTypingDelay, sleep };
|
|
631
|
+
export { Ectrol, ElementHandle, LocalStorage, SessionStorage, src_default as default, getHumanTypingDelay, randomInRange, sleep };
|
package/package.json
CHANGED