@creatoria/miniapp-mcp 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.
Files changed (160) hide show
  1. package/README.md +469 -0
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +144 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/config/defaults.d.ts +73 -0
  7. package/dist/config/defaults.d.ts.map +1 -0
  8. package/dist/config/defaults.js +118 -0
  9. package/dist/config/defaults.js.map +1 -0
  10. package/dist/config/loader.d.ts +50 -0
  11. package/dist/config/loader.d.ts.map +1 -0
  12. package/dist/config/loader.js +189 -0
  13. package/dist/config/loader.js.map +1 -0
  14. package/dist/core/element-ref.d.ts +44 -0
  15. package/dist/core/element-ref.d.ts.map +1 -0
  16. package/dist/core/element-ref.js +213 -0
  17. package/dist/core/element-ref.js.map +1 -0
  18. package/dist/core/logger.d.ts +55 -0
  19. package/dist/core/logger.d.ts.map +1 -0
  20. package/dist/core/logger.js +378 -0
  21. package/dist/core/logger.js.map +1 -0
  22. package/dist/core/output.d.ts +21 -0
  23. package/dist/core/output.d.ts.map +1 -0
  24. package/dist/core/output.js +56 -0
  25. package/dist/core/output.js.map +1 -0
  26. package/dist/core/report-generator.d.ts +24 -0
  27. package/dist/core/report-generator.d.ts.map +1 -0
  28. package/dist/core/report-generator.js +212 -0
  29. package/dist/core/report-generator.js.map +1 -0
  30. package/dist/core/session.d.ts +83 -0
  31. package/dist/core/session.d.ts.map +1 -0
  32. package/dist/core/session.js +306 -0
  33. package/dist/core/session.js.map +1 -0
  34. package/dist/core/timeout.d.ts +49 -0
  35. package/dist/core/timeout.d.ts.map +1 -0
  36. package/dist/core/timeout.js +67 -0
  37. package/dist/core/timeout.js.map +1 -0
  38. package/dist/core/tool-logger.d.ts +83 -0
  39. package/dist/core/tool-logger.d.ts.map +1 -0
  40. package/dist/core/tool-logger.js +453 -0
  41. package/dist/core/tool-logger.js.map +1 -0
  42. package/dist/core/validation.d.ts +39 -0
  43. package/dist/core/validation.d.ts.map +1 -0
  44. package/dist/core/validation.js +93 -0
  45. package/dist/core/validation.js.map +1 -0
  46. package/dist/index.d.ts +7 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +6 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/server.d.ts +7 -0
  51. package/dist/server.d.ts.map +1 -0
  52. package/dist/server.js +85 -0
  53. package/dist/server.js.map +1 -0
  54. package/dist/tools/assert.d.ts +108 -0
  55. package/dist/tools/assert.d.ts.map +1 -0
  56. package/dist/tools/assert.js +291 -0
  57. package/dist/tools/assert.js.map +1 -0
  58. package/dist/tools/automator.d.ts +45 -0
  59. package/dist/tools/automator.d.ts.map +1 -0
  60. package/dist/tools/automator.js +186 -0
  61. package/dist/tools/automator.js.map +1 -0
  62. package/dist/tools/element.d.ts +253 -0
  63. package/dist/tools/element.d.ts.map +1 -0
  64. package/dist/tools/element.js +615 -0
  65. package/dist/tools/element.js.map +1 -0
  66. package/dist/tools/index.d.ts +97 -0
  67. package/dist/tools/index.d.ts.map +1 -0
  68. package/dist/tools/index.js +1565 -0
  69. package/dist/tools/index.js.map +1 -0
  70. package/dist/tools/miniprogram.d.ts +79 -0
  71. package/dist/tools/miniprogram.d.ts.map +1 -0
  72. package/dist/tools/miniprogram.js +245 -0
  73. package/dist/tools/miniprogram.js.map +1 -0
  74. package/dist/tools/network.d.ts +65 -0
  75. package/dist/tools/network.d.ts.map +1 -0
  76. package/dist/tools/network.js +205 -0
  77. package/dist/tools/network.js.map +1 -0
  78. package/dist/tools/page.d.ts +108 -0
  79. package/dist/tools/page.d.ts.map +1 -0
  80. package/dist/tools/page.js +307 -0
  81. package/dist/tools/page.js.map +1 -0
  82. package/dist/tools/record.d.ts +86 -0
  83. package/dist/tools/record.d.ts.map +1 -0
  84. package/dist/tools/record.js +316 -0
  85. package/dist/tools/record.js.map +1 -0
  86. package/dist/tools/snapshot.d.ts +82 -0
  87. package/dist/tools/snapshot.d.ts.map +1 -0
  88. package/dist/tools/snapshot.js +258 -0
  89. package/dist/tools/snapshot.js.map +1 -0
  90. package/dist/types.d.ts +240 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +5 -0
  93. package/dist/types.js.map +1 -0
  94. package/docs/SIMPLE_USAGE.md +210 -0
  95. package/docs/api/README.md +244 -0
  96. package/docs/api/assert.md +1015 -0
  97. package/docs/api/automator.md +345 -0
  98. package/docs/api/element.md +1454 -0
  99. package/docs/api/miniprogram.md +558 -0
  100. package/docs/api/network.md +883 -0
  101. package/docs/api/page.md +909 -0
  102. package/docs/api/record.md +963 -0
  103. package/docs/api/snapshot.md +792 -0
  104. package/docs/architecture.E-Docs.md +1359 -0
  105. package/docs/architecture.F1.md +720 -0
  106. package/docs/architecture.F2.md +871 -0
  107. package/docs/architecture.F3.md +905 -0
  108. package/docs/architecture.md +90 -0
  109. package/docs/charter.A1.align.yaml +170 -0
  110. package/docs/charter.A2.align.yaml +199 -0
  111. package/docs/charter.A3.align.yaml +242 -0
  112. package/docs/charter.A4.align.yaml +227 -0
  113. package/docs/charter.B1.align.yaml +179 -0
  114. package/docs/charter.B2.align.yaml +200 -0
  115. package/docs/charter.B3.align.yaml +200 -0
  116. package/docs/charter.B4.align.yaml +188 -0
  117. package/docs/charter.C1.align.yaml +190 -0
  118. package/docs/charter.C2.align.yaml +202 -0
  119. package/docs/charter.C3.align.yaml +211 -0
  120. package/docs/charter.C4.align.yaml +263 -0
  121. package/docs/charter.C5.align.yaml +220 -0
  122. package/docs/charter.D1.align.yaml +190 -0
  123. package/docs/charter.D2.align.yaml +234 -0
  124. package/docs/charter.D3.align.yaml +206 -0
  125. package/docs/charter.E-Docs.align.yaml +294 -0
  126. package/docs/charter.F1.align.yaml +193 -0
  127. package/docs/charter.F2.align.yaml +248 -0
  128. package/docs/charter.F3.align.yaml +287 -0
  129. package/docs/charter.G.align.yaml +174 -0
  130. package/docs/charter.align.yaml +111 -0
  131. package/docs/examples/session-report-usage.md +449 -0
  132. package/docs/maintenance.md +682 -0
  133. package/docs/playwright-mcp/350/260/203/347/240/224.md +53 -0
  134. package/docs/setup-guide.md +775 -0
  135. package/docs/tasks.A1.atomize.md +296 -0
  136. package/docs/tasks.A2.atomize.md +408 -0
  137. package/docs/tasks.A3.atomize.md +564 -0
  138. package/docs/tasks.A4.atomize.md +496 -0
  139. package/docs/tasks.B1.atomize.md +352 -0
  140. package/docs/tasks.B2.atomize.md +561 -0
  141. package/docs/tasks.B3.atomize.md +508 -0
  142. package/docs/tasks.B4.atomize.md +504 -0
  143. package/docs/tasks.C1.atomize.md +540 -0
  144. package/docs/tasks.C2.atomize.md +665 -0
  145. package/docs/tasks.C3.atomize.md +745 -0
  146. package/docs/tasks.C4.atomize.md +908 -0
  147. package/docs/tasks.C5.atomize.md +755 -0
  148. package/docs/tasks.D1.atomize.md +547 -0
  149. package/docs/tasks.D2.atomize.md +619 -0
  150. package/docs/tasks.D3.atomize.md +790 -0
  151. package/docs/tasks.E-Docs.atomize.md +1204 -0
  152. package/docs/tasks.atomize.md +189 -0
  153. package/docs/troubleshooting.md +855 -0
  154. package/docs//345/256/214/346/225/264/345/256/236/347/216/260/346/226/271/346/241/210.md +155 -0
  155. package/docs//345/274/200/345/217/221/344/273/273/345/212/241/350/256/241/345/210/222.md +110 -0
  156. package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226API/345/256/214/346/225/264/346/226/207/346/241/243.md +894 -0
  157. package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226/345/256/214/346/225/264/346/223/215/344/275/234/346/211/213/345/206/214.md +1885 -0
  158. package/docs//346/216/245/345/217/243/346/226/271/346/241/210.md +565 -0
  159. package/docs//347/254/254/344/270/200/347/211/210/346/234/254/346/226/271/346/241/210.md +380 -0
  160. package/package.json +87 -0
@@ -0,0 +1,1885 @@
1
+ # 微信小程序自动化完整操作手册
2
+
3
+ > 官方文档:<https://developers.weixin.qq.com/miniprogram/dev/devtools/auto/quick-start.html>
4
+ >
5
+ > 本文档涵盖所有可用的自动化接口和操作功能
6
+
7
+ ---
8
+
9
+ ## 📑 目录
10
+
11
+ - [1. 快速入门](#1-快速入门)
12
+ - [2. Automator API](#2-automator-api)
13
+ - [3. MiniProgram API](#3-miniprogram-api)
14
+ - [4. Page API](#4-page-api)
15
+ - [5. Element API](#5-element-api)
16
+ - [6. 常用示例](#6-常用示例)
17
+ - [7. 真机自动化](#7-真机自动化)
18
+ - [8. 录制回放](#8-录制回放)
19
+ - [9. FAQ](#9-faq)
20
+
21
+ ---
22
+
23
+ ## 1. 快速入门
24
+
25
+ ### 1.1 运行环境
26
+
27
+ - **Node.js**: 版本大于 8.0
28
+ - **基础库**: 版本 `2.7.3` 及以上
29
+ - **开发者工具**: 版本 `1.02.1907232` 及以上
30
+
31
+ ### 1.2 安装
32
+
33
+ ```bash
34
+ npm i miniprogram-automator --save-dev
35
+ ```
36
+
37
+ ### 1.3 使用
38
+
39
+ **第一步**:开启工具安全设置中的 **CLI/HTTP 调用功能**
40
+
41
+ > ⚠️ 必须开启以上选项,否则 SDK 将无法正常启动工具自动化功能
42
+
43
+ **第二步**:编写控制脚本
44
+
45
+ ```javascript
46
+ const automator = require('miniprogram-automator')
47
+
48
+ automator.launch({
49
+ cliPath: 'path/to/cli', // 工具 cli 位置,默认安装位置可忽略
50
+ projectPath: 'path/to/project', // 项目文件地址
51
+ }).then(async miniProgram => {
52
+ const page = await miniProgram.reLaunch('/page/component/index')
53
+ await page.waitFor(500)
54
+ const element = await page.$('.kind-list-item-hd')
55
+ console.log(await element.attribute('class'))
56
+ await element.tap()
57
+ await miniProgram.close()
58
+ })
59
+ ```
60
+
61
+ **第三步**:执行脚本
62
+
63
+ ```bash
64
+ node path/to/script
65
+ ```
66
+
67
+ ---
68
+
69
+ ## 2. Automator API
70
+
71
+ Automator 模块提供了启动及连接开发者工具的方法。
72
+
73
+ ### 2.1 automator.connect
74
+
75
+ 连接开发者工具。
76
+
77
+ ```typescript
78
+ automator.connect(options: Object): Promise<MiniProgram>
79
+ ```
80
+
81
+ **参数说明**
82
+
83
+ | 字段 | 类型 | 必填 | 默认值 | 说明 |
84
+ |------|------|------|--------|------|
85
+ | wsEndpoint | string | 是 | - | 开发者工具 WebSocket 地址 |
86
+
87
+ **命令行参数**
88
+
89
+ - `--auto <project_root>`: 打开指定项目并开启自动化功能
90
+ - `--auto-port <port>`: 指定自动化监听端口
91
+
92
+ ```bash
93
+ cli --auto /Users/username/demo --auto-port 9420
94
+ ```
95
+
96
+ **示例代码**
97
+
98
+ ```javascript
99
+ automator.connect({
100
+ wsEndpoint: 'ws://localhost:9420'
101
+ }).then(async miniProgram => {
102
+ const page = await miniProgram.navigateTo('/page/component/index')
103
+ await page.setData({})
104
+ })
105
+ ```
106
+
107
+ ### 2.2 automator.launch
108
+
109
+ 启动并连接开发者工具。
110
+
111
+ > ⚠️ 确保工具安全设置中已开启 CLI/HTTP 调用功能
112
+
113
+ ```typescript
114
+ automator.launch(options: Object): Promise<MiniProgram>
115
+ ```
116
+
117
+ **参数说明**
118
+
119
+ | 字段 | 类型 | 必填 | 默认值 | 说明 |
120
+ |------|------|------|--------|------|
121
+ | cliPath | string | 否 | - | 开发者工具命令行工具绝对路径 |
122
+ | projectPath | string | 是 | - | 项目绝对路径 |
123
+ | timeout | number | 否 | 30000 | 启动最长等待时间(毫秒) |
124
+ | port | number | 否 | - | WebSocket 端口号 |
125
+ | account | string | 否 | - | 用户 openid |
126
+ | projectConfig | Object | 否 | - | 覆盖 project.config.json 中的配置 |
127
+ | ticket | string | 否 | - | 开发者工具登录票据 |
128
+
129
+ **cliPath 默认位置**
130
+
131
+ - **Mac**: `/Applications/wechatwebdevtools.app/Contents/MacOS/cli`
132
+ - **Windows**: `C:/Program Files (x86)/Tencent/微信web开发者工具/cli.bat`
133
+
134
+ **示例代码**
135
+
136
+ ```javascript
137
+ automator.launch({
138
+ cliPath: 'path/to/cli',
139
+ projectPath: 'path/to/project',
140
+ projectConfig: {
141
+ setting: {
142
+ autoAudits: true,
143
+ },
144
+ },
145
+ }).then(async miniProgram => {
146
+ const page = await miniProgram.navigateTo('/page/component/index')
147
+ await page.setData({})
148
+ })
149
+ ```
150
+
151
+ ---
152
+
153
+ ## 3. MiniProgram API
154
+
155
+ MiniProgram 模块提供了控制小程序的方法。
156
+
157
+ ### 3.1 页面导航方法
158
+
159
+ #### 3.1.1 miniProgram.pageStack
160
+
161
+ 获取小程序页面堆栈。
162
+
163
+ ```typescript
164
+ miniProgram.pageStack(): Promise<Page[]>
165
+ ```
166
+
167
+ #### 3.1.2 miniProgram.navigateTo
168
+
169
+ 保留当前页面,跳转到应用内的某个页面,同 `wx.navigateTo`。
170
+
171
+ ```typescript
172
+ miniProgram.navigateTo(url: string): Promise<Page>
173
+ ```
174
+
175
+ | 字段 | 类型 | 必填 | 说明 |
176
+ |------|------|------|------|
177
+ | url | string | 是 | 需要跳转的应用内非 tabBar 的页面的路径 |
178
+
179
+ #### 3.1.3 miniProgram.redirectTo
180
+
181
+ 关闭当前页面,跳转到应用内的某个页面,同 `wx.redirectTo`。
182
+
183
+ ```typescript
184
+ miniProgram.redirectTo(url: string): Promise<Page>
185
+ ```
186
+
187
+ #### 3.1.4 miniProgram.navigateBack
188
+
189
+ 关闭当前页面,返回上一页面或多级页面,同 `wx.navigateBack`。
190
+
191
+ ```typescript
192
+ miniProgram.navigateBack(): Promise<Page>
193
+ ```
194
+
195
+ #### 3.1.5 miniProgram.reLaunch
196
+
197
+ 关闭所有页面,打开到应用内的某个页面,同 `wx.reLaunch`。
198
+
199
+ ```typescript
200
+ miniProgram.reLaunch(url: string): Promise<Page>
201
+ ```
202
+
203
+ #### 3.1.6 miniProgram.switchTab
204
+
205
+ 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面,同 `wx.switchTab`。
206
+
207
+ ```typescript
208
+ miniProgram.switchTab(url: string): Promise<Page>
209
+ ```
210
+
211
+ #### 3.1.7 miniProgram.currentPage
212
+
213
+ 获取当前页面。
214
+
215
+ ```typescript
216
+ miniProgram.currentPage(): Promise<Page>
217
+ ```
218
+
219
+ ### 3.2 系统信息方法
220
+
221
+ #### 3.2.1 miniProgram.systemInfo
222
+
223
+ 获取系统信息,同 `wx.getSystemInfo`。
224
+
225
+ ```typescript
226
+ miniProgram.systemInfo(): Promise<Object>
227
+ ```
228
+
229
+ **示例代码**
230
+
231
+ ```javascript
232
+ const systemInfo = await miniProgram.systemInfo()
233
+ if (systemInfo.platform === 'devtools') {
234
+ // Do something
235
+ }
236
+ ```
237
+
238
+ ### 3.3 方法调用与Mock
239
+
240
+ #### 3.3.1 miniProgram.callWxMethod
241
+
242
+ 调用 wx 对象上的指定方法。
243
+
244
+ ```typescript
245
+ miniProgram.callWxMethod(method: string, ...args: any[]): Promise<any>
246
+ ```
247
+
248
+ | 字段 | 类型 | 必填 | 说明 |
249
+ |------|------|------|------|
250
+ | method | string | 是 | 需要调用的方法名 |
251
+ | ...args | array\<any\> | 否 | 方法参数 |
252
+
253
+ > 💡 调用异步方法时无需传入 success 及 fail 回调函数
254
+
255
+ **示例代码**
256
+
257
+ ```javascript
258
+ await miniProgram.callWxMethod('setStorage', {
259
+ key: 'test',
260
+ data: 'test'
261
+ })
262
+ const { data } = await miniProgram.callWxMethod('getStorageSync', 'test')
263
+ console.log(data) // -> 'test'
264
+ ```
265
+
266
+ #### 3.3.2 miniProgram.callPluginWxMethod
267
+
268
+ > 📌 基础库 2.19.3 开始支持
269
+
270
+ 调用插件 wx 对象上的指定方法,用法同 `miniProgram.callWxMethod`。
271
+
272
+ ```typescript
273
+ miniProgram.callPluginWxMethod(pluginId: string, method: string, ...args: any[]): Promise<any>
274
+ ```
275
+
276
+ #### 3.3.3 miniProgram.mockWxMethod
277
+
278
+ > 📌 传入函数功能 automator 0.9.0,基础库 2.9.5 开始支持
279
+
280
+ 覆盖 wx 对象上指定方法的调用结果。
281
+
282
+ ```typescript
283
+ miniProgram.mockWxMethod(method: string, result: any): Promise<void>
284
+ miniProgram.mockWxMethod(method: string, fn: Function | string, ...args: any[]): Promise<void>
285
+ ```
286
+
287
+ **参数说明 - 方式一**
288
+
289
+ | 字段 | 类型 | 必填 | 说明 |
290
+ |------|------|------|------|
291
+ | method | string | 是 | 需要覆盖的方法名 |
292
+ | result | any | 是 | 指定调用结果 |
293
+
294
+ **参数说明 - 方式二**
295
+
296
+ | 字段 | 类型 | 必填 | 说明 |
297
+ |------|------|------|------|
298
+ | method | string | 是 | 需要覆盖的方法名 |
299
+ | fn | Function \| string | 是 | 处理返回函数 |
300
+ | ...args | array\<any\> | 否 | 传入参数 |
301
+
302
+ > ⚠️ fn 同 `miniProgram.evaluate` 的 appFunction 参数一样,无法使用闭包来引用外部变量。此外,你还可以在方法内使用 `this.origin` 来调用原始方法。
303
+
304
+ **示例代码**
305
+
306
+ ```javascript
307
+ // 方式一:直接指定结果
308
+ await miniProgram.mockWxMethod('showModal', {
309
+ confirm: true,
310
+ cancel: false
311
+ })
312
+
313
+ // 方式二:使用函数处理
314
+ await miniProgram.mockWxMethod(
315
+ 'getStorageSync',
316
+ function(key, defVal) {
317
+ if (key === 'name') return 'redhoodsu'
318
+ if (key === 'sex') return 'male'
319
+ return defVal
320
+ },
321
+ 'unknown',
322
+ )
323
+
324
+ // 更改 getSystemInfo 中的 platform 字段
325
+ await miniProgram.mockWxMethod(
326
+ 'getSystemInfo',
327
+ function(obj, platform) {
328
+ return new Promise(resolve => {
329
+ this.origin({
330
+ success(res) {
331
+ res.platform = platform
332
+ resolve(res)
333
+ },
334
+ })
335
+ })
336
+ },
337
+ 'test',
338
+ )
339
+ ```
340
+
341
+ #### 3.3.4 miniProgram.mockPluginWxMethod
342
+
343
+ > 📌 基础库 2.19.3 开始支持
344
+
345
+ 覆盖插件 wx 对象上指定方法的调用结果,用法同 `miniProgram.mockWxMethod`。
346
+
347
+ ```typescript
348
+ miniProgram.mockPluginWxMethod(pluginId: string, method: string, result: any): Promise<void>
349
+ miniProgram.mockPluginWxMethod(pluginId: string, method: string, fn: Function | string, ...args: any[]): Promise<void>
350
+ ```
351
+
352
+ #### 3.3.5 miniProgram.restoreWxMethod
353
+
354
+ 重置 wx 指定方法,消除 mockWxMethod 调用的影响。
355
+
356
+ ```typescript
357
+ miniProgram.restoreWxMethod(method: string): Promise<void>
358
+ ```
359
+
360
+ **示例代码**
361
+
362
+ ```javascript
363
+ console.log(await miniProgram.callWxMethod('getStorageSync', 'test')) // -> ''
364
+ await miniProgram.mockWxMethod('getStorageSync', 'mockValue')
365
+ console.log(await miniProgram.callWxMethod('getStorageSync', 'test')) // -> 'mockValue'
366
+ await miniProgram.restoreWxMethod('getStorageSync')
367
+ console.log(await miniProgram.callWxMethod('getStorageSync', 'test')) // -> ''
368
+ ```
369
+
370
+ #### 3.3.6 miniProgram.restorePluginWxMethod
371
+
372
+ > 📌 基础库 2.19.3 开始支持
373
+
374
+ 重置插件 wx 指定方法,消除 mockPluginWxMethod 调用的影响,用法同 `miniProgram.restoreWxMethod`。
375
+
376
+ ```typescript
377
+ miniProgram.restorePluginWxMethod(pluginId: string, method: string): Promise<void>
378
+ ```
379
+
380
+ ### 3.4 代码执行方法
381
+
382
+ #### 3.4.1 miniProgram.evaluate
383
+
384
+ 往 AppService 注入代码片段并返回执行结果。
385
+
386
+ ```typescript
387
+ miniProgram.evaluate(appFunction: Function | string, ...args: any[]): Promise<any>
388
+ ```
389
+
390
+ | 字段 | 类型 | 必填 | 说明 |
391
+ |------|------|------|------|
392
+ | appFunction | Function \| string | 是 | 代码片段 |
393
+ | ...args | array\<any\> | 否 | 执行时传入参数 |
394
+
395
+ > ⚠️ appFunction 最终会被序列化传递到开发者工具,因此你无法在函数中利用闭包来引用外部变量。
396
+
397
+ **示例代码**
398
+
399
+ ```javascript
400
+ // 方式一:使用 Promise
401
+ let systemInfo = await miniProgram.evaluate(() => {
402
+ return new Promise(resolve => {
403
+ wx.getSystemInfo({
404
+ success(result) {
405
+ resolve(result)
406
+ }
407
+ })
408
+ })
409
+ })
410
+
411
+ // 方式二:同步方法
412
+ systemInfo = await miniProgram.evaluate(() => {
413
+ return wx.getSystemInfoSync()
414
+ })
415
+
416
+ // 方式三:带参数
417
+ await miniProgram.evaluate(key => {
418
+ wx.setStorageSync(key, 'test')
419
+ }, 'test')
420
+
421
+ // 获取全局数据
422
+ const hasLogin = await miniProgram.evaluate(() => getApp().globalData.hasLogin)
423
+ ```
424
+
425
+ ### 3.5 页面操作方法
426
+
427
+ #### 3.5.1 miniProgram.pageScrollTo
428
+
429
+ 将页面滚动到目标位置,同 `wx.pageScrollTo`。
430
+
431
+ ```typescript
432
+ miniProgram.pageScrollTo(scrollTop: number): Promise<void>
433
+ ```
434
+
435
+ | 字段 | 类型 | 必填 | 说明 |
436
+ |------|------|------|------|
437
+ | scrollTop | number | 是 | 滚动到页面的目标位置,单位 px |
438
+
439
+ **示例代码**
440
+
441
+ ```javascript
442
+ await miniProgram.pageScrollTo(50)
443
+ ```
444
+
445
+ #### 3.5.2 miniProgram.screenshot
446
+
447
+ > 📌 automator 0.9.0,基础库 2.9.5,开发者工具 1.02.2001082 开始支持
448
+
449
+ 对当前页面截图,目前只有开发者工具模拟器支持,客户端无法使用。
450
+
451
+ ```typescript
452
+ miniProgram.screenshot(options?: Object): Promise<string | void>
453
+ ```
454
+
455
+ **参数说明**
456
+
457
+ | 字段 | 类型 | 必填 | 默认值 | 说明 |
458
+ |------|------|------|--------|------|
459
+ | options | Object | 否 | - | 截图选项 |
460
+
461
+ 如果不传 options,该方法返回图片数据的 base64 编码。
462
+
463
+ **options 字段**
464
+
465
+ | 字段 | 类型 | 必填 | 说明 |
466
+ |------|------|------|------|
467
+ | path | string | 是 | 图片保存路径 |
468
+
469
+ **示例代码**
470
+
471
+ ```javascript
472
+ await miniProgram.screenshot({
473
+ path: 'screenshot.png'
474
+ })
475
+ ```
476
+
477
+ ### 3.6 高级功能
478
+
479
+ #### 3.6.1 miniProgram.exposeFunction
480
+
481
+ 在 AppService 全局暴露方法,供小程序侧调用测试脚本中的方法。
482
+
483
+ ```typescript
484
+ miniProgram.exposeFunction(name: string, bindingFunction: Function): Promise<void>
485
+ ```
486
+
487
+ | 字段 | 类型 | 必填 | 说明 |
488
+ |------|------|------|------|
489
+ | name | string | 是 | 全局方法名 |
490
+ | bindingFunction | Function | 是 | 脚本方法 |
491
+
492
+ > 💡 你可以利用该方法来监听事件,不支持在小程序侧获取调用结果。
493
+
494
+ **示例代码**
495
+
496
+ ```javascript
497
+ await miniProgram.exposeFunction('onAppShow', options => {
498
+ // Do something...
499
+ })
500
+
501
+ await miniProgram.evaluate(function() {
502
+ wx.onAppShow(function(options) {
503
+ onAppShow(options)
504
+ })
505
+ })
506
+ ```
507
+
508
+ #### 3.6.2 miniProgram.testAccounts
509
+
510
+ > 📌 automator 0.9.0,开发者工具 1.02.2002272 开始支持
511
+
512
+ 获取多账号调试中已添加的用户列表。
513
+
514
+ ```typescript
515
+ miniProgram.testAccounts(): Promise<Account[]>
516
+ ```
517
+
518
+ **Account 字段**
519
+
520
+ | 字段 | 类型 | 说明 |
521
+ |------|------|------|
522
+ | nickName | string | 用户昵称 |
523
+ | openid | string | 账号 openid |
524
+
525
+ **示例代码**
526
+
527
+ ```javascript
528
+ const testAccounts = await miniProgram.testAccounts()
529
+ for (let i = 0, len = testAccounts.length; i < len; i++) {
530
+ const miniProgram = await automator.launch({
531
+ projectPath: 'path/to/project',
532
+ account: testAccounts[i].openid
533
+ })
534
+ // 控制多个用户登录的不同小程序
535
+ }
536
+ ```
537
+
538
+ #### 3.6.3 miniProgram.stopAudits
539
+
540
+ > 📌 automator 0.10.0,开发者工具 1.04.2006242 开始支持
541
+
542
+ 停止体验评分并获取报告。
543
+
544
+ ```typescript
545
+ miniProgram.stopAudits(options?: Object): Promise<Object>
546
+ ```
547
+
548
+ **参数说明**
549
+
550
+ | 字段 | 类型 | 必填 | 默认值 | 说明 |
551
+ |------|------|------|--------|------|
552
+ | options | Object | 否 | - | 选项 |
553
+
554
+ **options 字段**
555
+
556
+ | 字段 | 类型 | 必填 | 默认值 | 说明 |
557
+ |------|------|------|--------|------|
558
+ | path | string | 否 | - | 报告保存路径 |
559
+
560
+ > ⚠️ 需要开启自动运行体验评分选项
561
+
562
+ **示例代码**
563
+
564
+ ```javascript
565
+ automator.launch({
566
+ projectConfig: {
567
+ setting: {
568
+ autoAudits: true,
569
+ },
570
+ },
571
+ }).then(async miniProgram => {
572
+ const data = await miniProgram.stopAudits({
573
+ path: 'report.html'
574
+ })
575
+ console.log(data) // 体验评分报告数据
576
+ })
577
+ ```
578
+
579
+ ### 3.7 票据管理
580
+
581
+ #### 3.7.1 miniProgram.getTicket
582
+
583
+ 获取开发者工具当前的登录票据。
584
+
585
+ > ⚠️ 确保工具安全设置中已开启允许获取工具登录票据功能
586
+
587
+ ```typescript
588
+ miniProgram.getTicket(): Promise<Object>
589
+ ```
590
+
591
+ **返回值说明**
592
+
593
+ | 字段 | 类型 | 说明 |
594
+ |------|------|------|
595
+ | ticket | string | 登录票据 |
596
+ | expiredTime | number | 票据过期时间 |
597
+
598
+ **示例代码**
599
+
600
+ ```javascript
601
+ const result = await miniProgram.getTicket()
602
+ console.log(result.ticket)
603
+ ```
604
+
605
+ #### 3.7.2 miniProgram.setTicket
606
+
607
+ 设置开发者工具登录票据,可在工具运行测试期间更新失效的登录票据。
608
+
609
+ ```typescript
610
+ miniProgram.setTicket(ticket: string): Promise<void>
611
+ ```
612
+
613
+ **示例代码**
614
+
615
+ ```javascript
616
+ // ticket 从已登录的开发者工具获取
617
+ automator.launch({
618
+ ticket,
619
+ }).then(async miniProgram => {
620
+ // 如果初始票据已失效,获取新票据后通过 setTicket 更新
621
+ await miniProgram.setTicket(ticket)
622
+ })
623
+ ```
624
+
625
+ #### 3.7.3 miniProgram.refreshTicket
626
+
627
+ 刷新开发者工具登录票据,可以使票据过期时间重置为两小时。
628
+
629
+ ```typescript
630
+ miniProgram.refreshTicket(): Promise<void>
631
+ ```
632
+
633
+ > ⚠️ 刷新票据后原有的票据即使过期时间未到也会过期
634
+
635
+ **示例代码**
636
+
637
+ ```javascript
638
+ await miniProgram.refreshTicket()
639
+ ```
640
+
641
+ ### 3.8 真机调试
642
+
643
+ #### 3.8.1 miniProgram.remote
644
+
645
+ 开启工具真机调试功能。
646
+
647
+ ```typescript
648
+ miniProgram.remote(auto?: boolean): Promise<void>
649
+ ```
650
+
651
+ | 字段 | 类型 | 必填 | 默认值 | 说明 |
652
+ |------|------|------|--------|------|
653
+ | auto | boolean | 否 | false | 是否自动真机调试 |
654
+
655
+ 调用后脚本会启动工具真机调试功能,并且在控制台上打印二维码,然后你需要使用真机扫码连接使自动化脚本继续跑下去。
656
+
657
+ > 💡 auto 为 true 时,真机上会自动调起小程序,无需扫码,仅支持微信 7.0.6(安卓)、6.6.7(iOS)及以上版本
658
+
659
+ **示例代码**
660
+
661
+ ```javascript
662
+ await miniProgram.remote()
663
+ // 扫码连接成功后在真机上执行自动化脚本
664
+ ```
665
+
666
+ ### 3.9 连接管理
667
+
668
+ #### 3.9.1 miniProgram.disconnect
669
+
670
+ 断开与小程序运行时的连接。
671
+
672
+ ```typescript
673
+ miniProgram.disconnect(): void
674
+ ```
675
+
676
+ **示例代码**
677
+
678
+ ```javascript
679
+ miniProgram.disconnect()
680
+ ```
681
+
682
+ #### 3.9.2 miniProgram.close
683
+
684
+ 断开与小程序运行时的连接并关闭项目窗口。
685
+
686
+ ```typescript
687
+ miniProgram.close(): Promise<void>
688
+ ```
689
+
690
+ **示例代码**
691
+
692
+ ```javascript
693
+ await miniProgram.close()
694
+ ```
695
+
696
+ ### 3.10 事件监听
697
+
698
+ #### 3.10.1 console
699
+
700
+ 日志打印时触发。
701
+
702
+ **msg 参数字段**
703
+
704
+ | 字段 | 类型 | 说明 |
705
+ |------|------|------|
706
+ | type | string | 日志类型,log、info 等 |
707
+ | args | array\<any\> | 日志内容 |
708
+
709
+ **示例代码**
710
+
711
+ ```javascript
712
+ miniProgram.on('console', msg => {
713
+ console.log(msg.type, msg.args)
714
+ })
715
+ ```
716
+
717
+ #### 3.10.2 exception
718
+
719
+ 页面 JS 出错时触发。
720
+
721
+ **error 参数字段**
722
+
723
+ | 字段 | 类型 | 说明 |
724
+ |------|------|------|
725
+ | message | string | 错误信息 |
726
+ | stack | string | 错误堆栈 |
727
+
728
+ **示例代码**
729
+
730
+ ```javascript
731
+ miniProgram.on('exception', err => {
732
+ console.log(err.message, err.stack)
733
+ })
734
+ ```
735
+
736
+ ---
737
+
738
+ ## 4. Page API
739
+
740
+ Page 模块提供了控制小程序页面的方法。
741
+
742
+ ### 4.1 属性
743
+
744
+ #### 4.1.1 page.path
745
+
746
+ 页面路径。
747
+
748
+ ```typescript
749
+ page.path: string
750
+ ```
751
+
752
+ #### 4.1.2 page.query
753
+
754
+ 页面参数。
755
+
756
+ ```typescript
757
+ page.query: Object
758
+ ```
759
+
760
+ ### 4.2 元素选择方法
761
+
762
+ #### 4.2.1 page.$
763
+
764
+ 获取页面元素。
765
+
766
+ ```typescript
767
+ page.$(selector: string): Promise<Element>
768
+ ```
769
+
770
+ | 字段 | 类型 | 必填 | 说明 |
771
+ |------|------|------|------|
772
+ | selector | string | 是 | 选择器 |
773
+
774
+ > 💡 同 WXSS,仅支持部分 CSS 选择器
775
+
776
+ **示例代码**
777
+
778
+ ```javascript
779
+ const page = await miniProgram.currentPage()
780
+ const element = await page.$('.index-desc')
781
+ console.log(element.tagName) // -> 'view'
782
+ ```
783
+
784
+ #### 4.2.2 page.$$
785
+
786
+ 获取页面元素数组。
787
+
788
+ ```typescript
789
+ page.$$(selector: string): Promise<Element[]>
790
+ ```
791
+
792
+ > ⚠️ 该方法跟 $ 一样均无法选择自定义组件内的元素,请使用 `element.$`
793
+
794
+ **示例代码**
795
+
796
+ ```javascript
797
+ const elements = await page.$$('.kind-list-text')
798
+ console.log(elements.length)
799
+ ```
800
+
801
+ ### 4.3 等待方法
802
+
803
+ #### 4.3.1 page.waitFor
804
+
805
+ 等待直到指定条件成立。
806
+
807
+ ```typescript
808
+ page.waitFor(condition: string | number | Function): Promise<void>
809
+ ```
810
+
811
+ | 字段 | 类型 | 必填 | 说明 |
812
+ |------|------|------|------|
813
+ | condition | string \| number \| Function | 是 | 等待条件 |
814
+
815
+ **条件类型说明**
816
+
817
+ - **string 类型**: 当成选择器,当该选择器选中元素个数不为零时,结束等待
818
+ - **number 类型**: 当成超时时长,当经过指定时间后,结束等待
819
+ - **Function 类型**: 当成断言函数,当该函数返回真值时,结束等待
820
+
821
+ **示例代码**
822
+
823
+ ```javascript
824
+ await page.waitFor(5000) // 等待 5 秒
825
+ await page.waitFor('picker') // 等待页面中出现 picker 元素
826
+ await page.waitFor(async () => {
827
+ return (await page.$$('picker')).length > 5
828
+ }) // 等待页面中 picker 元素数量大于 5
829
+ ```
830
+
831
+ ### 4.4 数据操作方法
832
+
833
+ #### 4.4.1 page.data
834
+
835
+ > 📌 传递数据路径 automator 0.6.0,基础库 2.9.0 开始支持
836
+
837
+ 获取页面渲染数据。
838
+
839
+ ```typescript
840
+ page.data(path?: string): Promise<Object>
841
+ ```
842
+
843
+ | 字段 | 类型 | 必填 | 说明 |
844
+ |------|------|------|------|
845
+ | path | string | 否 | 数据路径 |
846
+
847
+ **示例代码**
848
+
849
+ ```javascript
850
+ console.log(await page.data('list'))
851
+ ```
852
+
853
+ #### 4.4.2 page.setData
854
+
855
+ 设置页面渲染数据。
856
+
857
+ ```typescript
858
+ page.setData(data: Object): Promise<void>
859
+ ```
860
+
861
+ | 字段 | 类型 | 必填 | 说明 |
862
+ |------|------|------|------|
863
+ | data | Object | 是 | 要改变的数据 |
864
+
865
+ **示例代码**
866
+
867
+ ```javascript
868
+ await page.setData({
869
+ text: 'changed data'
870
+ })
871
+ ```
872
+
873
+ ### 4.5 页面信息方法
874
+
875
+ #### 4.5.1 page.size
876
+
877
+ 获取页面大小。
878
+
879
+ ```typescript
880
+ page.size(): Promise<Object>
881
+ ```
882
+
883
+ **返回值说明**
884
+
885
+ | 字段 | 类型 | 说明 |
886
+ |------|------|------|
887
+ | width | number | 页面可滚动宽度 |
888
+ | height | number | 页面可滚动高度 |
889
+
890
+ **示例代码**
891
+
892
+ ```javascript
893
+ const { width, height } = await page.size()
894
+ console.log(width, height)
895
+ ```
896
+
897
+ #### 4.5.2 page.scrollTop
898
+
899
+ > 📌 automator 0.7.0 开始支持
900
+
901
+ 获取页面滚动位置。
902
+
903
+ ```typescript
904
+ page.scrollTop(): Promise<number>
905
+ ```
906
+
907
+ **示例代码**
908
+
909
+ ```javascript
910
+ await miniProgram.pageScrollTo(20)
911
+ console.log(await page.scrollTop())
912
+ ```
913
+
914
+ ### 4.6 方法调用
915
+
916
+ #### 4.6.1 page.callMethod
917
+
918
+ 调用页面指定方法。
919
+
920
+ ```typescript
921
+ page.callMethod(method: string, ...args: any[]): Promise<any>
922
+ ```
923
+
924
+ | 字段 | 类型 | 必填 | 说明 |
925
+ |------|------|------|------|
926
+ | method | string | 是 | 需要调用的方法名 |
927
+ | ...args | array\<any\> | 否 | 方法参数 |
928
+
929
+ **示例代码**
930
+
931
+ ```javascript
932
+ await page.callMethod('onShareAppMessage')
933
+ ```
934
+
935
+ ---
936
+
937
+ ## 5. Element API
938
+
939
+ Element 模块提供了控制小程序页面元素的方法。
940
+
941
+ ### 5.1 属性
942
+
943
+ #### 5.1.1 element.tagName
944
+
945
+ 标签名,小写。
946
+
947
+ ```typescript
948
+ element.tagName: string
949
+ ```
950
+
951
+ ### 5.2 元素查询方法
952
+
953
+ #### 5.2.1 element.$
954
+
955
+ 在元素范围内获取元素。
956
+
957
+ ```typescript
958
+ element.$(selector: string): Promise<Element>
959
+ ```
960
+
961
+ **示例代码**
962
+
963
+ ```javascript
964
+ let element = await page.$('.index-hd')
965
+ element = await element.$('.index-desc')
966
+ console.log(await element.text())
967
+ ```
968
+
969
+ #### 5.2.2 element.$$
970
+
971
+ 在元素范围内获取元素数组。
972
+
973
+ ```typescript
974
+ element.$$(selector: string): Promise<Element[]>
975
+ ```
976
+
977
+ **示例代码**
978
+
979
+ ```javascript
980
+ const element = await page.$('.index-bd')
981
+ const elements = await element.$$('.kind-list-text')
982
+ console.log(await elements[0].text())
983
+ ```
984
+
985
+ ### 5.3 元素信息方法
986
+
987
+ #### 5.3.1 element.size
988
+
989
+ 获取元素大小。
990
+
991
+ ```typescript
992
+ element.size(): Promise<Object>
993
+ ```
994
+
995
+ **返回值说明**
996
+
997
+ | 字段 | 类型 | 说明 |
998
+ |------|------|------|
999
+ | width | number | 元素宽度 |
1000
+ | height | number | 元素高度 |
1001
+
1002
+ **示例代码**
1003
+
1004
+ ```javascript
1005
+ const { width, height } = await element.size()
1006
+ console.log(width, height)
1007
+ ```
1008
+
1009
+ #### 5.3.2 element.offset
1010
+
1011
+ 获取元素绝对位置。
1012
+
1013
+ ```typescript
1014
+ element.offset(): Promise<Object>
1015
+ ```
1016
+
1017
+ **返回值说明**
1018
+
1019
+ | 字段 | 类型 | 说明 |
1020
+ |------|------|------|
1021
+ | left | number | 左上角 x 坐标,单位:px |
1022
+ | top | number | 左上角 y 坐标,单位:px |
1023
+
1024
+ > 💡 坐标信息以页面左上角为原点
1025
+
1026
+ **示例代码**
1027
+
1028
+ ```javascript
1029
+ const { left, top } = await element.offset()
1030
+ console.log(left, top)
1031
+ ```
1032
+
1033
+ #### 5.3.3 element.text
1034
+
1035
+ 获取元素文本。
1036
+
1037
+ ```typescript
1038
+ element.text(): Promise<string>
1039
+ ```
1040
+
1041
+ **示例代码**
1042
+
1043
+ ```javascript
1044
+ const element = await page.$('.index-desc')
1045
+ console.log(await element.text())
1046
+ ```
1047
+
1048
+ ### 5.4 属性与样式方法
1049
+
1050
+ #### 5.4.1 element.attribute
1051
+
1052
+ 获取元素特性。
1053
+
1054
+ ```typescript
1055
+ element.attribute(name: string): Promise<string>
1056
+ ```
1057
+
1058
+ | 字段 | 类型 | 必填 | 说明 |
1059
+ |------|------|------|------|
1060
+ | name | string | 是 | 特性名 |
1061
+
1062
+ **示例代码**
1063
+
1064
+ ```javascript
1065
+ const element = await page.$('.index-logo')
1066
+ console.log(await element.attribute('src')) // -> 'resources/kind/logo.png'
1067
+ ```
1068
+
1069
+ #### 5.4.2 element.property
1070
+
1071
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1072
+
1073
+ 获取元素属性。
1074
+
1075
+ ```typescript
1076
+ element.property(name: string): Promise<any>
1077
+ ```
1078
+
1079
+ **element.property 与 element.attribute 主要区别**
1080
+
1081
+ - `element.attribute` 获取的是标签上的值,因此它的返回类型一定是字符串,`element.property` 则不一定
1082
+ - `element.attribute` 可以获取到 class 和 id 之类的值,`element.property` 不行
1083
+ - `element.property` 可以获取到文档里对应组件列举的大部分属性值,比如表单 input 等组件的 value 值
1084
+
1085
+ **示例代码**
1086
+
1087
+ ```javascript
1088
+ const element = await page.$('input')
1089
+ console.log(await element.property('value'))
1090
+ ```
1091
+
1092
+ #### 5.4.3 element.wxml
1093
+
1094
+ 获取元素 WXML。
1095
+
1096
+ ```typescript
1097
+ element.wxml(): Promise<string>
1098
+ ```
1099
+
1100
+ #### 5.4.4 element.outerWxml
1101
+
1102
+ 同 wxml,只是会获取到元素本身。
1103
+
1104
+ ```typescript
1105
+ element.outerWxml(): Promise<string>
1106
+ ```
1107
+
1108
+ **示例代码**
1109
+
1110
+ ```javascript
1111
+ const element = await page.$('.index-desc')
1112
+ console.log(await element.wxml())
1113
+ console.log(await element.outerWxml())
1114
+ ```
1115
+
1116
+ #### 5.4.5 element.value
1117
+
1118
+ 获取元素值。
1119
+
1120
+ ```typescript
1121
+ element.value(): Promise<string>
1122
+ ```
1123
+
1124
+ **示例代码**
1125
+
1126
+ ```javascript
1127
+ const element = await page.$('.weui-input')
1128
+ console.log(await element.value())
1129
+ ```
1130
+
1131
+ #### 5.4.6 element.style
1132
+
1133
+ 获取元素样式值。
1134
+
1135
+ ```typescript
1136
+ element.style(name: string): Promise<string>
1137
+ ```
1138
+
1139
+ | 字段 | 类型 | 必填 | 说明 |
1140
+ |------|------|------|------|
1141
+ | name | string | 是 | 样式名 |
1142
+
1143
+ **示例代码**
1144
+
1145
+ ```javascript
1146
+ const element = await page.$('.index-desc')
1147
+ console.log(await element.style('color')) // -> 'rgb(136, 136, 136)'
1148
+ ```
1149
+
1150
+ ### 5.5 交互操作方法
1151
+
1152
+ #### 5.5.1 element.tap
1153
+
1154
+ 点击元素。
1155
+
1156
+ ```typescript
1157
+ element.tap(): Promise<void>
1158
+ ```
1159
+
1160
+ **示例代码**
1161
+
1162
+ ```javascript
1163
+ const element = await page.$('.kind-list-item-hd')
1164
+ await element.tap()
1165
+ ```
1166
+
1167
+ #### 5.5.2 element.longpress
1168
+
1169
+ 长按元素。
1170
+
1171
+ ```typescript
1172
+ element.longpress(): Promise<void>
1173
+ ```
1174
+
1175
+ #### 5.5.3 element.touchstart
1176
+
1177
+ > 📌 automator 0.8.0,基础库 2.9.1 开始支持
1178
+
1179
+ 手指开始触摸元素。
1180
+
1181
+ ```typescript
1182
+ element.touchstart(options: Object): Promise<void>
1183
+ ```
1184
+
1185
+ **options 字段**
1186
+
1187
+ | 字段 | 类型 | 必填 | 说明 |
1188
+ |------|------|------|------|
1189
+ | touches | array\<Touch\> | 是 | 触摸事件,当前停留在屏幕中的触摸点信息的数组 |
1190
+ | changedTouches | array\<Touch\> | 是 | 触摸事件,当前变化的触摸点信息的数组 |
1191
+
1192
+ #### 5.5.4 element.touchmove
1193
+
1194
+ > 📌 automator 0.8.0,基础库 2.9.1 开始支持
1195
+
1196
+ 手指触摸元素后移动。
1197
+
1198
+ ```typescript
1199
+ element.touchmove(options: Object): Promise<void>
1200
+ ```
1201
+
1202
+ > 💡 options 字段同 touchstart
1203
+
1204
+ #### 5.5.5 element.touchend
1205
+
1206
+ > 📌 automator 0.8.0,基础库 2.9.1 开始支持
1207
+
1208
+ 手指结束触摸元素。
1209
+
1210
+ ```typescript
1211
+ element.touchend(options: Object): Promise<void>
1212
+ ```
1213
+
1214
+ > 💡 options 字段同 touchstart
1215
+
1216
+ **综合示例代码**
1217
+
1218
+ ```javascript
1219
+ const element = await page.$('.touch')
1220
+
1221
+ await element.touchstart({
1222
+ touches: [{
1223
+ identifier: 1,
1224
+ pageX: 500,
1225
+ pageY: 500
1226
+ }],
1227
+ changedTouches: [{
1228
+ identifier: 1,
1229
+ pageX: 500,
1230
+ pageY: 500
1231
+ }]
1232
+ })
1233
+
1234
+ await element.touchend({
1235
+ touches: [],
1236
+ changedTouches: [{
1237
+ identifier: 1,
1238
+ pageX: 500,
1239
+ pageY: 500
1240
+ }]
1241
+ })
1242
+ ```
1243
+
1244
+ #### 5.5.6 element.trigger
1245
+
1246
+ 触发元素事件。
1247
+
1248
+ ```typescript
1249
+ element.trigger(type: string, detail?: Object): Promise<void>
1250
+ ```
1251
+
1252
+ | 字段 | 类型 | 必填 | 说明 |
1253
+ |------|------|------|------|
1254
+ | type | string | 是 | 触发事件类型 |
1255
+ | detail | Object | 否 | 触发事件时传递的 detail 值 |
1256
+
1257
+ **示例代码**
1258
+
1259
+ ```javascript
1260
+ const element = await page.$('picker')
1261
+ await element.trigger('change', { value: 1 })
1262
+ ```
1263
+
1264
+ > ⚠️ 该方法无法改变组件状态,仅触发响应方法,也无法触发用户操作事件,即 tap,longpress 等事件,请使用对应的其它方法调用
1265
+
1266
+ #### 5.5.7 element.input
1267
+
1268
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1269
+
1270
+ 输入文本,仅 input、textarea 组件可以使用。
1271
+
1272
+ ```typescript
1273
+ element.input(value: string): Promise<void>
1274
+ ```
1275
+
1276
+ | 字段 | 类型 | 必填 | 说明 |
1277
+ |------|------|------|------|
1278
+ | value | string | 是 | 需要输入的文本 |
1279
+
1280
+ **示例代码**
1281
+
1282
+ ```javascript
1283
+ const element = await page.$('input')
1284
+ await element.input('test')
1285
+ ```
1286
+
1287
+ ### 5.6 组件方法
1288
+
1289
+ #### 5.6.1 element.callMethod
1290
+
1291
+ > 📌 automator 0.6.0,基础库 2.9.0 开始支持
1292
+
1293
+ 调用组件实例指定方法,仅自定义组件可以使用。
1294
+
1295
+ ```typescript
1296
+ element.callMethod(method: string, ...args: any[]): Promise<any>
1297
+ ```
1298
+
1299
+ **示例代码**
1300
+
1301
+ ```javascript
1302
+ const element = await page.$('set-tab-bar')
1303
+ await element.callMethod('navigateBack')
1304
+ ```
1305
+
1306
+ #### 5.6.2 element.data
1307
+
1308
+ > 📌 automator 0.6.0,基础库 2.9.0 开始支持
1309
+
1310
+ 获取组件实例渲染数据,仅自定义组件可以使用。
1311
+
1312
+ ```typescript
1313
+ element.data(path?: string): Promise<Object>
1314
+ ```
1315
+
1316
+ **示例代码**
1317
+
1318
+ ```javascript
1319
+ const element = await page.$('set-tab-bar')
1320
+ console.log(await element.data('hasSetTabBarBadge'))
1321
+ ```
1322
+
1323
+ #### 5.6.3 element.setData
1324
+
1325
+ > 📌 automator 0.6.0,基础库 2.9.0 开始支持
1326
+
1327
+ 设置组件实例渲染数据,仅自定义组件可以使用。
1328
+
1329
+ ```typescript
1330
+ element.setData(data: Object): Promise<void>
1331
+ ```
1332
+
1333
+ **示例代码**
1334
+
1335
+ ```javascript
1336
+ const element = await page.$('set-tab-bar')
1337
+ await element.setData({
1338
+ hasSetTabBarBadge: true
1339
+ })
1340
+ ```
1341
+
1342
+ #### 5.6.4 element.callContextMethod
1343
+
1344
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1345
+
1346
+ 调用上下文 Context 对象方法,仅 video 组件可以使用。
1347
+
1348
+ ```typescript
1349
+ element.callContextMethod(method: string, ...args: any[]): Promise<any>
1350
+ ```
1351
+
1352
+ > ⚠️ video 组件必须设置了 id 才能使用
1353
+
1354
+ **示例代码**
1355
+
1356
+ ```javascript
1357
+ const element = await page.$('video')
1358
+ await element.callContextMethod('play')
1359
+ ```
1360
+
1361
+ ### 5.7 滚动视图方法
1362
+
1363
+ #### 5.7.1 element.scrollWidth
1364
+
1365
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1366
+
1367
+ 获取滚动宽度,仅 scroll-view 组件可以使用。
1368
+
1369
+ ```typescript
1370
+ element.scrollWidth(): Promise<number>
1371
+ ```
1372
+
1373
+ #### 5.7.2 element.scrollHeight
1374
+
1375
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1376
+
1377
+ 获取滚动高度,仅 scroll-view 组件可以使用。
1378
+
1379
+ ```typescript
1380
+ element.scrollHeight(): Promise<number>
1381
+ ```
1382
+
1383
+ #### 5.7.3 element.scrollTo
1384
+
1385
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1386
+
1387
+ 滚动到指定位置,仅 scroll-view 组件可以使用。
1388
+
1389
+ ```typescript
1390
+ element.scrollTo(x: number, y: number): Promise<void>
1391
+ ```
1392
+
1393
+ | 字段 | 类型 | 必填 | 说明 |
1394
+ |------|------|------|------|
1395
+ | x | number | 是 | 横向滚动位置 |
1396
+ | y | number | 是 | 纵向滚动位置 |
1397
+
1398
+ **示例代码**
1399
+
1400
+ ```javascript
1401
+ const element = await page.$('scroll-view')
1402
+ const y = (await element.scrollHeight()) - 50
1403
+ await element.scrollTo(0, y)
1404
+ ```
1405
+
1406
+ ### 5.8 其他组件专用方法
1407
+
1408
+ #### 5.8.1 element.swipeTo
1409
+
1410
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1411
+
1412
+ 滑动到指定滑块,仅 swiper 组件可以使用。
1413
+
1414
+ ```typescript
1415
+ element.swipeTo(index: number): Promise<void>
1416
+ ```
1417
+
1418
+ | 字段 | 类型 | 必填 | 说明 |
1419
+ |------|------|------|------|
1420
+ | index | number | 是 | 目标滑块的 index |
1421
+
1422
+ **示例代码**
1423
+
1424
+ ```javascript
1425
+ const element = await page.$('swiper')
1426
+ await element.swipeTo(2)
1427
+ ```
1428
+
1429
+ #### 5.8.2 element.moveTo
1430
+
1431
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1432
+
1433
+ 移动视图容器,仅 movable-view 组件可以使用。
1434
+
1435
+ ```typescript
1436
+ element.moveTo(x: number, y: number): Promise<void>
1437
+ ```
1438
+
1439
+ | 字段 | 类型 | 必填 | 说明 |
1440
+ |------|------|------|------|
1441
+ | x | number | 是 | x 轴方向的偏移 |
1442
+ | y | number | 是 | y 轴方向的偏移 |
1443
+
1444
+ **示例代码**
1445
+
1446
+ ```javascript
1447
+ const element = await page.$('movable-view')
1448
+ await element.moveTo(40, 40)
1449
+ ```
1450
+
1451
+ #### 5.8.3 element.slideTo
1452
+
1453
+ > 📌 automator 0.9.0,基础库 2.9.5 开始支持
1454
+
1455
+ 滑动到指定数值,仅 slider 组件可以使用。
1456
+
1457
+ ```typescript
1458
+ element.slideTo(value: number): Promise<void>
1459
+ ```
1460
+
1461
+ | 字段 | 类型 | 必填 | 说明 |
1462
+ |------|------|------|------|
1463
+ | value | number | 是 | 要设置的值 |
1464
+
1465
+ **示例代码**
1466
+
1467
+ ```javascript
1468
+ const element = await page.$('slider')
1469
+ await element.slideTo(10)
1470
+ ```
1471
+
1472
+ ---
1473
+
1474
+ ## 6. 常用示例
1475
+
1476
+ 这里提供一些常用的测试方法示例,以帮助你更好地去使用自动化 SDK 完成测试任务。
1477
+
1478
+ ### 6.1 错误处理
1479
+
1480
+ SDK 的方法调用有可能会抛出错误,比如 `miniProgram.navigateTo('path/to/page')` 在页面不存在时会出错。
1481
+
1482
+ 在可能出错的代码上,你可以使用 `try catch` 进行处理:
1483
+
1484
+ ```javascript
1485
+ automator.launch().then(async miniProgram => {
1486
+ let page
1487
+ try {
1488
+ page = await miniProgram.navigateTo('/page/component/index')
1489
+ } catch (e) {
1490
+ // 处理出错情况
1491
+ console.log(e.message)
1492
+ }
1493
+ })
1494
+ ```
1495
+
1496
+ ### 6.2 模板测试
1497
+
1498
+ 小程序的模板是由 WXML 标记语言编写的。在执行时,小程序会将模板和页面数据相结合渲染出最终的页面来。测试框架 Jest 提供了一项很棒的**快照**功能。利用这个特性和 SDK 提供的设置页面数据接口,你可以很轻松地测试模板文件在不同数据下渲染出来的结果是否正确。
1499
+
1500
+ 下面是小程序示例测试接口页模板的代码示例:
1501
+
1502
+ ```javascript
1503
+ const automator = require('miniprogram-automator')
1504
+
1505
+ describe('api', () => {
1506
+ let miniProgram
1507
+ let page
1508
+
1509
+ beforeAll(async () => {
1510
+ miniProgram = await automator.launch({
1511
+ projectPath: 'path/to/miniprogram-demo'
1512
+ })
1513
+ page = await miniProgram.reLaunch('/page/API/index')
1514
+ await page.waitFor(500)
1515
+ })
1516
+
1517
+ afterAll(async () => {
1518
+ await miniProgram.close()
1519
+ })
1520
+
1521
+ it('wxml', async () => {
1522
+ const element = await page.$('page')
1523
+ expect(await element.wxml()).toMatchSnapshot()
1524
+ await page.setData({
1525
+ list: []
1526
+ })
1527
+ expect(await element.wxml()).toMatchSnapshot()
1528
+ })
1529
+ })
1530
+ ```
1531
+
1532
+ ### 6.3 测试环境
1533
+
1534
+ 在测试时,有时候你可能需要执行一些特殊逻辑,比如使用测试账号,或者使用不同的请求地址。这种情况我们建议在小程序代码中植入这部分代码,然后在全局对象 globalData 上设置开关,通过 SDK 提供的执行代码片段功能在测试时开启。
1535
+
1536
+ 下面是小程序示例测试登录接口页模板的代码示例:
1537
+
1538
+ ```javascript
1539
+ const automator = require('miniprogram-automator')
1540
+
1541
+ describe('api', () => {
1542
+ let miniProgram
1543
+ let page
1544
+
1545
+ beforeAll(async () => {
1546
+ miniProgram = await automator.launch({
1547
+ projectPath: 'path/to/miniprogram-demo'
1548
+ })
1549
+ // 直接更改全局变量
1550
+ await miniProgram.evaluate(() => {
1551
+ getApp().globalData.hasLogin = true
1552
+ })
1553
+ page = await miniProgram.reLaunch('/page/API/pages/login/login')
1554
+ await page.waitFor(500)
1555
+ })
1556
+
1557
+ afterAll(async () => {
1558
+ await miniProgram.close()
1559
+ })
1560
+
1561
+ it('wxml', async () => {
1562
+ const element = await page.$('page')
1563
+ expect(await element.wxml()).toMatchSnapshot()
1564
+ })
1565
+ })
1566
+ ```
1567
+
1568
+ ### 6.4 伪造请求结果
1569
+
1570
+ 在测试环境中,有时为了模拟各种情况,需要对 wx 方法调用的结果进行伪造,比如伪造地理位置、伪造请求结果等,这种情况下就可以使用 `miniProgram.mockWxMethod`。
1571
+
1572
+ 下面是伪造特定请求结果的代码示例:
1573
+
1574
+ ```javascript
1575
+ const automator = require('miniprogram-automator')
1576
+
1577
+ describe('api', () => {
1578
+ let miniProgram
1579
+
1580
+ beforeAll(async () => {
1581
+ miniProgram = await automator.launch({
1582
+ projectPath: 'path/to/miniprogram-demo'
1583
+ })
1584
+ })
1585
+
1586
+ afterAll(async () => {
1587
+ await miniProgram.close()
1588
+ })
1589
+
1590
+ it('request', async () => {
1591
+ const mockData = [
1592
+ {
1593
+ rule: 'testRequest',
1594
+ result: {
1595
+ data: 'test',
1596
+ cookies: [],
1597
+ header: {},
1598
+ statusCode: 200,
1599
+ },
1600
+ },
1601
+ ]
1602
+
1603
+ await miniProgram.mockWxMethod(
1604
+ 'request',
1605
+ function(obj, data) {
1606
+ for (let i = 0, len = data.length; i < len; i++) {
1607
+ const item = data[i]
1608
+ const rule = new RegExp(item.rule)
1609
+ if (rule.test(obj.url)) {
1610
+ return item.result
1611
+ }
1612
+
1613
+ // 没命中规则的真实访问后台
1614
+ return new Promise(resolve => {
1615
+ obj.success = res => resolve(res)
1616
+ obj.fail = res => resolve(res)
1617
+ this.origin(obj)
1618
+ })
1619
+ }
1620
+ },
1621
+ mockData,
1622
+ )
1623
+
1624
+ const result = await miniProgram.callWxMethod('request', {
1625
+ url: 'https://14592619.qcloud.la/testRequest',
1626
+ })
1627
+ console.log(result.data) // -> 'test'
1628
+ await miniProgram.restoreWxMethod('request')
1629
+ })
1630
+ })
1631
+ ```
1632
+
1633
+ ---
1634
+
1635
+ ## 7. 真机自动化
1636
+
1637
+ 小程序自动化除了能够控制开发者工具中的小程序模拟器,也支持通过远程调试控制真机,以达到在真机上进行自动化测试的目的。
1638
+
1639
+ ### 7.1 运行环境
1640
+
1641
+ - 确保目标机器上的基础库版本为 `2.7.3` 及以上
1642
+
1643
+ ### 7.2 使用方式
1644
+
1645
+ 在编写完测试用例并且在工具模拟器上测试成功之后,假如想要在真机上跑自动化,可以通过以下两种方法实现。
1646
+
1647
+ #### 7.2.1 通过 SDK 启动
1648
+
1649
+ 你可以在测试脚本开头使用 `miniProgram.remote` 接口启动工具的真机调试功能,调用成功后脚本会在控制台打印二维码。使用目标机器扫码成功连接后,脚本会继续在真机上执行下去。
1650
+
1651
+ **脚本示例**
1652
+
1653
+ ```javascript
1654
+ const automator = require('miniprogram-automator')
1655
+
1656
+ automator.launch({
1657
+ cliPath: 'path/to/cli',
1658
+ projectPath: 'path/to/project',
1659
+ }).then(async miniProgram => {
1660
+ await miniProgram.remote() // 扫码登录连接真机,在真机上执行后续测试脚本
1661
+ const page = await miniProgram.reLaunch('/page/component/index')
1662
+ await page.waitFor(500)
1663
+ const element = await page.$('.kind-list-item-hd')
1664
+ console.log(await element.attribute('class'))
1665
+ await element.tap()
1666
+ await miniProgram.close()
1667
+ })
1668
+ ```
1669
+
1670
+ #### 7.2.2 手工启动
1671
+
1672
+ 如果工具是打开常驻并且使用 `automator.connect` 接口进行连接,那么可以先手工启用工具的真机调试功能后再运行测试脚本,这样就可以在真机上测试小程序了。
1673
+
1674
+ ---
1675
+
1676
+ ## 8. 录制回放
1677
+
1678
+ 开发者可以将测试操作提前录制好,然后通过执行录制脚本来实现测试过程的回放。
1679
+
1680
+ ### 8.1 运行环境要求
1681
+
1682
+ - 下载并安装 `1.05.2110202` 或以上版本的开发者工具
1683
+ - 基础库版本为 `2.19.6` 及以上
1684
+
1685
+ ### 8.2 使用流程
1686
+
1687
+ #### 8.2.1 工具 -> 自动化测试
1688
+
1689
+ 通过工具菜单打开自动化测试窗口。
1690
+
1691
+ #### 8.2.2 新建用例并开始录制
1692
+
1693
+ 新建会弹出一个新建弹窗,允许:
1694
+
1695
+ - 修改用例名
1696
+ - 选择是否开启 mock
1697
+ - 修改录制时的最大等待时间(默认值为 10s)
1698
+ - 配置规则忽略随机生成的 classname
1699
+ - 配置清除缓存选项
1700
+
1701
+ 开始录制后,正常点击小程序元素可进行录制,录制结束后可以再微调等待时间等。
1702
+
1703
+ #### 8.2.3 CGI Mock
1704
+
1705
+ 支持 mock `wx.request`/`wx.cloud.callFunction` 等接口。
1706
+
1707
+ > 💡 云开发相关的接口支持的最低工具版本是 `1.06.2206242`
1708
+
1709
+ #### 8.2.4 断言/检查
1710
+
1711
+ 录制时可以记录 data 快照/wxml 快照,用于回放时匹配校验,或者选择检查元素,断言元素存在/innertext 是否相等。
1712
+
1713
+ **支持的断言类型:**
1714
+
1715
+ 1. **data 快照**: 记录当前 `page.data` 数据,回放时进行匹配
1716
+ 2. **wxml 快照**: 记录 wxml 字符串
1717
+ 3. **检查元素**: 检查元素是否存在或文本内容
1718
+ 4. **截屏** (工具最低可用版本 `1.06.2206090`): 以 base64 格式存储截屏结果
1719
+
1720
+ #### 8.2.5 重新录制
1721
+
1722
+ 重新录制会覆盖之前录制的用例步骤。
1723
+
1724
+ #### 8.2.6 回放
1725
+
1726
+ 点击回放可进行回放操作,失败会标注失败原因。另外,支持扫码后在真机回放用例。
1727
+
1728
+ #### 8.2.7 回放全部
1729
+
1730
+ 选择回放全部,会生成一个简易测试报告,并保存到本地。
1731
+
1732
+ 也可选择使用工具命令行回放:
1733
+
1734
+ ```bash
1735
+ # 打开自动化测试窗口
1736
+ cli auto-replay --project /Users/username/demo
1737
+
1738
+ # 打开自动化测试窗口并回放全部测试用例
1739
+ cli auto-replay --project /Users/username/demo --replay-all
1740
+ ```
1741
+
1742
+ #### 8.2.8 回放配置
1743
+
1744
+ 工具版本 `1.06.2211012` 以上允许配置回放时截图:
1745
+
1746
+ - 如果配置失败时截图,则图片内容以 base64 存放在回放结果文件中
1747
+ - 如果配置每个步骤都截图,则图片保存在和回放结果文件的同名文件夹中
1748
+
1749
+ #### 8.2.9 小程序云测回放
1750
+
1751
+ 本地回放时,是基于开发者工具本地代码版本。如果开发者希望在其他小程序版本测试(如回归测试中在体验版对多个用例进行回放),可以尝试使用**小程序云测**。
1752
+
1753
+ 小程序云测支持将录制好的用例,在开发中版本、体验版、线上版进行回放,支持定时任务/API 任务,并生成详细的测试报告。
1754
+
1755
+ ### 8.3 其他功能
1756
+
1757
+ #### 8.3.1 企业微信小程序支持
1758
+
1759
+ 工具版本 `1.06.2209152` 以上支持企业微信小程序进行录制回放自动化测试。切换到企业微信小程序模式,然后企业微信基础库选择 2.20.3,即可和普通小程序一样使用录制回放功能。
1760
+
1761
+ #### 8.3.2 测试账号切换
1762
+
1763
+ 点击头像,可切换测试账号。
1764
+
1765
+ #### 8.3.3 配置文件说明
1766
+
1767
+ 测试保存目录默认在 `minitest/`,可在 `project.config.json` 修改:
1768
+
1769
+ ```json
1770
+ "testRoot": "minitest/"
1771
+ ```
1772
+
1773
+ ---
1774
+
1775
+ ## 9. FAQ
1776
+
1777
+ ### 9.1 怎么操作系统原生组件,如用户授权、位置选择等?
1778
+
1779
+ 用户授权框等系统组件不提供方法获取和操作,请在执行自动化测试前确保已手工对所需权限进行授权。
1780
+
1781
+ 位置选择等调用 wx 对象接口触发的原生界面组件,可以直接使用 `miniProgram.mockWxMethod` 指定返回结果。
1782
+
1783
+ ### 9.2 Node.js 脚本执行完为什么不会退出?
1784
+
1785
+ 请确保在测试执行完毕后调用 `miniProgram.close` 或者 `miniProgram.disconnect` 断开与工具的连接。
1786
+
1787
+ ### 9.3 怎么在一台机器上登录多个账号测试?
1788
+
1789
+ 可以使用工具的多账号调试功能,配合自动化的 `miniProgram.testAccounts` 来达到目的。
1790
+
1791
+ ### 9.4 怎么在多个机器上的工具登录相同账号运行测试?
1792
+
1793
+ 利用 `miniProgram.getTicket` 接口可以获取到当前工具的登录票据,然后就可以使用该票据在其它机器上登录工具。票据具体怎么从机器上同步到另一台机器上,需要开发者自行维护。
1794
+
1795
+ ---
1796
+
1797
+ ## 📚 附录
1798
+
1799
+ ### A. CLI 默认路径
1800
+
1801
+ **Mac**
1802
+
1803
+ ```bash
1804
+ /Applications/wechatwebdevtools.app/Contents/MacOS/cli
1805
+ ```
1806
+
1807
+ **Windows**
1808
+
1809
+ ```bash
1810
+ C:/Program Files (x86)/Tencent/微信web开发者工具/cli.bat
1811
+ ```
1812
+
1813
+ ### B. 版本要求总结
1814
+
1815
+ | 功能 | 最低版本要求 |
1816
+ |------|-------------|
1817
+ | 基本自动化 | 基础库 2.7.3 + 工具 1.02.1907232 |
1818
+ | 传入函数 Mock | automator 0.9.0 + 基础库 2.9.5 |
1819
+ | 插件 wx 方法调用 | 基础库 2.19.3 |
1820
+ | 截图功能 | automator 0.9.0 + 基础库 2.9.5 + 工具 1.02.2001082 |
1821
+ | 录制回放 | 基础库 2.19.6 + 工具 1.05.2110202 |
1822
+ | 云开发 Mock | 工具 1.06.2206242 |
1823
+ | 企业微信小程序 | 工具 1.06.2209152 |
1824
+
1825
+ ### C. 相关链接
1826
+
1827
+ - 官方文档:<https://developers.weixin.qq.com/miniprogram/dev/devtools/auto/>
1828
+ - Jest 官网:<https://jestjs.io/>
1829
+ - 小程序示例:<https://github.com/wechat-miniprogram/miniprogram-demo>
1830
+
1831
+ ---
1832
+
1833
+ ## 🎯 完整测试示例
1834
+
1835
+ ```javascript
1836
+ const automator = require('miniprogram-automator')
1837
+
1838
+ describe('Mini Program Automation Test', () => {
1839
+ let miniProgram
1840
+ let page
1841
+
1842
+ beforeAll(async () => {
1843
+ miniProgram = await automator.launch({
1844
+ projectPath: 'path/to/project'
1845
+ })
1846
+ page = await miniProgram.reLaunch('/page/index/index')
1847
+ await page.waitFor(500)
1848
+ }, 30000)
1849
+
1850
+ afterAll(async () => {
1851
+ await miniProgram.close()
1852
+ })
1853
+
1854
+ it('should navigate to detail page', async () => {
1855
+ const button = await page.$('.nav-button')
1856
+ await button.tap()
1857
+ await page.waitFor(500)
1858
+ expect((await miniProgram.currentPage()).path).toBe('page/detail/detail')
1859
+ })
1860
+
1861
+ it('should input text correctly', async () => {
1862
+ const input = await page.$('input')
1863
+ await input.input('test text')
1864
+ expect(await input.value()).toBe('test text')
1865
+ })
1866
+
1867
+ it('should handle mock request', async () => {
1868
+ await miniProgram.mockWxMethod('request', {
1869
+ data: { success: true },
1870
+ statusCode: 200
1871
+ })
1872
+ const result = await miniProgram.callWxMethod('request', {
1873
+ url: 'https://api.example.com/test'
1874
+ })
1875
+ expect(result.data.success).toBe(true)
1876
+ await miniProgram.restoreWxMethod('request')
1877
+ })
1878
+ })
1879
+ ```
1880
+
1881
+ ---
1882
+
1883
+ **文档版本**: v1.0
1884
+ **最后更新**: 2025-10-02
1885
+ **整理来源**: 微信小程序官方文档