assistsx-js 0.0.1331 → 0.0.1333
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/AssistsX.d.ts +21 -0
- package/dist/AssistsX.js +66 -0
- package/package.json +5 -1
- package/src/AssistsX.ts +72 -0
- package/src/global.d.ts +1 -0
- package/README-DEV.md +0 -350
- package/tsconfig.json +0 -20
package/dist/AssistsX.d.ts
CHANGED
|
@@ -303,5 +303,26 @@ export declare class AssistsX {
|
|
|
303
303
|
* @returns 应用窗口尺寸对象
|
|
304
304
|
*/
|
|
305
305
|
static getAppScreenSize(): any;
|
|
306
|
+
/**
|
|
307
|
+
* 添加无障碍事件监听器
|
|
308
|
+
* @param listener 监听器函数
|
|
309
|
+
* @returns 监听器ID,用于移除监听器
|
|
310
|
+
*/
|
|
311
|
+
static addAccessibilityEventListener(listener: (event: any) => void): string;
|
|
312
|
+
/**
|
|
313
|
+
* 移除无障碍事件监听器
|
|
314
|
+
* @param listenerId 监听器ID
|
|
315
|
+
* @returns 是否移除成功
|
|
316
|
+
*/
|
|
317
|
+
static removeAccessibilityEventListener(listenerId: string): boolean;
|
|
318
|
+
/**
|
|
319
|
+
* 移除所有无障碍事件监听器
|
|
320
|
+
*/
|
|
321
|
+
static removeAllAccessibilityEventListeners(): void;
|
|
322
|
+
/**
|
|
323
|
+
* 获取当前注册的无障碍事件监听器数量
|
|
324
|
+
* @returns 监听器数量
|
|
325
|
+
*/
|
|
326
|
+
static getAccessibilityEventListenerCount(): number;
|
|
306
327
|
}
|
|
307
328
|
export {};
|
package/dist/AssistsX.js
CHANGED
|
@@ -9,6 +9,8 @@ import { Bounds } from './Bounds';
|
|
|
9
9
|
import { generateUUID } from './Utils';
|
|
10
10
|
// 回调函数存储对象
|
|
11
11
|
const callbacks = {};
|
|
12
|
+
// 无障碍事件监听器存储
|
|
13
|
+
const accessibilityEventListeners = [];
|
|
12
14
|
// 初始化全局回调函数
|
|
13
15
|
if (typeof window !== 'undefined' && !window.assistsxCallback) {
|
|
14
16
|
window.assistsxCallback = (data) => {
|
|
@@ -19,6 +21,20 @@ if (typeof window !== 'undefined' && !window.assistsxCallback) {
|
|
|
19
21
|
}
|
|
20
22
|
};
|
|
21
23
|
}
|
|
24
|
+
// 初始化全局无障碍事件函数
|
|
25
|
+
if (typeof window !== 'undefined' && !window.onAccessibilityEvent) {
|
|
26
|
+
window.onAccessibilityEvent = (event) => {
|
|
27
|
+
// 通知所有注册的监听器
|
|
28
|
+
accessibilityEventListeners.forEach(listener => {
|
|
29
|
+
try {
|
|
30
|
+
listener(event);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error('Accessibility event listener error:', error);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
}
|
|
22
38
|
export class AssistsX {
|
|
23
39
|
/**
|
|
24
40
|
* 执行同步调用
|
|
@@ -425,4 +441,54 @@ export class AssistsX {
|
|
|
425
441
|
const response = this.call(CallMethod.getAppScreenSize);
|
|
426
442
|
return response.getDataOrDefault("{}");
|
|
427
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* 添加无障碍事件监听器
|
|
446
|
+
* @param listener 监听器函数
|
|
447
|
+
* @returns 监听器ID,用于移除监听器
|
|
448
|
+
*/
|
|
449
|
+
static addAccessibilityEventListener(listener) {
|
|
450
|
+
const listenerId = generateUUID();
|
|
451
|
+
const wrappedListener = (event) => {
|
|
452
|
+
try {
|
|
453
|
+
listener(event);
|
|
454
|
+
}
|
|
455
|
+
catch (error) {
|
|
456
|
+
console.error('Accessibility event listener error:', error);
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
// 将监听器包装并存储,使用ID作为键
|
|
460
|
+
accessibilityEventListeners[listenerId] = wrappedListener;
|
|
461
|
+
accessibilityEventListeners.push(wrappedListener);
|
|
462
|
+
return listenerId;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* 移除无障碍事件监听器
|
|
466
|
+
* @param listenerId 监听器ID
|
|
467
|
+
* @returns 是否移除成功
|
|
468
|
+
*/
|
|
469
|
+
static removeAccessibilityEventListener(listenerId) {
|
|
470
|
+
const listener = accessibilityEventListeners[listenerId];
|
|
471
|
+
if (listener) {
|
|
472
|
+
const index = accessibilityEventListeners.indexOf(listener);
|
|
473
|
+
if (index > -1) {
|
|
474
|
+
accessibilityEventListeners.splice(index, 1);
|
|
475
|
+
delete accessibilityEventListeners[listenerId];
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* 移除所有无障碍事件监听器
|
|
483
|
+
*/
|
|
484
|
+
static removeAllAccessibilityEventListeners() {
|
|
485
|
+
accessibilityEventListeners.length = 0;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* 获取当前注册的无障碍事件监听器数量
|
|
489
|
+
* @returns 监听器数量
|
|
490
|
+
*/
|
|
491
|
+
static getAccessibilityEventListenerCount() {
|
|
492
|
+
return accessibilityEventListeners.length;
|
|
493
|
+
}
|
|
428
494
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assistsx-js",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1333",
|
|
4
4
|
"description": "assistsx-js自动化开发SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src"
|
|
11
|
+
],
|
|
8
12
|
"exports": {
|
|
9
13
|
".": {
|
|
10
14
|
"import": "./dist/index.js",
|
package/src/AssistsX.ts
CHANGED
|
@@ -34,6 +34,9 @@ interface WebFloatingWindowOptions {
|
|
|
34
34
|
// 回调函数存储对象
|
|
35
35
|
const callbacks: { [key: string]: (data: any) => void } = {};
|
|
36
36
|
|
|
37
|
+
// 无障碍事件监听器存储
|
|
38
|
+
const accessibilityEventListeners: ((event: any) => void)[] = [];
|
|
39
|
+
|
|
37
40
|
// 初始化全局回调函数
|
|
38
41
|
if (typeof window !== 'undefined' && !window.assistsxCallback) {
|
|
39
42
|
window.assistsxCallback = (data: string) => {
|
|
@@ -45,6 +48,20 @@ if (typeof window !== 'undefined' && !window.assistsxCallback) {
|
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
// 初始化全局无障碍事件函数
|
|
52
|
+
if (typeof window !== 'undefined' && !window.onAccessibilityEvent) {
|
|
53
|
+
window.onAccessibilityEvent = (event: any) => {
|
|
54
|
+
// 通知所有注册的监听器
|
|
55
|
+
accessibilityEventListeners.forEach(listener => {
|
|
56
|
+
try {
|
|
57
|
+
listener(event);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error('Accessibility event listener error:', error);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
48
65
|
export class AssistsX {
|
|
49
66
|
/**
|
|
50
67
|
* 执行同步调用
|
|
@@ -489,4 +506,59 @@ export class AssistsX {
|
|
|
489
506
|
const response = this.call(CallMethod.getAppScreenSize);
|
|
490
507
|
return response.getDataOrDefault("{}");
|
|
491
508
|
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* 添加无障碍事件监听器
|
|
512
|
+
* @param listener 监听器函数
|
|
513
|
+
* @returns 监听器ID,用于移除监听器
|
|
514
|
+
*/
|
|
515
|
+
public static addAccessibilityEventListener(listener: (event: any) => void): string {
|
|
516
|
+
const listenerId = generateUUID();
|
|
517
|
+
const wrappedListener = (event: any) => {
|
|
518
|
+
try {
|
|
519
|
+
listener(event);
|
|
520
|
+
} catch (error) {
|
|
521
|
+
console.error('Accessibility event listener error:', error);
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
// 将监听器包装并存储,使用ID作为键
|
|
526
|
+
(accessibilityEventListeners as any)[listenerId] = wrappedListener;
|
|
527
|
+
accessibilityEventListeners.push(wrappedListener);
|
|
528
|
+
|
|
529
|
+
return listenerId;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* 移除无障碍事件监听器
|
|
534
|
+
* @param listenerId 监听器ID
|
|
535
|
+
* @returns 是否移除成功
|
|
536
|
+
*/
|
|
537
|
+
public static removeAccessibilityEventListener(listenerId: string): boolean {
|
|
538
|
+
const listener = (accessibilityEventListeners as any)[listenerId];
|
|
539
|
+
if (listener) {
|
|
540
|
+
const index = accessibilityEventListeners.indexOf(listener);
|
|
541
|
+
if (index > -1) {
|
|
542
|
+
accessibilityEventListeners.splice(index, 1);
|
|
543
|
+
delete (accessibilityEventListeners as any)[listenerId];
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* 移除所有无障碍事件监听器
|
|
552
|
+
*/
|
|
553
|
+
public static removeAllAccessibilityEventListeners(): void {
|
|
554
|
+
accessibilityEventListeners.length = 0;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* 获取当前注册的无障碍事件监听器数量
|
|
559
|
+
* @returns 监听器数量
|
|
560
|
+
*/
|
|
561
|
+
public static getAccessibilityEventListenerCount(): number {
|
|
562
|
+
return accessibilityEventListeners.length;
|
|
563
|
+
}
|
|
492
564
|
}
|
package/src/global.d.ts
CHANGED
package/README-DEV.md
DELETED
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
### 基本用法
|
|
2
|
-
|
|
3
|
-
```typescript
|
|
4
|
-
import { AssistsX, Node } from 'assistsx-js';
|
|
5
|
-
|
|
6
|
-
// 获取所有节点
|
|
7
|
-
const nodes: Node[] = AssistsX.getAllNodes();
|
|
8
|
-
|
|
9
|
-
// 通过ID查找节点
|
|
10
|
-
const nodeList: Node[] = AssistsX.findById('target_id');
|
|
11
|
-
|
|
12
|
-
// 点击第一个节点
|
|
13
|
-
if (nodeList.length > 0) {
|
|
14
|
-
AssistsX.click(nodeList[0]);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 执行手势点击
|
|
18
|
-
AssistsX.gestureClick(100, 200, 50); // 在(100,200)位置点击,持续50ms
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### 节点对象的常用操作
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
const node: Node = nodeList[0];
|
|
25
|
-
|
|
26
|
-
// 设置节点文本
|
|
27
|
-
node.setNodeText('new text');
|
|
28
|
-
|
|
29
|
-
// 节点点击
|
|
30
|
-
node.click();
|
|
31
|
-
|
|
32
|
-
// 节点长按
|
|
33
|
-
node.longClick();
|
|
34
|
-
|
|
35
|
-
// 节点滚动
|
|
36
|
-
node.scrollForward();
|
|
37
|
-
node.scrollBackward();
|
|
38
|
-
|
|
39
|
-
// 获取节点在屏幕中的位置
|
|
40
|
-
const bounds = node.getBoundsInScreen();
|
|
41
|
-
console.log(bounds);
|
|
42
|
-
|
|
43
|
-
// 节点截图
|
|
44
|
-
const imagePath = await node.takeScreenshot();
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### 复杂查找与遍历
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
// 通过文本查找节点
|
|
51
|
-
const textNodes = AssistsX.findByText('确定');
|
|
52
|
-
|
|
53
|
-
// 通过标签查找节点
|
|
54
|
-
const tagNodes = AssistsX.findByTags('android.widget.Button', { filterText: '提交' });
|
|
55
|
-
|
|
56
|
-
// 获取节点的所有子节点
|
|
57
|
-
const children = node.getChildren();
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## 主要类型说明
|
|
61
|
-
|
|
62
|
-
### AssistsX
|
|
63
|
-
|
|
64
|
-
- 提供静态方法用于节点查找、手势操作、系统操作等。
|
|
65
|
-
- 常用方法:
|
|
66
|
-
- `getAllNodes`:获取所有节点
|
|
67
|
-
- `findById`、`findByText`、`findByTags`:多种查找方式
|
|
68
|
-
- `click`、`longClick`、`gestureClick`:节点点击与手势
|
|
69
|
-
- `takeScreenshotNodes`:节点截图
|
|
70
|
-
- `launchApp`、`back`、`home`、`notifications`、`recentApps`:系统操作
|
|
71
|
-
|
|
72
|
-
### Node
|
|
73
|
-
|
|
74
|
-
- 表示界面上的一个可交互元素,包含属性和操作方法。
|
|
75
|
-
- 主要属性:
|
|
76
|
-
- `nodeId`、`text`、`des`、`viewId`、`className`
|
|
77
|
-
- `isScrollable`、`isClickable`、`isEnabled`
|
|
78
|
-
- 主要方法:
|
|
79
|
-
- `setNodeText(text: string)`:设置文本
|
|
80
|
-
- `click()`、`longClick()`:点击/长按
|
|
81
|
-
- `scrollForward()`、`scrollBackward()`:滚动
|
|
82
|
-
- `getBoundsInScreen()`:获取屏幕位置
|
|
83
|
-
- `takeScreenshot()`:节点截图
|
|
84
|
-
- `findById`、`findByText`、`findByTags`:在当前节点范围内查找
|
|
85
|
-
|
|
86
|
-
## 典型场景
|
|
87
|
-
|
|
88
|
-
### 1. 自动化测试
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
// 启动应用
|
|
92
|
-
AssistsX.launchApp('com.example.app');
|
|
93
|
-
|
|
94
|
-
// 等待并点击登录按钮
|
|
95
|
-
const loginBtn = AssistsX.findByText('登录');
|
|
96
|
-
if (loginBtn.length > 0) {
|
|
97
|
-
loginBtn[0].click();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// 检查是否包含某文本
|
|
101
|
-
const hasText = AssistsX.containsText('登录成功');
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 2. 界面元素操作
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
// 查找输入框并输入文本
|
|
108
|
-
const input = AssistsX.findById('input_field');
|
|
109
|
-
if (input.length > 0) {
|
|
110
|
-
input[0].setNodeText('测试文本');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// 查找并点击提交按钮
|
|
114
|
-
const submit = AssistsX.findByText('提交');
|
|
115
|
-
if (submit.length > 0) {
|
|
116
|
-
submit[0].click();
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### 3. 手势操作
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// 简单点击
|
|
124
|
-
AssistsX.gestureClick(100, 200, 50);
|
|
125
|
-
|
|
126
|
-
// 节点手势点击(支持偏移)
|
|
127
|
-
const node = AssistsX.findById('target')[0];
|
|
128
|
-
await node.nodeGestureClick({
|
|
129
|
-
offsetX: 10,
|
|
130
|
-
offsetY: 10,
|
|
131
|
-
clickDuration: 50
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// 双击操作
|
|
135
|
-
await node.nodeGestureClickByDouble({
|
|
136
|
-
clickInterval: 200
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### 4. 滚动和导航
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
// 系统导航
|
|
144
|
-
AssistsX.back(); // 返回
|
|
145
|
-
AssistsX.home(); // 主页
|
|
146
|
-
AssistsX.notifications(); // 通知栏
|
|
147
|
-
|
|
148
|
-
// 滚动操作
|
|
149
|
-
const scrollable = AssistsX.findByTags('android.widget.ScrollView')[0];
|
|
150
|
-
scrollable.scrollForward();
|
|
151
|
-
scrollable.scrollBackward();
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## 步骤器(Step)使用说明
|
|
155
|
-
|
|
156
|
-
步骤器提供了一种结构化的方式来组织和执行自动化操作,支持步骤的生命周期管理、状态控制和界面操作。
|
|
157
|
-
|
|
158
|
-
### 基本用法
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
import { Step } from 'assistsx-js';
|
|
162
|
-
|
|
163
|
-
// 定义步骤实现
|
|
164
|
-
async function loginStep(step: Step): Promise<Step | undefined> {
|
|
165
|
-
// 启动应用
|
|
166
|
-
step.launchApp('com.example.app');
|
|
167
|
-
|
|
168
|
-
// 查找用户名输入框并输入
|
|
169
|
-
const usernameInput = step.findById('username_input');
|
|
170
|
-
if (usernameInput.length > 0) {
|
|
171
|
-
usernameInput[0].setNodeText('user123');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 查找密码输入框并输入
|
|
175
|
-
const passwordInput = step.findById('password_input');
|
|
176
|
-
if (passwordInput.length > 0) {
|
|
177
|
-
passwordInput[0].setNodeText('password123');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// 点击登录按钮
|
|
181
|
-
const loginButton = step.findByText('登录');
|
|
182
|
-
if (loginButton.length > 0) {
|
|
183
|
-
loginButton[0].click();
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// 返回 undefined 表示步骤结束
|
|
187
|
-
return undefined;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// 运行步骤
|
|
191
|
-
await Step.run(loginStep, {
|
|
192
|
-
tag: 'login', // 步骤标签
|
|
193
|
-
data: { user: 'test' }, // 步骤数据
|
|
194
|
-
delayMs: 1000 // 步骤延迟
|
|
195
|
-
});
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
### 步骤链式调用
|
|
199
|
-
|
|
200
|
-
```typescript
|
|
201
|
-
async function step1(step: Step): Promise<Step | undefined> {
|
|
202
|
-
// 执行某些操作
|
|
203
|
-
// ...
|
|
204
|
-
|
|
205
|
-
// 返回下一个步骤
|
|
206
|
-
return step.next(step2, { tag: 'step2' });
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async function step2(step: Step): Promise<Step | undefined> {
|
|
210
|
-
// 执行某些操作
|
|
211
|
-
// ...
|
|
212
|
-
|
|
213
|
-
// 重复当前步骤
|
|
214
|
-
if (needRepeat) {
|
|
215
|
-
return step.repeat();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// 返回下一个步骤
|
|
219
|
-
return step.next(step3, { tag: 'step3' });
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
async function step3(step: Step): Promise<Step | undefined> {
|
|
223
|
-
// 执行最后的操作
|
|
224
|
-
// ...
|
|
225
|
-
|
|
226
|
-
// 步骤结束
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// 运行步骤链
|
|
231
|
-
await Step.run(step1, { tag: 'step1' });
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### 异步操作处理
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
async function asyncStep(step: Step): Promise<Step | undefined> {
|
|
238
|
-
// 等待异步操作
|
|
239
|
-
await step.delay(1000);
|
|
240
|
-
|
|
241
|
-
// 执行异步方法
|
|
242
|
-
const result = await step.await(async () => {
|
|
243
|
-
// 异步操作
|
|
244
|
-
return 'result';
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// 节点截图
|
|
248
|
-
const node = step.findById('target')[0];
|
|
249
|
-
const imagePath = await step.takeScreenshotByNode(node);
|
|
250
|
-
|
|
251
|
-
return undefined;
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
## Step API 文档
|
|
256
|
-
|
|
257
|
-
### 静态方法
|
|
258
|
-
|
|
259
|
-
#### `Step.run(impl, options)`
|
|
260
|
-
运行步骤实现。
|
|
261
|
-
- `impl`: `(step: Step) => Promise<Step | undefined>` - 步骤实现函数
|
|
262
|
-
- `options`:
|
|
263
|
-
- `tag?: string` - 步骤标签
|
|
264
|
-
- `data?: any` - 步骤数据
|
|
265
|
-
- `delayMs?: number` - 步骤延迟时间(毫秒),默认 1000
|
|
266
|
-
|
|
267
|
-
#### `Step.stop()`
|
|
268
|
-
停止当前步骤执行。
|
|
269
|
-
|
|
270
|
-
### 实例属性
|
|
271
|
-
|
|
272
|
-
- `stepId: string` - 步骤ID
|
|
273
|
-
- `repeatCount: number` - 步骤重复执行次数
|
|
274
|
-
- `tag?: string` - 步骤标签
|
|
275
|
-
- `data?: any` - 步骤数据
|
|
276
|
-
- `delayMs: number` - 步骤延迟时间(毫秒)
|
|
277
|
-
|
|
278
|
-
### 实例方法
|
|
279
|
-
|
|
280
|
-
#### 步骤控制
|
|
281
|
-
- `next(impl, options)` - 创建下一个步骤
|
|
282
|
-
- `repeat(options)` - 重复当前步骤
|
|
283
|
-
- `delay(ms)` - 延迟执行
|
|
284
|
-
- `await<T>(method)` - 等待异步方法执行完成
|
|
285
|
-
|
|
286
|
-
#### 节点操作
|
|
287
|
-
- `getAllNodes(options)` - 获取所有符合条件的节点
|
|
288
|
-
- `findById(id, options)` - 通过ID查找节点
|
|
289
|
-
- `findByText(text, options)` - 通过文本查找节点
|
|
290
|
-
- `findByTags(className, options)` - 通过标签查找节点
|
|
291
|
-
- `findByTextAllMatch(text)` - 查找所有匹配文本的节点
|
|
292
|
-
- `findFirstParentByTags(className)` - 查找第一个匹配标签的父节点
|
|
293
|
-
|
|
294
|
-
#### 界面操作
|
|
295
|
-
- `takeScreenshotByNode(node, delay)` - 对单个节点进行截图
|
|
296
|
-
- `takeScreenshotNodes(nodes, delay)` - 对多个节点进行截图
|
|
297
|
-
- `gestureClick(x, y, duration)` - 执行点击手势
|
|
298
|
-
- `back()` - 返回操作
|
|
299
|
-
- `home()` - 回到主页
|
|
300
|
-
- `notifications()` - 打开通知栏
|
|
301
|
-
- `recentApps()` - 显示最近应用
|
|
302
|
-
|
|
303
|
-
#### 应用控制
|
|
304
|
-
- `launchApp(packageName)` - 启动应用
|
|
305
|
-
- `getPackageName()` - 获取当前应用包名
|
|
306
|
-
|
|
307
|
-
#### 其他操作
|
|
308
|
-
- `containsText(text)` - 检查是否包含指定文本
|
|
309
|
-
- `getAllText()` - 获取所有文本
|
|
310
|
-
- `getScreenSize()` - 获取屏幕尺寸
|
|
311
|
-
- `getAppScreenSize()` - 获取应用窗口尺寸
|
|
312
|
-
|
|
313
|
-
## 最佳实践
|
|
314
|
-
|
|
315
|
-
1. 步骤组织
|
|
316
|
-
- 将复杂的自动化流程拆分为多个步骤
|
|
317
|
-
- 每个步骤专注于完成特定的任务
|
|
318
|
-
- 使用有意义的标签和数据来标识步骤
|
|
319
|
-
|
|
320
|
-
2. 错误处理
|
|
321
|
-
```typescript
|
|
322
|
-
async function robustStep(step: Step): Promise<Step | undefined> {
|
|
323
|
-
try {
|
|
324
|
-
const node = step.findById('target')[0];
|
|
325
|
-
if (!node) {
|
|
326
|
-
throw new Error('Target node not found');
|
|
327
|
-
}
|
|
328
|
-
// ... 其他操作
|
|
329
|
-
} catch (error) {
|
|
330
|
-
console.error(`Step failed: ${error.message}`);
|
|
331
|
-
// 可以选择重试或执行其他步骤
|
|
332
|
-
return step.repeat({ delayMs: 2000 });
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
3. 步骤复用
|
|
338
|
-
```typescript
|
|
339
|
-
// 创建可复用的步骤
|
|
340
|
-
function createLoginStep(username: string, password: string) {
|
|
341
|
-
return async function(step: Step): Promise<Step | undefined> {
|
|
342
|
-
// ... 登录逻辑
|
|
343
|
-
return undefined;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// 在不同地方复用
|
|
348
|
-
await Step.run(createLoginStep('user1', 'pass1'));
|
|
349
|
-
await Step.run(createLoginStep('user2', 'pass2'));
|
|
350
|
-
```
|
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2018",
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"moduleResolution": "node",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"outDir": "./dist",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"rootDir": "./src",
|
|
13
|
-
"baseUrl": ".",
|
|
14
|
-
"paths": {
|
|
15
|
-
"*": ["src/*"]
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
"include": ["src/**/*"],
|
|
19
|
-
"exclude": ["node_modules", "dist"]
|
|
20
|
-
}
|