testdriverai 7.4.0 → 7.4.1
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/.github/skills/testdriver:find/SKILL.md +13 -4
- package/.github/skills/testdriver:waiting-for-elements/SKILL.md +10 -4
- package/CHANGELOG.md +4 -0
- package/ai/skills/testdriver:client/SKILL.md +107 -2
- package/ai/skills/testdriver:customizing-devices/SKILL.md +170 -4
- package/ai/skills/testdriver:find/SKILL.md +13 -4
- package/ai/skills/testdriver:waiting-for-elements/SKILL.md +10 -4
- package/docs/v7/find.mdx +13 -4
- package/docs/v7/waiting-for-elements.mdx +10 -4
- package/package.json +1 -1
- package/sdk.js +8 -4
|
@@ -33,8 +33,8 @@ const element = await testdriver.find(description, options)
|
|
|
33
33
|
Similarity threshold (0-1) for cache matching. Lower values require more similarity. Set to -1 to disable cache.
|
|
34
34
|
</ParamField>
|
|
35
35
|
|
|
36
|
-
<ParamField path="timeout" type="number">
|
|
37
|
-
Maximum time in milliseconds to poll for the element. Retries every 5 seconds until found or timeout expires.
|
|
36
|
+
<ParamField path="timeout" type="number" default={10000}>
|
|
37
|
+
Maximum time in milliseconds to poll for the element. Retries every 5 seconds until found or timeout expires. Defaults to `10000` (10 seconds). Set to `0` to disable polling and make a single attempt.
|
|
38
38
|
</ParamField>
|
|
39
39
|
|
|
40
40
|
<ParamField path="confidence" type="number">
|
|
@@ -309,19 +309,28 @@ const el = await testdriver.find('the blue submit button', { type: 'any' });
|
|
|
309
309
|
</Tip>
|
|
310
310
|
## Polling for Dynamic Elements
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
By default, `find()` polls for up to 10 seconds (retrying every 5 seconds) until the element is found. You can customize this with the `timeout` option:
|
|
313
313
|
|
|
314
314
|
```javascript
|
|
315
|
-
//
|
|
315
|
+
// Uses default 10s timeout - polls every 5 seconds
|
|
316
|
+
const element = await testdriver.find('login button');
|
|
317
|
+
await element.click();
|
|
318
|
+
|
|
319
|
+
// Custom timeout - wait up to 30 seconds
|
|
316
320
|
const element = await testdriver.find('login button', { timeout: 30000 });
|
|
317
321
|
await element.click();
|
|
322
|
+
|
|
323
|
+
// Disable polling - single attempt only
|
|
324
|
+
const element = await testdriver.find('login button', { timeout: 0 });
|
|
318
325
|
```
|
|
319
326
|
|
|
320
327
|
The `timeout` option:
|
|
328
|
+
- Defaults to `10000` (10 seconds)
|
|
321
329
|
- Retries finding the element every 5 seconds
|
|
322
330
|
- Stops when the element is found or the timeout expires
|
|
323
331
|
- Logs progress during polling
|
|
324
332
|
- Returns the element (check `element.found()` if not throwing on failure)
|
|
333
|
+
- Set to `0` to disable polling and make a single attempt
|
|
325
334
|
|
|
326
335
|
## Zoom Mode for Crowded UIs
|
|
327
336
|
|
|
@@ -6,10 +6,16 @@ description: Handle async operations and prevent flaky tests
|
|
|
6
6
|
|
|
7
7
|
## Waiting for Elements
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
By default, `find()` automatically polls for up to 10 seconds, retrying every 5 seconds until the element is found. This means most elements that appear after short async operations will be found without any extra configuration.
|
|
10
|
+
|
|
11
|
+
For longer operations, increase the `timeout`:
|
|
10
12
|
|
|
11
13
|
```javascript
|
|
12
|
-
//
|
|
14
|
+
// Default behavior - polls for up to 10 seconds automatically
|
|
15
|
+
const element = await testdriver.find('Loading complete indicator');
|
|
16
|
+
await element.click();
|
|
17
|
+
|
|
18
|
+
// Wait up to 30 seconds for slower operations
|
|
13
19
|
const element = await testdriver.find('Loading complete indicator', { timeout: 30000 });
|
|
14
20
|
await element.click();
|
|
15
21
|
|
|
@@ -17,8 +23,8 @@ await element.click();
|
|
|
17
23
|
await testdriver.find('submit button').click();
|
|
18
24
|
await testdriver.find('success message', { timeout: 15000 });
|
|
19
25
|
|
|
20
|
-
//
|
|
21
|
-
const toast = await testdriver.find('notification toast', { timeout:
|
|
26
|
+
// Disable polling for instant checks
|
|
27
|
+
const toast = await testdriver.find('notification toast', { timeout: 0 });
|
|
22
28
|
```
|
|
23
29
|
|
|
24
30
|
## Flake Prevention
|
package/CHANGELOG.md
CHANGED
|
@@ -24,7 +24,7 @@ const testdriver = new TestDriver(apiKey, options)
|
|
|
24
24
|
Configuration options for the client
|
|
25
25
|
|
|
26
26
|
<Expandable title="properties">
|
|
27
|
-
<ParamField path="os" type="string" default="
|
|
27
|
+
<ParamField path="os" type="string" default="linux">
|
|
28
28
|
Operating system for the sandbox: `'windows'` or `'linux'`
|
|
29
29
|
</ParamField>
|
|
30
30
|
|
|
@@ -32,7 +32,7 @@ const testdriver = new TestDriver(apiKey, options)
|
|
|
32
32
|
Screen resolution for the sandbox (e.g., `'1920x1080'`, `'1366x768'`)
|
|
33
33
|
</ParamField>
|
|
34
34
|
|
|
35
|
-
<ParamField path="apiRoot" type="string"
|
|
35
|
+
<ParamField path="apiRoot" type="string">
|
|
36
36
|
API endpoint URL (typically only changed for self-hosted deployments)
|
|
37
37
|
</ParamField>
|
|
38
38
|
|
|
@@ -48,6 +48,111 @@ const testdriver = new TestDriver(apiKey, options)
|
|
|
48
48
|
Automatically capture screenshots before and after each command. Screenshots are saved to `.testdriver/screenshots/<test>/` with descriptive filenames that include the line number and action name. Format: `<seq>-<action>-<phase>-L<line>-<description>.png`
|
|
49
49
|
</ParamField>
|
|
50
50
|
|
|
51
|
+
<ParamField path="newSandbox" type="boolean" default="true">
|
|
52
|
+
Force creation of a new sandbox instead of reusing an existing one
|
|
53
|
+
</ParamField>
|
|
54
|
+
|
|
55
|
+
<ParamField path="reconnect" type="boolean" default="false">
|
|
56
|
+
Reconnect to the last used sandbox instead of creating a new one. When `true`, provision methods (`chrome`, `vscode`, `installer`, etc.) will be skipped since the application is already running. Throws error if no previous sandbox exists.
|
|
57
|
+
</ParamField>
|
|
58
|
+
|
|
59
|
+
<ParamField path="keepAlive" type="number" default="60000">
|
|
60
|
+
Keep sandbox alive for the specified number of milliseconds after disconnect. Set to `0` to terminate immediately on disconnect. Useful for debugging or reconnecting to the same sandbox.
|
|
61
|
+
</ParamField>
|
|
62
|
+
|
|
63
|
+
<ParamField path="preview" type="string" default="browser">
|
|
64
|
+
Preview mode for live test visualization:
|
|
65
|
+
- `"browser"` — Opens debugger in default browser (default)
|
|
66
|
+
- `"ide"` — Opens preview in IDE panel (VSCode, Cursor - requires TestDriver extension)
|
|
67
|
+
- `"none"` — Headless mode, no visual preview
|
|
68
|
+
</ParamField>
|
|
69
|
+
|
|
70
|
+
<ParamField path="headless" type="boolean" default="false">
|
|
71
|
+
**Deprecated**: Use `preview: "none"` instead. Run in headless mode without opening the debugger.
|
|
72
|
+
</ParamField>
|
|
73
|
+
|
|
74
|
+
<ParamField path="debugOnFailure" type="boolean" default="false">
|
|
75
|
+
Keep the sandbox alive when a test fails so you can reconnect and debug interactively. The sandbox ID is printed to the console.
|
|
76
|
+
</ParamField>
|
|
77
|
+
|
|
78
|
+
<ParamField path="ip" type="string">
|
|
79
|
+
Direct IP address to connect to a running sandbox instance (for self-hosted deployments)
|
|
80
|
+
</ParamField>
|
|
81
|
+
|
|
82
|
+
<ParamField path="sandboxAmi" type="string">
|
|
83
|
+
Custom AMI ID for the sandbox instance (AWS deployments, e.g., `'ami-1234'`)
|
|
84
|
+
</ParamField>
|
|
85
|
+
|
|
86
|
+
<ParamField path="sandboxInstance" type="string">
|
|
87
|
+
EC2 instance type for the sandbox (AWS deployments, e.g., `'i3.metal'`)
|
|
88
|
+
</ParamField>
|
|
89
|
+
|
|
90
|
+
<ParamField path="cache" type="boolean | object" default="true">
|
|
91
|
+
Enable or disable element caching, or provide advanced threshold configuration.
|
|
92
|
+
|
|
93
|
+
<Expandable title="advanced config">
|
|
94
|
+
<ParamField path="enabled" type="boolean" default="true">
|
|
95
|
+
Enable or disable caching
|
|
96
|
+
</ParamField>
|
|
97
|
+
|
|
98
|
+
<ParamField path="thresholds" type="object">
|
|
99
|
+
Fine-tune cache matching
|
|
100
|
+
|
|
101
|
+
<Expandable title="properties">
|
|
102
|
+
<ParamField path="find" type="object">
|
|
103
|
+
Thresholds for `find()` operations
|
|
104
|
+
|
|
105
|
+
<Expandable title="properties">
|
|
106
|
+
<ParamField path="screen" type="number" default="0.05">
|
|
107
|
+
Pixel diff threshold for screen comparison (0-1). `0.05` = 5% diff allowed.
|
|
108
|
+
</ParamField>
|
|
109
|
+
|
|
110
|
+
<ParamField path="element" type="number" default="0.8">
|
|
111
|
+
OpenCV template match threshold for element matching (0-1). `0.8` = 80% correlation.
|
|
112
|
+
</ParamField>
|
|
113
|
+
</Expandable>
|
|
114
|
+
</ParamField>
|
|
115
|
+
|
|
116
|
+
<ParamField path="assert" type="number" default="0.05">
|
|
117
|
+
Pixel diff threshold for `assert()` operations (0-1). `0.05` = 5% diff allowed.
|
|
118
|
+
</ParamField>
|
|
119
|
+
</Expandable>
|
|
120
|
+
</ParamField>
|
|
121
|
+
</Expandable>
|
|
122
|
+
</ParamField>
|
|
123
|
+
|
|
124
|
+
<ParamField path="cacheKey" type="string">
|
|
125
|
+
Cache key for element finding operations. If provided, enables caching tied to this key.
|
|
126
|
+
</ParamField>
|
|
127
|
+
|
|
128
|
+
<ParamField path="dashcam" type="boolean" default="true">
|
|
129
|
+
Enable or disable Dashcam video recording
|
|
130
|
+
</ParamField>
|
|
131
|
+
|
|
132
|
+
<ParamField path="redraw" type="boolean | object" default="true">
|
|
133
|
+
Enable or disable screen-change (redraw) detection, or provide advanced configuration.
|
|
134
|
+
|
|
135
|
+
<Expandable title="advanced config">
|
|
136
|
+
<ParamField path="enabled" type="boolean" default="true">
|
|
137
|
+
Enable or disable redraw detection
|
|
138
|
+
</ParamField>
|
|
139
|
+
|
|
140
|
+
<ParamField path="thresholds" type="object">
|
|
141
|
+
Threshold configuration
|
|
142
|
+
|
|
143
|
+
<Expandable title="properties">
|
|
144
|
+
<ParamField path="screen" type="number | false" default="0.05">
|
|
145
|
+
Pixel diff threshold (0-1). Set to `false` to disable screen redraw detection.
|
|
146
|
+
</ParamField>
|
|
147
|
+
|
|
148
|
+
<ParamField path="network" type="boolean" default="false">
|
|
149
|
+
Enable or disable network activity monitoring
|
|
150
|
+
</ParamField>
|
|
151
|
+
</Expandable>
|
|
152
|
+
</ParamField>
|
|
153
|
+
</Expandable>
|
|
154
|
+
</ParamField>
|
|
155
|
+
|
|
51
156
|
<ParamField path="environment" type="object">
|
|
52
157
|
Additional environment variables to pass to the sandbox
|
|
53
158
|
</ParamField>
|
|
@@ -10,7 +10,64 @@ Configure TestDriver behavior with options passed to the `TestDriver()` function
|
|
|
10
10
|
|
|
11
11
|
```javascript
|
|
12
12
|
const testdriver = TestDriver(context, {
|
|
13
|
-
|
|
13
|
+
// === Sandbox & Connection ===
|
|
14
|
+
newSandbox: true, // Force creation of a new sandbox (default: true)
|
|
15
|
+
reconnect: false, // Reconnect to last sandbox (default: false)
|
|
16
|
+
keepAlive: 60000, // Keep sandbox alive after disconnect in ms (default: 60000)
|
|
17
|
+
os: "linux", // 'linux' | 'windows' (default: 'linux')
|
|
18
|
+
resolution: "1366x768", // Sandbox resolution (e.g., '1920x1080')
|
|
19
|
+
ip: "203.0.113.42", // Direct IP for self-hosted sandbox
|
|
20
|
+
sandboxAmi: "ami-1234", // Custom AMI ID (AWS deployments)
|
|
21
|
+
sandboxInstance: "i3.metal", // EC2 instance type (AWS deployments)
|
|
22
|
+
|
|
23
|
+
// === Preview & Debugging ===
|
|
24
|
+
preview: "browser", // "browser" | "ide" | "none" (default: "browser")
|
|
25
|
+
headless: false, // @deprecated - use preview: "none" instead
|
|
26
|
+
debugOnFailure: false, // Keep sandbox alive on test failure for debugging
|
|
27
|
+
|
|
28
|
+
// === Caching ===
|
|
29
|
+
cache: true, // Enable element caching (default: true)
|
|
30
|
+
// Or use advanced caching config:
|
|
31
|
+
// cache: {
|
|
32
|
+
// enabled: true,
|
|
33
|
+
// thresholds: {
|
|
34
|
+
// find: { screen: 0.05, element: 0.8 },
|
|
35
|
+
// assert: 0.05
|
|
36
|
+
// }
|
|
37
|
+
// },
|
|
38
|
+
cacheKey: "my-test", // Cache key for element finding operations
|
|
39
|
+
|
|
40
|
+
// === Recording & Screenshots ===
|
|
41
|
+
dashcam: true, // Enable/disable Dashcam video recording (default: true)
|
|
42
|
+
autoScreenshots: true, // Capture screenshots before/after each command (default: true)
|
|
43
|
+
|
|
44
|
+
// === AI Configuration ===
|
|
45
|
+
ai: { // Global AI sampling configuration
|
|
46
|
+
temperature: 0, // 0 = deterministic, higher = more creative
|
|
47
|
+
top: {
|
|
48
|
+
p: 0.9, // Top-P nucleus sampling (0-1)
|
|
49
|
+
k: 40, // Top-K sampling (1 = most likely, 0 = disabled)
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
// === Screen Change Detection ===
|
|
54
|
+
redraw: true, // Enable redraw detection (default: true)
|
|
55
|
+
// Or use advanced redraw config:
|
|
56
|
+
// redraw: {
|
|
57
|
+
// enabled: true,
|
|
58
|
+
// thresholds: {
|
|
59
|
+
// screen: 0.05, // Pixel diff threshold (0-1), false to disable
|
|
60
|
+
// network: false, // Monitor network activity (default: false)
|
|
61
|
+
// }
|
|
62
|
+
// },
|
|
63
|
+
|
|
64
|
+
// === Logging & Analytics ===
|
|
65
|
+
logging: true, // Enable console logging output (default: true)
|
|
66
|
+
analytics: true, // Enable analytics tracking (default: true)
|
|
67
|
+
|
|
68
|
+
// === Advanced ===
|
|
69
|
+
apiRoot: "https://...", // API endpoint URL (for self-hosted deployments)
|
|
70
|
+
environment: {}, // Additional environment variables for the sandbox
|
|
14
71
|
});
|
|
15
72
|
```
|
|
16
73
|
|
|
@@ -54,6 +111,16 @@ const testdriver = TestDriver(context, {
|
|
|
54
111
|
The legacy `headless: true` option still works for backward compatibility and maps to `preview: "none"`.
|
|
55
112
|
</Note>
|
|
56
113
|
|
|
114
|
+
### Debug on Failure
|
|
115
|
+
|
|
116
|
+
Keep the sandbox alive when a test fails so you can reconnect and debug interactively. The sandbox ID is printed to the console along with instructions for reconnecting via MCP.
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const testdriver = TestDriver(context, {
|
|
120
|
+
debugOnFailure: true,
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
57
124
|
### IP Target
|
|
58
125
|
|
|
59
126
|
If self-hosting TestDriver, use `ip` to specify the device IP. See [Self-Hosting TestDriver](../self-hosting.md) for details.
|
|
@@ -105,11 +172,102 @@ steps:
|
|
|
105
172
|
- run: TD_OS=${{ matrix.os }} vitest run
|
|
106
173
|
```
|
|
107
174
|
|
|
108
|
-
|
|
175
|
+
### Dashcam Recording
|
|
176
|
+
|
|
177
|
+
Dashcam video recording is enabled by default. Disable it to skip recording:
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
const testdriver = TestDriver(context, {
|
|
181
|
+
dashcam: false,
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Automatic Screenshots
|
|
186
|
+
|
|
187
|
+
Screenshots are automatically captured before and after every command (click, type, find, assert, etc.) by default. Each screenshot filename includes the line number from your test file.
|
|
188
|
+
|
|
189
|
+
Disable automatic screenshots:
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
const testdriver = TestDriver(context, {
|
|
193
|
+
autoScreenshots: false,
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Caching
|
|
198
|
+
|
|
199
|
+
Element caching speeds up repeated `find()` and `assert()` calls. Enabled by default.
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
// Disable caching
|
|
203
|
+
const testdriver = TestDriver(context, {
|
|
204
|
+
cache: false,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Advanced: custom thresholds
|
|
208
|
+
const testdriver = TestDriver(context, {
|
|
209
|
+
cache: {
|
|
210
|
+
enabled: true,
|
|
211
|
+
thresholds: {
|
|
212
|
+
find: { screen: 0.05, element: 0.8 },
|
|
213
|
+
assert: 0.05,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
cacheKey: "my-test",
|
|
217
|
+
});
|
|
218
|
+
```
|
|
109
219
|
|
|
110
|
-
|
|
220
|
+
### Redraw Detection
|
|
111
221
|
|
|
112
|
-
|
|
222
|
+
Redraw detection waits for the screen to stabilize before taking actions. Enabled by default.
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
// Disable redraw detection
|
|
226
|
+
const testdriver = TestDriver(context, {
|
|
227
|
+
redraw: false,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Advanced: custom thresholds with network monitoring
|
|
231
|
+
const testdriver = TestDriver(context, {
|
|
232
|
+
redraw: {
|
|
233
|
+
enabled: true,
|
|
234
|
+
thresholds: {
|
|
235
|
+
screen: 0.05,
|
|
236
|
+
network: true,
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### AI Configuration
|
|
243
|
+
|
|
244
|
+
Control how the AI model generates responses for `find()` verification and `assert()` calls:
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
const testdriver = TestDriver(context, {
|
|
248
|
+
ai: {
|
|
249
|
+
temperature: 0, // 0 = deterministic
|
|
250
|
+
top: { p: 0.9, k: 40 },
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Environment Variables
|
|
256
|
+
|
|
257
|
+
Pass additional environment variables to the sandbox:
|
|
258
|
+
|
|
259
|
+
```javascript
|
|
260
|
+
const testdriver = TestDriver(context, {
|
|
261
|
+
environment: {
|
|
262
|
+
MY_VAR: "value",
|
|
263
|
+
DEBUG: "true",
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Keepalive
|
|
269
|
+
|
|
270
|
+
By default, sandboxes stay alive for 60 seconds after disconnect. Customize this with `keepAlive`:
|
|
113
271
|
|
|
114
272
|
```javascript
|
|
115
273
|
const testdriver = TestDriver(context, {
|
|
@@ -117,6 +275,14 @@ const testdriver = TestDriver(context, {
|
|
|
117
275
|
});
|
|
118
276
|
```
|
|
119
277
|
|
|
278
|
+
Set to `0` to terminate immediately:
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
const testdriver = TestDriver(context, {
|
|
282
|
+
keepAlive: 0, // Terminate sandbox immediately on disconnect
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
120
286
|
### Reconnecting to Existing Sandbox
|
|
121
287
|
|
|
122
288
|
Speed up test development by reconnecting to an existing sandbox instead of starting fresh each time. This lets you iterate quickly on failing steps without re-running the entire test from the beginning.
|
|
@@ -33,8 +33,8 @@ const element = await testdriver.find(description, options)
|
|
|
33
33
|
Similarity threshold (0-1) for cache matching. Lower values require more similarity. Set to -1 to disable cache.
|
|
34
34
|
</ParamField>
|
|
35
35
|
|
|
36
|
-
<ParamField path="timeout" type="number">
|
|
37
|
-
Maximum time in milliseconds to poll for the element. Retries every 5 seconds until found or timeout expires.
|
|
36
|
+
<ParamField path="timeout" type="number" default={10000}>
|
|
37
|
+
Maximum time in milliseconds to poll for the element. Retries every 5 seconds until found or timeout expires. Defaults to `10000` (10 seconds). Set to `0` to disable polling and make a single attempt.
|
|
38
38
|
</ParamField>
|
|
39
39
|
|
|
40
40
|
<ParamField path="confidence" type="number">
|
|
@@ -309,19 +309,28 @@ const el = await testdriver.find('the blue submit button', { type: 'any' });
|
|
|
309
309
|
</Tip>
|
|
310
310
|
## Polling for Dynamic Elements
|
|
311
311
|
|
|
312
|
-
|
|
312
|
+
By default, `find()` polls for up to 10 seconds (retrying every 5 seconds) until the element is found. You can customize this with the `timeout` option:
|
|
313
313
|
|
|
314
314
|
```javascript
|
|
315
|
-
//
|
|
315
|
+
// Uses default 10s timeout - polls every 5 seconds
|
|
316
|
+
const element = await testdriver.find('login button');
|
|
317
|
+
await element.click();
|
|
318
|
+
|
|
319
|
+
// Custom timeout - wait up to 30 seconds
|
|
316
320
|
const element = await testdriver.find('login button', { timeout: 30000 });
|
|
317
321
|
await element.click();
|
|
322
|
+
|
|
323
|
+
// Disable polling - single attempt only
|
|
324
|
+
const element = await testdriver.find('login button', { timeout: 0 });
|
|
318
325
|
```
|
|
319
326
|
|
|
320
327
|
The `timeout` option:
|
|
328
|
+
- Defaults to `10000` (10 seconds)
|
|
321
329
|
- Retries finding the element every 5 seconds
|
|
322
330
|
- Stops when the element is found or the timeout expires
|
|
323
331
|
- Logs progress during polling
|
|
324
332
|
- Returns the element (check `element.found()` if not throwing on failure)
|
|
333
|
+
- Set to `0` to disable polling and make a single attempt
|
|
325
334
|
|
|
326
335
|
## Zoom Mode for Crowded UIs
|
|
327
336
|
|
|
@@ -6,10 +6,16 @@ description: Handle async operations and prevent flaky tests
|
|
|
6
6
|
|
|
7
7
|
## Waiting for Elements
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
By default, `find()` automatically polls for up to 10 seconds, retrying every 5 seconds until the element is found. This means most elements that appear after short async operations will be found without any extra configuration.
|
|
10
|
+
|
|
11
|
+
For longer operations, increase the `timeout`:
|
|
10
12
|
|
|
11
13
|
```javascript
|
|
12
|
-
//
|
|
14
|
+
// Default behavior - polls for up to 10 seconds automatically
|
|
15
|
+
const element = await testdriver.find('Loading complete indicator');
|
|
16
|
+
await element.click();
|
|
17
|
+
|
|
18
|
+
// Wait up to 30 seconds for slower operations
|
|
13
19
|
const element = await testdriver.find('Loading complete indicator', { timeout: 30000 });
|
|
14
20
|
await element.click();
|
|
15
21
|
|
|
@@ -17,8 +23,8 @@ await element.click();
|
|
|
17
23
|
await testdriver.find('submit button').click();
|
|
18
24
|
await testdriver.find('success message', { timeout: 15000 });
|
|
19
25
|
|
|
20
|
-
//
|
|
21
|
-
const toast = await testdriver.find('notification toast', { timeout:
|
|
26
|
+
// Disable polling for instant checks
|
|
27
|
+
const toast = await testdriver.find('notification toast', { timeout: 0 });
|
|
22
28
|
```
|
|
23
29
|
|
|
24
30
|
## Flake Prevention
|
package/docs/v7/find.mdx
CHANGED
|
@@ -34,8 +34,8 @@ const element = await testdriver.find(description, options)
|
|
|
34
34
|
Similarity threshold (0-1) for cache matching. Lower values require more similarity. Set to -1 to disable cache.
|
|
35
35
|
</ParamField>
|
|
36
36
|
|
|
37
|
-
<ParamField path="timeout" type="number">
|
|
38
|
-
Maximum time in milliseconds to poll for the element. Retries every 5 seconds until found or timeout expires.
|
|
37
|
+
<ParamField path="timeout" type="number" default={10000}>
|
|
38
|
+
Maximum time in milliseconds to poll for the element. Retries every 5 seconds until found or timeout expires. Defaults to `10000` (10 seconds). Set to `0` to disable polling and make a single attempt.
|
|
39
39
|
</ParamField>
|
|
40
40
|
|
|
41
41
|
<ParamField path="confidence" type="number">
|
|
@@ -310,19 +310,28 @@ const el = await testdriver.find('the blue submit button', { type: 'any' });
|
|
|
310
310
|
</Tip>
|
|
311
311
|
## Polling for Dynamic Elements
|
|
312
312
|
|
|
313
|
-
|
|
313
|
+
By default, `find()` polls for up to 10 seconds (retrying every 5 seconds) until the element is found. You can customize this with the `timeout` option:
|
|
314
314
|
|
|
315
315
|
```javascript
|
|
316
|
-
//
|
|
316
|
+
// Uses default 10s timeout - polls every 5 seconds
|
|
317
|
+
const element = await testdriver.find('login button');
|
|
318
|
+
await element.click();
|
|
319
|
+
|
|
320
|
+
// Custom timeout - wait up to 30 seconds
|
|
317
321
|
const element = await testdriver.find('login button', { timeout: 30000 });
|
|
318
322
|
await element.click();
|
|
323
|
+
|
|
324
|
+
// Disable polling - single attempt only
|
|
325
|
+
const element = await testdriver.find('login button', { timeout: 0 });
|
|
319
326
|
```
|
|
320
327
|
|
|
321
328
|
The `timeout` option:
|
|
329
|
+
- Defaults to `10000` (10 seconds)
|
|
322
330
|
- Retries finding the element every 5 seconds
|
|
323
331
|
- Stops when the element is found or the timeout expires
|
|
324
332
|
- Logs progress during polling
|
|
325
333
|
- Returns the element (check `element.found()` if not throwing on failure)
|
|
334
|
+
- Set to `0` to disable polling and make a single attempt
|
|
326
335
|
|
|
327
336
|
## Zoom Mode for Crowded UIs
|
|
328
337
|
|
|
@@ -6,10 +6,16 @@ icon: "clock"
|
|
|
6
6
|
|
|
7
7
|
## Waiting for Elements
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
By default, `find()` automatically polls for up to 10 seconds, retrying every 5 seconds until the element is found. This means most elements that appear after short async operations will be found without any extra configuration.
|
|
10
|
+
|
|
11
|
+
For longer operations, increase the `timeout`:
|
|
10
12
|
|
|
11
13
|
```javascript
|
|
12
|
-
//
|
|
14
|
+
// Default behavior - polls for up to 10 seconds automatically
|
|
15
|
+
const element = await testdriver.find('Loading complete indicator');
|
|
16
|
+
await element.click();
|
|
17
|
+
|
|
18
|
+
// Wait up to 30 seconds for slower operations
|
|
13
19
|
const element = await testdriver.find('Loading complete indicator', { timeout: 30000 });
|
|
14
20
|
await element.click();
|
|
15
21
|
|
|
@@ -17,8 +23,8 @@ await element.click();
|
|
|
17
23
|
await testdriver.find('submit button').click();
|
|
18
24
|
await testdriver.find('success message', { timeout: 15000 });
|
|
19
25
|
|
|
20
|
-
//
|
|
21
|
-
const toast = await testdriver.find('notification toast', { timeout:
|
|
26
|
+
// Disable polling for instant checks
|
|
27
|
+
const toast = await testdriver.find('notification toast', { timeout: 0 });
|
|
22
28
|
```
|
|
23
29
|
|
|
24
30
|
## Flake Prevention
|
package/package.json
CHANGED
package/sdk.js
CHANGED
|
@@ -436,8 +436,10 @@ class Element {
|
|
|
436
436
|
* @returns {Promise<Element>} This element instance
|
|
437
437
|
*/
|
|
438
438
|
async find(newDescription, options) {
|
|
439
|
-
// Handle timeout/polling option
|
|
440
|
-
const timeout = typeof options === "object"
|
|
439
|
+
// Handle timeout/polling option (default: 30s)
|
|
440
|
+
const timeout = typeof options === "object" && options?.timeout !== undefined
|
|
441
|
+
? options.timeout
|
|
442
|
+
: 10000;
|
|
441
443
|
if (timeout && timeout > 0) {
|
|
442
444
|
return this._findWithTimeout(newDescription, options, timeout);
|
|
443
445
|
}
|
|
@@ -1729,6 +1731,8 @@ class TestDriverSDK {
|
|
|
1729
1731
|
*/
|
|
1730
1732
|
async _waitForChromeDebuggerReady(timeoutMs = 60000) {
|
|
1731
1733
|
const shell = this.os === "windows" ? "pwsh" : "sh";
|
|
1734
|
+
// PowerShell: Use async connect with 2-second timeout to match Linux curl behavior.
|
|
1735
|
+
// TcpClient.Connect() is synchronous and can hang indefinitely, causing exec timeouts.
|
|
1732
1736
|
const portCheckCmd = this.os === "windows"
|
|
1733
1737
|
? `$tcp = New-Object System.Net.Sockets.TcpClient; $tcp.Connect('127.0.0.1', 9222); $tcp.Close(); echo 'open'`
|
|
1734
1738
|
: `curl -s -o /dev/null --connect-timeout 2 http://localhost:9222 2>/dev/null && echo 'open' || echo 'closed'`;
|
|
@@ -1895,7 +1899,7 @@ class TestDriverSDK {
|
|
|
1895
1899
|
// Add web log tracking with domain wildcard pattern, then start dashcam
|
|
1896
1900
|
if (this.dashcamEnabled) {
|
|
1897
1901
|
const domainPattern = this._getUrlDomainPattern(url);
|
|
1898
|
-
|
|
1902
|
+
await this.dashcam.addWebLog(domainPattern, "Web Logs");
|
|
1899
1903
|
|
|
1900
1904
|
// Start dashcam recording after logs are configured
|
|
1901
1905
|
if (!(await this.dashcam.isRecording())) {
|
|
@@ -2462,7 +2466,7 @@ with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
|
|
2462
2466
|
const pattern = this._provisionedChromeUrl
|
|
2463
2467
|
? this._getUrlDomainPattern(this._provisionedChromeUrl)
|
|
2464
2468
|
: "**";
|
|
2465
|
-
|
|
2469
|
+
await this.dashcam.addWebLog(pattern, "Web Logs");
|
|
2466
2470
|
}
|
|
2467
2471
|
|
|
2468
2472
|
// Start recording if not already recording
|