@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.
- package/README.md +469 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/defaults.d.ts +73 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +118 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/loader.d.ts +50 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +189 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/core/element-ref.d.ts +44 -0
- package/dist/core/element-ref.d.ts.map +1 -0
- package/dist/core/element-ref.js +213 -0
- package/dist/core/element-ref.js.map +1 -0
- package/dist/core/logger.d.ts +55 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +378 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/output.d.ts +21 -0
- package/dist/core/output.d.ts.map +1 -0
- package/dist/core/output.js +56 -0
- package/dist/core/output.js.map +1 -0
- package/dist/core/report-generator.d.ts +24 -0
- package/dist/core/report-generator.d.ts.map +1 -0
- package/dist/core/report-generator.js +212 -0
- package/dist/core/report-generator.js.map +1 -0
- package/dist/core/session.d.ts +83 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +306 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/timeout.d.ts +49 -0
- package/dist/core/timeout.d.ts.map +1 -0
- package/dist/core/timeout.js +67 -0
- package/dist/core/timeout.js.map +1 -0
- package/dist/core/tool-logger.d.ts +83 -0
- package/dist/core/tool-logger.d.ts.map +1 -0
- package/dist/core/tool-logger.js +453 -0
- package/dist/core/tool-logger.js.map +1 -0
- package/dist/core/validation.d.ts +39 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +93 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +85 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/assert.d.ts +108 -0
- package/dist/tools/assert.d.ts.map +1 -0
- package/dist/tools/assert.js +291 -0
- package/dist/tools/assert.js.map +1 -0
- package/dist/tools/automator.d.ts +45 -0
- package/dist/tools/automator.d.ts.map +1 -0
- package/dist/tools/automator.js +186 -0
- package/dist/tools/automator.js.map +1 -0
- package/dist/tools/element.d.ts +253 -0
- package/dist/tools/element.d.ts.map +1 -0
- package/dist/tools/element.js +615 -0
- package/dist/tools/element.js.map +1 -0
- package/dist/tools/index.d.ts +97 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +1565 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/miniprogram.d.ts +79 -0
- package/dist/tools/miniprogram.d.ts.map +1 -0
- package/dist/tools/miniprogram.js +245 -0
- package/dist/tools/miniprogram.js.map +1 -0
- package/dist/tools/network.d.ts +65 -0
- package/dist/tools/network.d.ts.map +1 -0
- package/dist/tools/network.js +205 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/page.d.ts +108 -0
- package/dist/tools/page.d.ts.map +1 -0
- package/dist/tools/page.js +307 -0
- package/dist/tools/page.js.map +1 -0
- package/dist/tools/record.d.ts +86 -0
- package/dist/tools/record.d.ts.map +1 -0
- package/dist/tools/record.js +316 -0
- package/dist/tools/record.js.map +1 -0
- package/dist/tools/snapshot.d.ts +82 -0
- package/dist/tools/snapshot.d.ts.map +1 -0
- package/dist/tools/snapshot.js +258 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/types.d.ts +240 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/docs/SIMPLE_USAGE.md +210 -0
- package/docs/api/README.md +244 -0
- package/docs/api/assert.md +1015 -0
- package/docs/api/automator.md +345 -0
- package/docs/api/element.md +1454 -0
- package/docs/api/miniprogram.md +558 -0
- package/docs/api/network.md +883 -0
- package/docs/api/page.md +909 -0
- package/docs/api/record.md +963 -0
- package/docs/api/snapshot.md +792 -0
- package/docs/architecture.E-Docs.md +1359 -0
- package/docs/architecture.F1.md +720 -0
- package/docs/architecture.F2.md +871 -0
- package/docs/architecture.F3.md +905 -0
- package/docs/architecture.md +90 -0
- package/docs/charter.A1.align.yaml +170 -0
- package/docs/charter.A2.align.yaml +199 -0
- package/docs/charter.A3.align.yaml +242 -0
- package/docs/charter.A4.align.yaml +227 -0
- package/docs/charter.B1.align.yaml +179 -0
- package/docs/charter.B2.align.yaml +200 -0
- package/docs/charter.B3.align.yaml +200 -0
- package/docs/charter.B4.align.yaml +188 -0
- package/docs/charter.C1.align.yaml +190 -0
- package/docs/charter.C2.align.yaml +202 -0
- package/docs/charter.C3.align.yaml +211 -0
- package/docs/charter.C4.align.yaml +263 -0
- package/docs/charter.C5.align.yaml +220 -0
- package/docs/charter.D1.align.yaml +190 -0
- package/docs/charter.D2.align.yaml +234 -0
- package/docs/charter.D3.align.yaml +206 -0
- package/docs/charter.E-Docs.align.yaml +294 -0
- package/docs/charter.F1.align.yaml +193 -0
- package/docs/charter.F2.align.yaml +248 -0
- package/docs/charter.F3.align.yaml +287 -0
- package/docs/charter.G.align.yaml +174 -0
- package/docs/charter.align.yaml +111 -0
- package/docs/examples/session-report-usage.md +449 -0
- package/docs/maintenance.md +682 -0
- package/docs/playwright-mcp/350/260/203/347/240/224.md +53 -0
- package/docs/setup-guide.md +775 -0
- package/docs/tasks.A1.atomize.md +296 -0
- package/docs/tasks.A2.atomize.md +408 -0
- package/docs/tasks.A3.atomize.md +564 -0
- package/docs/tasks.A4.atomize.md +496 -0
- package/docs/tasks.B1.atomize.md +352 -0
- package/docs/tasks.B2.atomize.md +561 -0
- package/docs/tasks.B3.atomize.md +508 -0
- package/docs/tasks.B4.atomize.md +504 -0
- package/docs/tasks.C1.atomize.md +540 -0
- package/docs/tasks.C2.atomize.md +665 -0
- package/docs/tasks.C3.atomize.md +745 -0
- package/docs/tasks.C4.atomize.md +908 -0
- package/docs/tasks.C5.atomize.md +755 -0
- package/docs/tasks.D1.atomize.md +547 -0
- package/docs/tasks.D2.atomize.md +619 -0
- package/docs/tasks.D3.atomize.md +790 -0
- package/docs/tasks.E-Docs.atomize.md +1204 -0
- package/docs/tasks.atomize.md +189 -0
- package/docs/troubleshooting.md +855 -0
- package/docs//345/256/214/346/225/264/345/256/236/347/216/260/346/226/271/346/241/210.md +155 -0
- package/docs//345/274/200/345/217/221/344/273/273/345/212/241/350/256/241/345/210/222.md +110 -0
- 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
- 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
- package/docs//346/216/245/345/217/243/346/226/271/346/241/210.md +565 -0
- package/docs//347/254/254/344/270/200/347/211/210/346/234/254/346/226/271/346/241/210.md +380 -0
- package/package.json +87 -0
package/docs/api/page.md
ADDED
|
@@ -0,0 +1,909 @@
|
|
|
1
|
+
# Page API
|
|
2
|
+
|
|
3
|
+
> Page 工具提供页面级别的元素查询、数据操作和方法调用功能,是自动化测试的核心模块。
|
|
4
|
+
|
|
5
|
+
## 工具列表
|
|
6
|
+
|
|
7
|
+
| 工具名称 | 描述 | 主要用途 |
|
|
8
|
+
|---------|------|----------|
|
|
9
|
+
| `page_query` | 查询单个元素 | 元素定位和引用缓存 |
|
|
10
|
+
| `page_query_all` | 查询所有匹配元素 | 批量元素操作 |
|
|
11
|
+
| `page_wait_for` | 等待元素或条件 | 异步操作同步化 |
|
|
12
|
+
| `page_get_data` | 获取页面 data | 状态验证 |
|
|
13
|
+
| `page_set_data` | 设置页面 data | 数据模拟 |
|
|
14
|
+
| `page_call_method` | 调用页面方法 | 页面逻辑触发 |
|
|
15
|
+
| `page_get_size` | 获取页面尺寸 | 布局验证 |
|
|
16
|
+
| `page_get_scroll_top` | 获取滚动位置 | 滚动状态检查 |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## page_query
|
|
21
|
+
|
|
22
|
+
查询单个符合条件的元素,支持元素引用缓存(refId)以提高性能。
|
|
23
|
+
|
|
24
|
+
### 参数
|
|
25
|
+
|
|
26
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
27
|
+
|--------|------|------|--------|------|
|
|
28
|
+
| `selector` | string | ✅ | - | CSS 选择器(如 `.btn`, `#input-username`) |
|
|
29
|
+
| `pagePath` | string | ⭐ | currentPage | 页面路径(默认当前页面) |
|
|
30
|
+
| `save` | boolean | ⭐ | false | 是否缓存元素引用(推荐设为 true) |
|
|
31
|
+
|
|
32
|
+
### 返回值
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
{
|
|
36
|
+
success: true,
|
|
37
|
+
message: "Element found",
|
|
38
|
+
refId: "elem_abc123", // 元素引用 ID(如果 save: true)
|
|
39
|
+
selector: ".btn", // 原始选择器
|
|
40
|
+
pagePath: "/pages/index/index"
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 错误处理
|
|
45
|
+
|
|
46
|
+
- **未连接**: `Error: Mini program not connected. Call miniprogram_launch or miniprogram_connect first.`
|
|
47
|
+
- **元素不存在**: `Error: Element not found: {selector}`
|
|
48
|
+
- **选择器无效**: `Error: Invalid selector: {selector}`
|
|
49
|
+
|
|
50
|
+
### 使用示例
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// 示例 1: 基础查询(不缓存)
|
|
54
|
+
const result = await page_query({
|
|
55
|
+
selector: ".submit-btn"
|
|
56
|
+
})
|
|
57
|
+
console.log(result.message) // "Element found"
|
|
58
|
+
|
|
59
|
+
// 示例 2: 查询并缓存引用(推荐)
|
|
60
|
+
const result = await page_query({
|
|
61
|
+
selector: ".product-item",
|
|
62
|
+
save: true
|
|
63
|
+
})
|
|
64
|
+
// 后续可以使用 refId 操作元素,避免重复查询
|
|
65
|
+
await element_tap({ refId: result.refId })
|
|
66
|
+
await element_get_text({ refId: result.refId })
|
|
67
|
+
|
|
68
|
+
// 示例 3: 查询指定页面的元素
|
|
69
|
+
const result = await page_query({
|
|
70
|
+
selector: "#username-input",
|
|
71
|
+
pagePath: "/pages/login/login",
|
|
72
|
+
save: true
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// 示例 4: 组合选择器
|
|
76
|
+
const result = await page_query({
|
|
77
|
+
selector: ".product-list .item:first-child .title",
|
|
78
|
+
save: true
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// 示例 5: 查询后立即操作
|
|
82
|
+
const btn = await page_query({
|
|
83
|
+
selector: ".delete-btn",
|
|
84
|
+
save: true
|
|
85
|
+
})
|
|
86
|
+
await element_tap({ refId: btn.refId })
|
|
87
|
+
await assert_exists({ selector: ".success-toast" })
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 注意事项
|
|
91
|
+
|
|
92
|
+
- 💡 **推荐做法**: 始终使用 `save: true` 缓存元素引用,避免重复查询
|
|
93
|
+
- ⚠️ **选择器规则**: 遵循小程序 CSS 选择器规范(不支持伪元素)
|
|
94
|
+
- 💡 **性能优化**: refId 有效期为会话周期(30 分钟),自动清理
|
|
95
|
+
- ⚠️ **多元素匹配**: 如果选择器匹配多个元素,返回第一个匹配项
|
|
96
|
+
|
|
97
|
+
### 相关工具
|
|
98
|
+
|
|
99
|
+
- [`page_query_all`](#page_query_all) - 查询所有匹配元素
|
|
100
|
+
- [`element_tap`](./element.md#element_tap) - 点击查询到的元素
|
|
101
|
+
- [`element_get_text`](./element.md#element_get_text) - 获取元素文本
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## XPath 支持说明
|
|
106
|
+
|
|
107
|
+
当前 MCP API 以 CSS/WXML 选择器为主(`page_query` / `page_query_all`)。底层已具备 XPath 能力,但尚未对外提供独立的 `page_xpath` 系列工具,以避免变更既有工具数量(65 个)影响文档与校验脚本。
|
|
108
|
+
|
|
109
|
+
注意事项:
|
|
110
|
+
- 推荐优先使用 CSS/WXML 选择器,兼顾可读性与兼容性。
|
|
111
|
+
- 如确需 XPath 精准定位,可在 Issue 中反馈需求;后续将评估以不破坏现有计数与 CI 校验的方式补充对应工具。
|
|
112
|
+
- 参考:`miniprogram-automator` 0.11.0+ 提供 `page.xpath/getElementByXpath/getElementsByXpath` 能力。
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## page_query_all
|
|
117
|
+
|
|
118
|
+
查询所有符合条件的元素,返回元素数组。
|
|
119
|
+
|
|
120
|
+
### 参数
|
|
121
|
+
|
|
122
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
123
|
+
|--------|------|------|--------|------|
|
|
124
|
+
| `selector` | string | ✅ | - | CSS 选择器 |
|
|
125
|
+
| `pagePath` | string | ⭐ | currentPage | 页面路径(默认当前页面) |
|
|
126
|
+
| `save` | boolean | ⭐ | false | 是否缓存所有元素引用 |
|
|
127
|
+
|
|
128
|
+
### 返回值
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
{
|
|
132
|
+
success: true,
|
|
133
|
+
message: "Found 5 elements",
|
|
134
|
+
elements: [
|
|
135
|
+
{ refId: "elem_001", selector: ".item", index: 0 },
|
|
136
|
+
{ refId: "elem_002", selector: ".item", index: 1 },
|
|
137
|
+
{ refId: "elem_003", selector: ".item", index: 2 },
|
|
138
|
+
{ refId: "elem_004", selector: ".item", index: 3 },
|
|
139
|
+
{ refId: "elem_005", selector: ".item", index: 4 }
|
|
140
|
+
],
|
|
141
|
+
count: 5,
|
|
142
|
+
pagePath: "/pages/list/list"
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 错误处理
|
|
147
|
+
|
|
148
|
+
- **未连接**: `Error: Mini program not connected`
|
|
149
|
+
- **无匹配元素**: 返回空数组(不报错)
|
|
150
|
+
|
|
151
|
+
### 使用示例
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
// 示例 1: 查询所有商品项
|
|
155
|
+
const result = await page_query_all({
|
|
156
|
+
selector: ".product-item",
|
|
157
|
+
save: true
|
|
158
|
+
})
|
|
159
|
+
console.log(`找到 ${result.count} 个商品`) // "找到 10 个商品"
|
|
160
|
+
|
|
161
|
+
// 示例 2: 批量操作元素
|
|
162
|
+
const items = await page_query_all({
|
|
163
|
+
selector: ".checkbox",
|
|
164
|
+
save: true
|
|
165
|
+
})
|
|
166
|
+
// 全选所有复选框
|
|
167
|
+
for (const item of items.elements) {
|
|
168
|
+
await element_tap({ refId: item.refId })
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 示例 3: 获取列表文本
|
|
172
|
+
const items = await page_query_all({
|
|
173
|
+
selector: ".todo-item .title",
|
|
174
|
+
save: true
|
|
175
|
+
})
|
|
176
|
+
const titles = []
|
|
177
|
+
for (const item of items.elements) {
|
|
178
|
+
const text = await element_get_text({ refId: item.refId })
|
|
179
|
+
titles.push(text.text)
|
|
180
|
+
}
|
|
181
|
+
console.log("待办事项:", titles)
|
|
182
|
+
|
|
183
|
+
// 示例 4: 验证列表数量
|
|
184
|
+
const result = await page_query_all({
|
|
185
|
+
selector: ".comment-item"
|
|
186
|
+
})
|
|
187
|
+
if (result.count < 5) {
|
|
188
|
+
throw new Error("评论数量不足")
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// 示例 5: 操作特定索引的元素
|
|
192
|
+
const items = await page_query_all({
|
|
193
|
+
selector: ".product-item",
|
|
194
|
+
save: true
|
|
195
|
+
})
|
|
196
|
+
// 点击第 3 个商品
|
|
197
|
+
await element_tap({ refId: items.elements[2].refId })
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 注意事项
|
|
201
|
+
|
|
202
|
+
- 💡 **空结果**: 如果没有匹配元素,返回空数组(`count: 0`),不报错
|
|
203
|
+
- 💡 **索引访问**: `elements` 数组包含 `index` 字段,方便定位
|
|
204
|
+
- ⚠️ **性能考虑**: 大量元素(>100)建议不使用 `save: true`,避免内存占用
|
|
205
|
+
|
|
206
|
+
### 相关工具
|
|
207
|
+
|
|
208
|
+
- [`page_query`](#page_query) - 查询单个元素
|
|
209
|
+
- [`assert_exists`](./assert.md#assert_exists) - 验证元素存在
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## page_wait_for
|
|
214
|
+
|
|
215
|
+
等待元素出现、消失或指定时间,用于异步操作同步化。
|
|
216
|
+
|
|
217
|
+
### 参数
|
|
218
|
+
|
|
219
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
220
|
+
|--------|------|------|--------|------|
|
|
221
|
+
| `selector` | string | ⭐ | - | 等待出现的元素选择器 |
|
|
222
|
+
| `timeout` | number | ⭐ | - | 等待时间(毫秒) |
|
|
223
|
+
| `pagePath` | string | ⭐ | currentPage | 页面路径 |
|
|
224
|
+
|
|
225
|
+
### 返回值
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// 等待元素出现
|
|
229
|
+
{
|
|
230
|
+
success: true,
|
|
231
|
+
message: "Element appeared",
|
|
232
|
+
selector: ".success-toast",
|
|
233
|
+
waitedTime: 1234 // 实际等待时间(毫秒)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// 等待指定时间
|
|
237
|
+
{
|
|
238
|
+
success: true,
|
|
239
|
+
message: "Waited for 2000ms",
|
|
240
|
+
timeout: 2000
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### 错误处理
|
|
245
|
+
|
|
246
|
+
- **超时**: `Error: Timeout waiting for element: {selector}`
|
|
247
|
+
- **参数错误**: `Error: Must provide either selector or timeout`
|
|
248
|
+
|
|
249
|
+
### 使用示例
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
// 示例 1: 等待加载完成
|
|
253
|
+
await element_tap({ selector: ".load-more-btn" })
|
|
254
|
+
await page_wait_for({
|
|
255
|
+
selector: ".loading-indicator",
|
|
256
|
+
timeout: 5000
|
|
257
|
+
})
|
|
258
|
+
console.log("加载完成")
|
|
259
|
+
|
|
260
|
+
// 示例 2: 等待提示消息出现
|
|
261
|
+
await element_tap({ selector: ".submit-btn" })
|
|
262
|
+
await page_wait_for({
|
|
263
|
+
selector: ".success-toast",
|
|
264
|
+
timeout: 3000
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
// 示例 3: 等待固定时间(动画播放)
|
|
268
|
+
await element_tap({ selector: ".modal-close" })
|
|
269
|
+
await page_wait_for({ timeout: 500 }) // 等待关闭动画
|
|
270
|
+
|
|
271
|
+
// 示例 4: 等待页面跳转后的元素
|
|
272
|
+
await miniprogram_navigate({
|
|
273
|
+
method: "navigateTo",
|
|
274
|
+
url: "/pages/detail/detail"
|
|
275
|
+
})
|
|
276
|
+
await page_wait_for({
|
|
277
|
+
selector: ".detail-content",
|
|
278
|
+
timeout: 2000
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
// 示例 5: 错误处理
|
|
282
|
+
try {
|
|
283
|
+
await page_wait_for({
|
|
284
|
+
selector: ".non-existent",
|
|
285
|
+
timeout: 1000
|
|
286
|
+
})
|
|
287
|
+
} catch (error) {
|
|
288
|
+
console.log("元素未出现,继续其他操作")
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### 注意事项
|
|
293
|
+
|
|
294
|
+
- ⚠️ **必需参数**: 必须提供 `selector` 或 `timeout` 之一
|
|
295
|
+
- 💡 **超时设置**: 建议根据实际场景设置合理超时(网络请求 5s+,动画 1s-)
|
|
296
|
+
- 💡 **性能优化**: 使用 `selector` 等待比定时等待更精确
|
|
297
|
+
- ⚠️ **等待消失**: 当前版本不支持等待元素消失,请使用 `assert_not_exists`
|
|
298
|
+
|
|
299
|
+
### 相关工具
|
|
300
|
+
|
|
301
|
+
- [`assert_exists`](./assert.md#assert_exists) - 验证元素存在
|
|
302
|
+
- [`assert_not_exists`](./assert.md#assert_not_exists) - 验证元素不存在
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## page_get_data
|
|
307
|
+
|
|
308
|
+
获取页面 `data` 对象或指定路径的数据。
|
|
309
|
+
|
|
310
|
+
### 参数
|
|
311
|
+
|
|
312
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
313
|
+
|--------|------|------|--------|------|
|
|
314
|
+
| `path` | string | ⭐ | - | 数据路径(如 `userInfo.name`),为空返回整个 data |
|
|
315
|
+
| `pagePath` | string | ⭐ | currentPage | 页面路径 |
|
|
316
|
+
|
|
317
|
+
### 返回值
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
// 获取整个 data
|
|
321
|
+
{
|
|
322
|
+
success: true,
|
|
323
|
+
message: "Retrieved page data",
|
|
324
|
+
data: {
|
|
325
|
+
userInfo: { name: "Alice", age: 25 },
|
|
326
|
+
productList: [...],
|
|
327
|
+
isLoading: false
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// 获取指定路径
|
|
332
|
+
{
|
|
333
|
+
success: true,
|
|
334
|
+
message: "Retrieved page data at path: userInfo.name",
|
|
335
|
+
data: "Alice",
|
|
336
|
+
path: "userInfo.name"
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### 错误处理
|
|
341
|
+
|
|
342
|
+
- **未连接**: `Error: Mini program not connected`
|
|
343
|
+
- **路径不存在**: 返回 `undefined`(不报错)
|
|
344
|
+
|
|
345
|
+
### 使用示例
|
|
346
|
+
|
|
347
|
+
```javascript
|
|
348
|
+
// 示例 1: 获取整个 data
|
|
349
|
+
const result = await page_get_data()
|
|
350
|
+
console.log("页面数据:", result.data)
|
|
351
|
+
|
|
352
|
+
// 示例 2: 获取用户信息
|
|
353
|
+
const result = await page_get_data({
|
|
354
|
+
path: "userInfo"
|
|
355
|
+
})
|
|
356
|
+
console.log("用户名:", result.data.name)
|
|
357
|
+
|
|
358
|
+
// 示例 3: 获取嵌套属性
|
|
359
|
+
const result = await page_get_data({
|
|
360
|
+
path: "userInfo.settings.theme"
|
|
361
|
+
})
|
|
362
|
+
console.log("主题:", result.data) // "dark"
|
|
363
|
+
|
|
364
|
+
// 示例 4: 获取数组长度
|
|
365
|
+
const result = await page_get_data({
|
|
366
|
+
path: "productList"
|
|
367
|
+
})
|
|
368
|
+
console.log(`共 ${result.data.length} 个商品`)
|
|
369
|
+
|
|
370
|
+
// 示例 5: 验证数据状态
|
|
371
|
+
const result = await page_get_data({
|
|
372
|
+
path: "isLoading"
|
|
373
|
+
})
|
|
374
|
+
if (result.data === true) {
|
|
375
|
+
await page_wait_for({ timeout: 2000 })
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### 注意事项
|
|
380
|
+
|
|
381
|
+
- 💡 **路径语法**: 使用点号分隔(`a.b.c`),支持嵌套对象和数组
|
|
382
|
+
- ⚠️ **不存在路径**: 返回 `undefined`,不报错
|
|
383
|
+
- 💡 **调试技巧**: 先获取整个 data 查看结构,再获取具体路径
|
|
384
|
+
- 💡 **性能**: 获取整个 data 开销较大,建议指定路径
|
|
385
|
+
|
|
386
|
+
### 相关工具
|
|
387
|
+
|
|
388
|
+
- [`page_set_data`](#page_set_data) - 设置页面数据
|
|
389
|
+
- [`assert_data`](./assert.md#assert_data) - 验证页面数据
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## page_set_data
|
|
394
|
+
|
|
395
|
+
设置页面 `data` 对象的值,用于数据模拟和状态注入。
|
|
396
|
+
|
|
397
|
+
### 参数
|
|
398
|
+
|
|
399
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
400
|
+
|--------|------|------|--------|------|
|
|
401
|
+
| `data` | object | ✅ | - | 要设置的数据对象(支持路径语法) |
|
|
402
|
+
| `pagePath` | string | ⭐ | currentPage | 页面路径 |
|
|
403
|
+
|
|
404
|
+
### 返回值
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
{
|
|
408
|
+
success: true,
|
|
409
|
+
message: "Page data set successfully",
|
|
410
|
+
data: {
|
|
411
|
+
"userInfo.name": "Bob",
|
|
412
|
+
"isVip": true
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### 错误处理
|
|
418
|
+
|
|
419
|
+
- **未连接**: `Error: Mini program not connected`
|
|
420
|
+
- **参数错误**: `Error: data is required and must be an object`
|
|
421
|
+
|
|
422
|
+
### 使用示例
|
|
423
|
+
|
|
424
|
+
```javascript
|
|
425
|
+
// 示例 1: 设置单个属性
|
|
426
|
+
await page_set_data({
|
|
427
|
+
data: { isLoading: false }
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
// 示例 2: 设置嵌套属性(路径语法)
|
|
431
|
+
await page_set_data({
|
|
432
|
+
data: {
|
|
433
|
+
"userInfo.name": "Bob",
|
|
434
|
+
"userInfo.age": 30
|
|
435
|
+
}
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
// 示例 3: 模拟登录状态
|
|
439
|
+
await page_set_data({
|
|
440
|
+
data: {
|
|
441
|
+
isLoggedIn: true,
|
|
442
|
+
userInfo: {
|
|
443
|
+
id: 12345,
|
|
444
|
+
name: "测试用户",
|
|
445
|
+
avatar: "https://example.com/avatar.png"
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
// 示例 4: 模拟数据加载完成
|
|
451
|
+
await page_set_data({
|
|
452
|
+
data: {
|
|
453
|
+
isLoading: false,
|
|
454
|
+
productList: [
|
|
455
|
+
{ id: 1, name: "商品 1", price: 99 },
|
|
456
|
+
{ id: 2, name: "商品 2", price: 199 }
|
|
457
|
+
]
|
|
458
|
+
}
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
// 示例 5: 触发视图更新后验证
|
|
462
|
+
await page_set_data({
|
|
463
|
+
data: { count: 10 }
|
|
464
|
+
})
|
|
465
|
+
const result = await element_get_text({
|
|
466
|
+
selector: ".count-display"
|
|
467
|
+
})
|
|
468
|
+
console.log(result.text) // "10"
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### 注意事项
|
|
472
|
+
|
|
473
|
+
- 💡 **路径语法**: 使用 `"a.b.c"` 修改嵌套属性,无需修改整个对象
|
|
474
|
+
- ⚠️ **视图更新**: setData 会触发页面视图更新(与小程序原生行为一致)
|
|
475
|
+
- 💡 **数据覆盖**: 只覆盖指定路径的数据,不影响其他属性
|
|
476
|
+
- ⚠️ **类型检查**: 不会校验数据类型,请确保数据格式正确
|
|
477
|
+
|
|
478
|
+
### 相关工具
|
|
479
|
+
|
|
480
|
+
- [`page_get_data`](#page_get_data) - 获取页面数据
|
|
481
|
+
- [`assert_data`](./assert.md#assert_data) - 验证数据设置结果
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## page_call_method
|
|
486
|
+
|
|
487
|
+
调用页面中定义的方法(Page 对象的方法)。
|
|
488
|
+
|
|
489
|
+
### 参数
|
|
490
|
+
|
|
491
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
492
|
+
|--------|------|------|--------|------|
|
|
493
|
+
| `method` | string | ✅ | - | 方法名 |
|
|
494
|
+
| `args` | any[] | ⭐ | [] | 方法参数数组 |
|
|
495
|
+
| `pagePath` | string | ⭐ | currentPage | 页面路径 |
|
|
496
|
+
|
|
497
|
+
### 返回值
|
|
498
|
+
|
|
499
|
+
```typescript
|
|
500
|
+
{
|
|
501
|
+
success: true,
|
|
502
|
+
message: "Method called: onRefresh",
|
|
503
|
+
method: "onRefresh",
|
|
504
|
+
result: { success: true, data: [...] } // 方法返回值
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### 错误处理
|
|
509
|
+
|
|
510
|
+
- **未连接**: `Error: Mini program not connected`
|
|
511
|
+
- **方法不存在**: `Error: Method not found: {method}`
|
|
512
|
+
- **方法错误**: 返回方法抛出的错误
|
|
513
|
+
|
|
514
|
+
### 使用示例
|
|
515
|
+
|
|
516
|
+
```javascript
|
|
517
|
+
// 示例 1: 调用无参数方法
|
|
518
|
+
await page_call_method({
|
|
519
|
+
method: "onRefresh"
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
// 示例 2: 调用带参数方法
|
|
523
|
+
await page_call_method({
|
|
524
|
+
method: "addToCart",
|
|
525
|
+
args: [{ productId: 123, quantity: 2 }]
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
// 示例 3: 获取方法返回值
|
|
529
|
+
const result = await page_call_method({
|
|
530
|
+
method: "calculateTotal"
|
|
531
|
+
})
|
|
532
|
+
console.log("总价:", result.result)
|
|
533
|
+
|
|
534
|
+
// 示例 4: 调用多参数方法
|
|
535
|
+
await page_call_method({
|
|
536
|
+
method: "updateProduct",
|
|
537
|
+
args: [123, "新商品名", 299]
|
|
538
|
+
})
|
|
539
|
+
|
|
540
|
+
// 示例 5: 调用页面生命周期方法
|
|
541
|
+
await page_call_method({
|
|
542
|
+
method: "onPullDownRefresh"
|
|
543
|
+
})
|
|
544
|
+
// 等待刷新完成
|
|
545
|
+
await page_wait_for({ timeout: 2000 })
|
|
546
|
+
await page_call_method({
|
|
547
|
+
method: "onReachBottom"
|
|
548
|
+
})
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### 注意事项
|
|
552
|
+
|
|
553
|
+
- ⚠️ **方法定义**: 只能调用 Page() 中定义的方法,不能调用生命周期钩子外的函数
|
|
554
|
+
- 💡 **参数传递**: 使用数组传递多个参数(`args: [arg1, arg2, arg3]`)
|
|
555
|
+
- 💡 **异步方法**: 如果方法返回 Promise,会等待 Promise resolve
|
|
556
|
+
- ⚠️ **错误处理**: 方法内部错误会被捕获并抛出
|
|
557
|
+
|
|
558
|
+
### 相关工具
|
|
559
|
+
|
|
560
|
+
- [`miniprogram_evaluate`](./miniprogram.md#miniprogram_evaluate) - 执行任意 JavaScript 代码
|
|
561
|
+
- [`page_get_data`](#page_get_data) - 获取方法执行后的数据变化
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## page_get_size
|
|
566
|
+
|
|
567
|
+
获取页面的宽度和高度(视口尺寸)。
|
|
568
|
+
|
|
569
|
+
### 参数
|
|
570
|
+
|
|
571
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
572
|
+
|--------|------|------|--------|------|
|
|
573
|
+
| `pagePath` | string | ⭐ | currentPage | 页面路径 |
|
|
574
|
+
|
|
575
|
+
### 返回值
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
{
|
|
579
|
+
success: true,
|
|
580
|
+
message: "Retrieved page size",
|
|
581
|
+
size: {
|
|
582
|
+
width: 375, // 页面宽度(px)
|
|
583
|
+
height: 667 // 页面高度(px)
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### 错误处理
|
|
589
|
+
|
|
590
|
+
- **未连接**: `Error: Mini program not connected`
|
|
591
|
+
|
|
592
|
+
### 使用示例
|
|
593
|
+
|
|
594
|
+
```javascript
|
|
595
|
+
// 示例 1: 获取当前页面尺寸
|
|
596
|
+
const result = await page_get_size()
|
|
597
|
+
console.log(`页面尺寸: ${result.size.width}x${result.size.height}`)
|
|
598
|
+
|
|
599
|
+
// 示例 2: 验证布局适配
|
|
600
|
+
const { size } = await page_get_size()
|
|
601
|
+
if (size.width < 375) {
|
|
602
|
+
console.warn("页面宽度小于 iPhone SE,可能存在布局问题")
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// 示例 3: 计算滚动范围
|
|
606
|
+
const { size } = await page_get_size()
|
|
607
|
+
const scrollTop = await page_get_scroll_top()
|
|
608
|
+
const maxScroll = size.height * 2 // 假设页面高度为 2 倍视口
|
|
609
|
+
if (scrollTop.scrollTop < maxScroll) {
|
|
610
|
+
await element_scroll({ selector: "page", distance: 100 })
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// 示例 4: 获取指定页面尺寸
|
|
614
|
+
const result = await page_get_size({
|
|
615
|
+
pagePath: "/pages/detail/detail"
|
|
616
|
+
})
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### 注意事项
|
|
620
|
+
|
|
621
|
+
- 💡 **单位**: 返回值单位为物理像素(px),非 rpx
|
|
622
|
+
- 💡 **视口尺寸**: 返回的是视口尺寸,不是页面内容实际高度
|
|
623
|
+
- ⚠️ **动态变化**: 屏幕旋转或窗口大小改变时尺寸会变化
|
|
624
|
+
|
|
625
|
+
### 相关工具
|
|
626
|
+
|
|
627
|
+
- [`miniprogram_get_system_info`](./miniprogram.md#miniprogram_get_system_info) - 获取设备信息(含屏幕尺寸)
|
|
628
|
+
- [`element_get_size`](./element.md#element_get_size) - 获取元素尺寸
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
## page_get_scroll_top
|
|
633
|
+
|
|
634
|
+
获取页面当前的滚动位置(垂直方向)。
|
|
635
|
+
|
|
636
|
+
### 参数
|
|
637
|
+
|
|
638
|
+
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
|
639
|
+
|--------|------|------|--------|------|
|
|
640
|
+
| `pagePath` | string | ⭐ | currentPage | 页面路径 |
|
|
641
|
+
|
|
642
|
+
### 返回值
|
|
643
|
+
|
|
644
|
+
```typescript
|
|
645
|
+
{
|
|
646
|
+
success: true,
|
|
647
|
+
message: "Retrieved scroll position",
|
|
648
|
+
scrollTop: 320 // 滚动距离(px)
|
|
649
|
+
}
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### 错误处理
|
|
653
|
+
|
|
654
|
+
- **未连接**: `Error: Mini program not connected`
|
|
655
|
+
|
|
656
|
+
### 使用示例
|
|
657
|
+
|
|
658
|
+
```javascript
|
|
659
|
+
// 示例 1: 获取当前滚动位置
|
|
660
|
+
const result = await page_get_scroll_top()
|
|
661
|
+
console.log(`当前滚动: ${result.scrollTop}px`)
|
|
662
|
+
|
|
663
|
+
// 示例 2: 验证滚动到底部
|
|
664
|
+
const { scrollTop } = await page_get_scroll_top()
|
|
665
|
+
const { size } = await page_get_size()
|
|
666
|
+
const isBottom = scrollTop + size.height >= 1200 // 假设页面总高度 1200px
|
|
667
|
+
if (isBottom) {
|
|
668
|
+
console.log("已滚动到底部")
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// 示例 3: 验证滚动操作
|
|
672
|
+
const before = await page_get_scroll_top()
|
|
673
|
+
await element_scroll({
|
|
674
|
+
selector: "page",
|
|
675
|
+
distance: 200
|
|
676
|
+
})
|
|
677
|
+
const after = await page_get_scroll_top()
|
|
678
|
+
console.log(`滚动了 ${after.scrollTop - before.scrollTop}px`)
|
|
679
|
+
|
|
680
|
+
// 示例 4: 等待滚动完成
|
|
681
|
+
await element_scroll_to({
|
|
682
|
+
selector: "page",
|
|
683
|
+
top: 500
|
|
684
|
+
})
|
|
685
|
+
await page_wait_for({ timeout: 300 })
|
|
686
|
+
const { scrollTop } = await page_get_scroll_top()
|
|
687
|
+
if (Math.abs(scrollTop - 500) < 5) {
|
|
688
|
+
console.log("滚动到位")
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### 注意事项
|
|
693
|
+
|
|
694
|
+
- 💡 **单位**: 返回值单位为物理像素(px)
|
|
695
|
+
- 💡 **初始值**: 页面未滚动时 `scrollTop` 为 0
|
|
696
|
+
- ⚠️ **精度**: 滚动动画可能导致实际值与预期有 1-2px 偏差
|
|
697
|
+
- 💡 **仅垂直**: 当前仅支持垂直滚动,不支持水平滚动
|
|
698
|
+
|
|
699
|
+
### 相关工具
|
|
700
|
+
|
|
701
|
+
- [`element_scroll`](./element.md#element_scroll) - 滚动元素
|
|
702
|
+
- [`element_scroll_to`](./element.md#element_scroll_to) - 滚动到指定位置
|
|
703
|
+
- [`page_get_size`](#page_get_size) - 获取页面尺寸
|
|
704
|
+
|
|
705
|
+
---
|
|
706
|
+
|
|
707
|
+
## 完整示例:页面数据操作和验证
|
|
708
|
+
|
|
709
|
+
```javascript
|
|
710
|
+
// 场景:测试商品列表页的数据加载和交互
|
|
711
|
+
async function testProductList() {
|
|
712
|
+
try {
|
|
713
|
+
// 1. 启动小程序并导航
|
|
714
|
+
await miniprogram_launch({
|
|
715
|
+
projectPath: "/path/to/project"
|
|
716
|
+
})
|
|
717
|
+
await miniprogram_navigate({
|
|
718
|
+
method: "navigateTo",
|
|
719
|
+
url: "/pages/product/list"
|
|
720
|
+
})
|
|
721
|
+
|
|
722
|
+
// 2. 等待数据加载完成
|
|
723
|
+
await page_wait_for({
|
|
724
|
+
selector: ".product-item",
|
|
725
|
+
timeout: 5000
|
|
726
|
+
})
|
|
727
|
+
|
|
728
|
+
// 3. 验证初始数据状态
|
|
729
|
+
const data = await page_get_data({
|
|
730
|
+
path: "productList"
|
|
731
|
+
})
|
|
732
|
+
console.log(`✅ 加载了 ${data.data.length} 个商品`)
|
|
733
|
+
|
|
734
|
+
// 4. 模拟数据注入(测试空状态)
|
|
735
|
+
await page_set_data({
|
|
736
|
+
data: {
|
|
737
|
+
productList: [],
|
|
738
|
+
isEmpty: true
|
|
739
|
+
}
|
|
740
|
+
})
|
|
741
|
+
await assert_exists({ selector: ".empty-state" })
|
|
742
|
+
console.log("✅ 空状态显示正确")
|
|
743
|
+
|
|
744
|
+
// 5. 恢复数据并查询所有商品
|
|
745
|
+
await page_call_method({
|
|
746
|
+
method: "loadProducts"
|
|
747
|
+
})
|
|
748
|
+
await page_wait_for({ timeout: 1000 })
|
|
749
|
+
|
|
750
|
+
const items = await page_query_all({
|
|
751
|
+
selector: ".product-item",
|
|
752
|
+
save: true
|
|
753
|
+
})
|
|
754
|
+
console.log(`✅ 找到 ${items.count} 个商品项`)
|
|
755
|
+
|
|
756
|
+
// 6. 点击第一个商品
|
|
757
|
+
await element_tap({
|
|
758
|
+
refId: items.elements[0].refId
|
|
759
|
+
})
|
|
760
|
+
await page_wait_for({
|
|
761
|
+
selector: ".product-detail",
|
|
762
|
+
timeout: 2000
|
|
763
|
+
})
|
|
764
|
+
console.log("✅ 成功进入商品详情页")
|
|
765
|
+
|
|
766
|
+
// 7. 验证页面滚动
|
|
767
|
+
const { size } = await page_get_size()
|
|
768
|
+
console.log(`✅ 详情页尺寸: ${size.width}x${size.height}`)
|
|
769
|
+
|
|
770
|
+
await element_scroll({
|
|
771
|
+
selector: "page",
|
|
772
|
+
distance: 300
|
|
773
|
+
})
|
|
774
|
+
const { scrollTop } = await page_get_scroll_top()
|
|
775
|
+
console.log(`✅ 滚动位置: ${scrollTop}px`)
|
|
776
|
+
|
|
777
|
+
// 8. 清理
|
|
778
|
+
await miniprogram_close()
|
|
779
|
+
console.log("✅ 测试完成")
|
|
780
|
+
|
|
781
|
+
} catch (error) {
|
|
782
|
+
console.error("❌ 测试失败:", error.message)
|
|
783
|
+
await miniprogram_screenshot({
|
|
784
|
+
filename: "test-error.png"
|
|
785
|
+
})
|
|
786
|
+
throw error
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
testProductList()
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
---
|
|
794
|
+
|
|
795
|
+
## 故障排除
|
|
796
|
+
|
|
797
|
+
### 问题 1: 元素查询失败
|
|
798
|
+
|
|
799
|
+
**错误**: `Element not found: .my-selector`
|
|
800
|
+
|
|
801
|
+
**解决方案**:
|
|
802
|
+
1. 检查选择器语法是否正确(使用浏览器 DevTools 验证)
|
|
803
|
+
2. 确认元素是否已渲染(使用 `page_wait_for` 等待)
|
|
804
|
+
3. 检查页面路径是否正确(`pagePath` 参数)
|
|
805
|
+
4. 使用 `page_get_data` 检查数据是否已加载
|
|
806
|
+
|
|
807
|
+
```javascript
|
|
808
|
+
// ❌ 错误:元素未渲染完成
|
|
809
|
+
await page_query({ selector: ".async-content" })
|
|
810
|
+
|
|
811
|
+
// ✅ 正确:等待元素出现
|
|
812
|
+
await page_wait_for({
|
|
813
|
+
selector: ".async-content",
|
|
814
|
+
timeout: 3000
|
|
815
|
+
})
|
|
816
|
+
const result = await page_query({
|
|
817
|
+
selector: ".async-content",
|
|
818
|
+
save: true
|
|
819
|
+
})
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
### 问题 2: page_set_data 不生效
|
|
823
|
+
|
|
824
|
+
**错误**: 设置数据后页面未更新
|
|
825
|
+
|
|
826
|
+
**解决方案**:
|
|
827
|
+
1. 检查路径语法是否正确(嵌套属性用 `"a.b.c"`)
|
|
828
|
+
2. 确认页面是否有对应的数据字段
|
|
829
|
+
3. 使用 `page_get_data` 验证设置是否成功
|
|
830
|
+
4. 检查页面是否有 setData 监听器覆盖了值
|
|
831
|
+
|
|
832
|
+
```javascript
|
|
833
|
+
// ❌ 错误:路径语法错误
|
|
834
|
+
await page_set_data({
|
|
835
|
+
data: { userInfo: { name: "Bob" } } // 会覆盖整个 userInfo
|
|
836
|
+
})
|
|
837
|
+
|
|
838
|
+
// ✅ 正确:使用路径语法
|
|
839
|
+
await page_set_data({
|
|
840
|
+
data: { "userInfo.name": "Bob" } // 只修改 name 字段
|
|
841
|
+
})
|
|
842
|
+
|
|
843
|
+
// 验证设置结果
|
|
844
|
+
const result = await page_get_data({ path: "userInfo.name" })
|
|
845
|
+
console.log(result.data) // "Bob"
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
### 问题 3: page_call_method 方法不存在
|
|
849
|
+
|
|
850
|
+
**错误**: `Method not found: myMethod`
|
|
851
|
+
|
|
852
|
+
**解决方案**:
|
|
853
|
+
1. 确认方法是在 `Page()` 中定义的,不是外部函数
|
|
854
|
+
2. 检查方法名是否拼写正确(区分大小写)
|
|
855
|
+
3. 使用 `miniprogram_evaluate` 查看页面对象结构
|
|
856
|
+
|
|
857
|
+
```javascript
|
|
858
|
+
// 检查页面可用方法
|
|
859
|
+
const result = await miniprogram_evaluate({
|
|
860
|
+
expression: "Object.keys(getCurrentPages()[0])"
|
|
861
|
+
})
|
|
862
|
+
console.log("可用方法:", result.result)
|
|
863
|
+
|
|
864
|
+
// 调用确认存在的方法
|
|
865
|
+
await page_call_method({
|
|
866
|
+
method: "onPullDownRefresh"
|
|
867
|
+
})
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
---
|
|
871
|
+
|
|
872
|
+
## 技术细节
|
|
873
|
+
|
|
874
|
+
### 元素引用缓存机制
|
|
875
|
+
|
|
876
|
+
- **refId 生成**: `elem_${timestamp}_${random}`
|
|
877
|
+
- **缓存有效期**: 会话周期(30 分钟不活动自动清理)
|
|
878
|
+
- **缓存容量**: 无限制(建议单会话 < 1000 个)
|
|
879
|
+
- **清理时机**:
|
|
880
|
+
- 会话超时自动清理
|
|
881
|
+
- `miniprogram_close()` 清理
|
|
882
|
+
- `miniprogram_disconnect()` 保留缓存
|
|
883
|
+
|
|
884
|
+
### 选择器支持
|
|
885
|
+
|
|
886
|
+
- **支持**: 类选择器(`.class`)、ID 选择器(`#id`)、标签选择器(`view`)、属性选择器(`[attr="value"]`)、组合选择器(`.a .b`、`.a > .b`)
|
|
887
|
+
- **不支持**: 伪类(`:hover`)、伪元素(`::before`)、CSS4 选择器
|
|
888
|
+
|
|
889
|
+
### 数据路径语法
|
|
890
|
+
|
|
891
|
+
```javascript
|
|
892
|
+
// 支持的路径格式
|
|
893
|
+
"a" // 单层属性
|
|
894
|
+
"a.b" // 嵌套属性
|
|
895
|
+
"a.b.c" // 多层嵌套
|
|
896
|
+
"a[0]" // 数组索引
|
|
897
|
+
"a[0].b" // 数组元素的属性
|
|
898
|
+
"a.b[1].c" // 复杂嵌套
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
---
|
|
902
|
+
|
|
903
|
+
**相关文档**:
|
|
904
|
+
- [MiniProgram API](./miniprogram.md) - 小程序级别操作
|
|
905
|
+
- [Element API](./element.md) - 元素交互操作
|
|
906
|
+
- [Assert API](./assert.md) - 断言验证
|
|
907
|
+
- [使用示例](../../examples/02-form-interaction.md) - 表单交互示例
|
|
908
|
+
|
|
909
|
+
**最后更新**: 2025-10-02
|