@testdriverai/mcp 7.11.136-test → 7.11.138-test
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/ai/skills/testdriver-assert/SKILL.md +5 -5
- package/ai/skills/testdriver-caching/SKILL.md +2 -2
- package/ai/skills/testdriver-changelog/SKILL.md +186 -0
- package/ai/skills/testdriver-claude-mcp-plugin/SKILL.md +208 -0
- package/ai/skills/testdriver-click/SKILL.md +13 -13
- package/ai/skills/testdriver-client/SKILL.md +1 -1
- package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +5 -5
- package/ai/skills/testdriver-double-click/SKILL.md +7 -7
- package/ai/skills/testdriver-enterprise/SKILL.md +1 -1
- package/ai/skills/testdriver-events/SKILL.md +1 -1
- package/ai/skills/testdriver-exec/SKILL.md +10 -10
- package/ai/skills/testdriver-extract/SKILL.md +6 -6
- package/ai/skills/testdriver-find/SKILL.md +61 -61
- package/ai/skills/testdriver-focus-application/SKILL.md +6 -6
- package/ai/skills/testdriver-generating-tests/SKILL.md +3 -3
- package/ai/skills/testdriver-hosted/SKILL.md +3 -3
- package/ai/skills/testdriver-hover/SKILL.md +6 -6
- package/ai/skills/testdriver-making-assertions/SKILL.md +2 -2
- package/ai/skills/testdriver-mouse-down/SKILL.md +9 -9
- package/ai/skills/testdriver-mouse-up/SKILL.md +9 -9
- package/ai/skills/testdriver-parse/SKILL.md +4 -4
- package/ai/skills/testdriver-performing-actions/SKILL.md +4 -4
- package/ai/skills/testdriver-press-keys/SKILL.md +5 -5
- package/ai/skills/testdriver-quickstart/SKILL.md +51 -54
- package/ai/skills/testdriver-redraw/SKILL.md +1 -1
- package/ai/skills/testdriver-right-click/SKILL.md +7 -7
- package/ai/skills/testdriver-screenshot/SKILL.md +9 -9
- package/ai/skills/testdriver-scroll/SKILL.md +13 -13
- package/ai/skills/testdriver-self-hosted/SKILL.md +1 -1
- package/ai/skills/testdriver-type/SKILL.md +7 -7
- package/ai/skills/testdriver-wait/SKILL.md +5 -5
- package/ai/skills/testdriver-what-is-testdriver/SKILL.md +11 -11
- package/docs/{v7/_drafts → _drafts}/agents.mdx +1 -1
- package/docs/{v7/_drafts → _drafts}/best-practices.mdx +4 -4
- package/docs/{v7/_drafts → _drafts}/caching-selectors.mdx +3 -3
- package/docs/{v7/_drafts → _drafts}/configuration.mdx +4 -4
- package/docs/{v7/_drafts → _drafts}/debugging.mdx +4 -4
- package/docs/{v7/_drafts → _drafts}/error-handling.mdx +4 -4
- package/docs/{v7/_drafts → _drafts}/faq.mdx +7 -7
- package/docs/{v7/_drafts → _drafts}/installation.mdx +2 -2
- package/docs/{v7/_drafts → _drafts}/migration.mdx +4 -4
- package/docs/{v7/_drafts → _drafts}/observable.mdx +3 -3
- package/docs/{v7/_drafts → _drafts}/powerful.mdx +4 -4
- package/docs/{v7/_drafts → _drafts}/readme.mdx +11 -11
- package/docs/{v7/_drafts → _drafts}/reports.mdx +4 -4
- package/docs/{v7/_drafts → _drafts}/scalable.mdx +10 -10
- package/docs/{v7/_drafts → _drafts}/troubleshooting.mdx +4 -4
- package/docs/{v7/_drafts → _drafts}/vitest-plugin.mdx +2 -2
- package/docs/{v7/_drafts → _drafts}/vitest.mdx +9 -9
- package/docs/_scripts/generate-examples.js +9 -10
- package/docs/_scripts/generate-skills.js +4 -4
- package/docs/{v7/agent.mdx → agent.mdx} +17 -17
- package/docs/{v7/assert.mdx → assert.mdx} +5 -5
- package/docs/{v7/aws-setup.mdx → aws-setup.mdx} +6 -6
- package/docs/{v7/cache.mdx → cache.mdx} +9 -9
- package/docs/{v7/caching.mdx → caching.mdx} +13 -12
- package/docs/{v7/captcha.mdx → captcha.mdx} +7 -7
- package/docs/changelog.mdx +13 -13
- package/docs/{v7/ci-cd.mdx → ci-cd.mdx} +10 -10
- package/docs/{v7/click.mdx → click.mdx} +13 -13
- package/docs/client.mdx +323 -0
- package/docs/{v7/copilot → copilot}/auto-healing.mdx +2 -2
- package/docs/{v7/copilot → copilot}/running-tests.mdx +8 -8
- package/docs/{v7/customizing-devices.mdx → customizing-devices.mdx} +1 -1
- package/docs/{v7/dashcam.mdx → dashcam.mdx} +3 -3
- package/docs/{v7/debugging-with-screenshots.mdx → debugging-with-screenshots.mdx} +12 -12
- package/docs/docs.json +429 -288
- package/docs/{v7/double-click.mdx → double-click.mdx} +7 -7
- package/docs/{v7/elements.mdx → elements.mdx} +7 -7
- package/docs/{v7/enterprise.mdx → enterprise.mdx} +2 -2
- package/docs/{v7/errors.mdx → errors.mdx} +3 -3
- package/docs/{v7/events.mdx → events.mdx} +4 -4
- package/docs/{v7/exec.mdx → exec.mdx} +10 -10
- package/docs/{v7/extract.mdx → extract.mdx} +10 -10
- package/docs/{v7/find.mdx → find.mdx} +61 -61
- package/docs/{v7/focus-application.mdx → focus-application.mdx} +6 -6
- package/docs/{v7/generating-tests.mdx → generating-tests.mdx} +10 -10
- package/docs/guide/best-practices-polling.mdx +6 -1
- package/docs/{v7/hosted.mdx → hosted.mdx} +7 -7
- package/docs/{v7/hover.mdx → hover.mdx} +6 -6
- package/docs/interacting-with-your-app.mdx +198 -0
- package/docs/locating-elements.mdx +423 -0
- package/docs/{v7/making-assertions.mdx → making-assertions.mdx} +7 -7
- package/docs/{v7/mouse-down.mdx → mouse-down.mdx} +9 -9
- package/docs/{v7/mouse-up.mdx → mouse-up.mdx} +9 -9
- package/docs/options.mdx +320 -0
- package/docs/{v7/parse.mdx → parse.mdx} +12 -12
- package/docs/{v7/performing-actions.mdx → performing-actions.mdx} +11 -11
- package/docs/{v7/press-keys.mdx → press-keys.mdx} +5 -5
- package/docs/{v7/provision.mdx → provision.mdx} +9 -9
- package/docs/quickstart-cli.mdx +437 -0
- package/docs/quickstart-github.mdx +54 -0
- package/docs/quickstart-manual.mdx +135 -0
- package/docs/quickstart.mdx +22 -0
- package/docs/{v7/redraw.mdx → redraw.mdx} +7 -7
- package/docs/{v7/reusable-code.mdx → reusable-code.mdx} +3 -3
- package/docs/{v7/right-click.mdx → right-click.mdx} +7 -7
- package/docs/{v7/screenshot.mdx → screenshot.mdx} +9 -9
- package/docs/{v7/screenshots.mdx → screenshots.mdx} +3 -3
- package/docs/{v7/scroll.mdx → scroll.mdx} +13 -13
- package/docs/{v7/secrets.mdx → secrets.mdx} +4 -4
- package/docs/{v7/self-hosted.mdx → self-hosted.mdx} +7 -7
- package/docs/{v7/test-results-json.mdx → test-results-json.mdx} +4 -4
- package/docs/{v7/type.mdx → type.mdx} +7 -7
- package/docs/{v7/variables.mdx → variables.mdx} +2 -2
- package/docs/{v7/wait.mdx → wait.mdx} +5 -5
- package/docs/what-is-testdriver.mdx +54 -0
- package/lib/environments.json +1 -1
- package/lib/github-comment.mjs +2 -3
- package/package.json +1 -1
- package/scripts/generate-skills.js +1 -1
- package/docs/v7/client.mdx +0 -486
- package/docs/v7/quickstart.mdx +0 -451
- package/docs/v7/what-is-testdriver.mdx +0 -54
- /package/docs/{v7/_drafts → _drafts}/architecture.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/auto-cache-key.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/awesome-logs-quick-ref.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/cli-to-sdk-migration.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/assert.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/exec.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/focus-application.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/hover-image.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/hover-text.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/if.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/match-image.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/press-keys.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/remember.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/run.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/scroll-until-image.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/scroll-until-text.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/scroll.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/type.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/wait-for-image.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/wait-for-text.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/commands/wait.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/contributing.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/dashcam-title-feature.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/hooks.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/init-command.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/playwright.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/plugin-migration.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/presets.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/progressive-disclosure.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/provision.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/quick-start-test-recording.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/screenshot.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/sdk-awesome-logs.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/sdk-browser-rendering.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/sdk-migration.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/sdk-v7-complete.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/self-hosting.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/test-recording.mdx +0 -0
- /package/docs/{v7/_drafts → _drafts}/writing-tests.mdx +0 -0
- /package/docs/{v7/examples → examples}/ai.mdx +0 -0
- /package/docs/{v7/examples → examples}/assert.mdx +0 -0
- /package/docs/{v7/examples → examples}/captcha-api.mdx +0 -0
- /package/docs/{v7/examples → examples}/chrome-extension.mdx +0 -0
- /package/docs/{v7/examples → examples}/drag-and-drop.mdx +0 -0
- /package/docs/{v7/examples → examples}/element-not-found.mdx +0 -0
- /package/docs/{v7/examples → examples}/findall-coffee-icons.mdx +0 -0
- /package/docs/{v7/examples → examples}/formatted-logging.mdx +0 -0
- /package/docs/{v7/examples → examples}/hover-image.mdx +0 -0
- /package/docs/{v7/examples → examples}/hover-text-with-description.mdx +0 -0
- /package/docs/{v7/examples → examples}/hover-text.mdx +0 -0
- /package/docs/{v7/examples → examples}/installer.mdx +0 -0
- /package/docs/{v7/examples → examples}/launch-vscode-linux.mdx +0 -0
- /package/docs/{v7/examples → examples}/match-image.mdx +0 -0
- /package/docs/{v7/examples → examples}/parse.mdx +0 -0
- /package/docs/{v7/examples → examples}/press-keys.mdx +0 -0
- /package/docs/{v7/examples → examples}/scroll-keyboard.mdx +0 -0
- /package/docs/{v7/examples → examples}/scroll-until-text.mdx +0 -0
- /package/docs/{v7/examples → examples}/scroll.mdx +0 -0
- /package/docs/{v7/examples → examples}/type.mdx +0 -0
- /package/docs/{v7/mcp.mdx → mcp.mdx} +0 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Locating Elements"
|
|
3
|
+
sidebarTitle: "Locating Elements"
|
|
4
|
+
description: "Locate UI elements using AI"
|
|
5
|
+
icon: "mouse-pointer"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
The TestDriver element finding system uses AI. It finds elements on the screen with natural language descriptions. The `find()` method returns an `Element` object. You can [interact with the object](/interacting-with-your-app).
|
|
11
|
+
|
|
12
|
+
## Finding Elements
|
|
13
|
+
|
|
14
|
+
### find()
|
|
15
|
+
|
|
16
|
+
Find an element on the screen with a natural language description.
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
const element = await testdriver.find(description)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Parameters:**
|
|
23
|
+
- `description` (string) - A natural language description of the element to find
|
|
24
|
+
|
|
25
|
+
**Returns:** `Promise<Element>` - The Element instance that TestDriver found
|
|
26
|
+
|
|
27
|
+
**Example:**
|
|
28
|
+
```javascript
|
|
29
|
+
// Find a button
|
|
30
|
+
const submitButton = await testdriver.find('the submit button');
|
|
31
|
+
|
|
32
|
+
// Find an input field with context
|
|
33
|
+
const emailField = await testdriver.find('email input field in the login form');
|
|
34
|
+
|
|
35
|
+
// Find an element by visual characteristics
|
|
36
|
+
const redButton = await testdriver.find('red button in the top right corner');
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
<Tip>
|
|
40
|
+
Be specific in your descriptions. Include visual details, location context, or nearby text to make the accuracy better.
|
|
41
|
+
</Tip>
|
|
42
|
+
|
|
43
|
+
## Element Class
|
|
44
|
+
|
|
45
|
+
The `Element` class represents a located (or to-be-located) UI element. It provides methods for interaction and properties for element information. For interaction methods like `click()` and `hover()`, see [Interacting With Your App](/interacting-with-your-app).
|
|
46
|
+
|
|
47
|
+
### Methods
|
|
48
|
+
|
|
49
|
+
#### found()
|
|
50
|
+
|
|
51
|
+
Check if the element was successfully located.
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
element.found()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Returns:** `boolean` - True if element coordinates were found
|
|
58
|
+
|
|
59
|
+
**Example:**
|
|
60
|
+
```javascript
|
|
61
|
+
const element = await testdriver.find('login button');
|
|
62
|
+
if (element.found()) {
|
|
63
|
+
await element.click();
|
|
64
|
+
} else {
|
|
65
|
+
console.log('Element not found');
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### find()
|
|
70
|
+
|
|
71
|
+
Re-locate the element, optionally with a new description.
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
await element.find(newDescription)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Parameters:**
|
|
78
|
+
- `newDescription` (string, optional) - New description to search for
|
|
79
|
+
|
|
80
|
+
**Returns:** `Promise<Element>` - This element instance
|
|
81
|
+
|
|
82
|
+
**Example:**
|
|
83
|
+
```javascript
|
|
84
|
+
// Re-locate if the UI changed
|
|
85
|
+
const element = await testdriver.find('submit button');
|
|
86
|
+
// ... page updates ...
|
|
87
|
+
await element.find(); // Re-locate with same description
|
|
88
|
+
|
|
89
|
+
// Or update the description
|
|
90
|
+
await element.find('blue submit button'); // Now looking for blue button
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Properties
|
|
94
|
+
|
|
95
|
+
Element properties provide additional information about located elements. Properties are available after a successful `find()` call.
|
|
96
|
+
|
|
97
|
+
#### coordinates
|
|
98
|
+
|
|
99
|
+
Get the element's coordinates object containing all position information.
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const coords = element.getCoordinates()
|
|
103
|
+
// or access directly
|
|
104
|
+
element.coordinates
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Returns:** `Object | null` - Coordinate object with `{ x, y, centerX, centerY }`
|
|
108
|
+
|
|
109
|
+
**Example:**
|
|
110
|
+
```javascript
|
|
111
|
+
const button = await testdriver.find('submit button');
|
|
112
|
+
const coords = button.coordinates;
|
|
113
|
+
|
|
114
|
+
if (coords) {
|
|
115
|
+
console.log(`Top-left: (${coords.x}, ${coords.y})`);
|
|
116
|
+
console.log(`Center: (${coords.centerX}, ${coords.centerY})`);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### x, y, centerX, centerY
|
|
121
|
+
|
|
122
|
+
Direct access to coordinate values. Always available after successful `find()`.
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
element.x // Top-left X coordinate (number)
|
|
126
|
+
element.y // Top-left Y coordinate (number)
|
|
127
|
+
element.centerX // Center X coordinate (number)
|
|
128
|
+
element.centerY // Center Y coordinate (number)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Example:**
|
|
132
|
+
```javascript
|
|
133
|
+
const button = await testdriver.find('submit button');
|
|
134
|
+
console.log(`Button at: (${button.x}, ${button.y})`);
|
|
135
|
+
console.log(`Button center: (${button.centerX}, ${button.centerY})`);
|
|
136
|
+
|
|
137
|
+
// Use for custom mouse operations
|
|
138
|
+
await testdriver.click(button.centerX, button.centerY);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### width, height
|
|
142
|
+
|
|
143
|
+
Element dimensions in pixels. Available when AI detects element bounds.
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
element.width // Width in pixels (number | null)
|
|
147
|
+
element.height // Height in pixels (number | null)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Example:**
|
|
151
|
+
```javascript
|
|
152
|
+
const button = await testdriver.find('submit button');
|
|
153
|
+
|
|
154
|
+
if (button.width && button.height) {
|
|
155
|
+
console.log(`Button size: ${button.width}x${button.height}px`);
|
|
156
|
+
|
|
157
|
+
// Check if button is large enough
|
|
158
|
+
if (button.width < 50) {
|
|
159
|
+
console.warn('Button might be too small');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### boundingBox
|
|
165
|
+
|
|
166
|
+
Complete bounding box information including position and dimensions.
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
element.boundingBox
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Returns:** `Object | null` - Bounding box with all dimension data
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
{
|
|
176
|
+
x: number, // Top-left X
|
|
177
|
+
y: number, // Top-left Y
|
|
178
|
+
width: number, // Width in pixels
|
|
179
|
+
height: number // Height in pixels
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Example:**
|
|
184
|
+
```javascript
|
|
185
|
+
const element = await testdriver.find('dialog box');
|
|
186
|
+
|
|
187
|
+
if (element.boundingBox) {
|
|
188
|
+
const { x, y, width, height } = element.boundingBox;
|
|
189
|
+
console.log(`Dialog: ${width}x${height} at (${x}, ${y})`);
|
|
190
|
+
|
|
191
|
+
// Calculate if element is in viewport
|
|
192
|
+
const rightEdge = x + width;
|
|
193
|
+
const bottomEdge = y + height;
|
|
194
|
+
console.log(`Element extends to (${rightEdge}, ${bottomEdge})`);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### screenshot
|
|
199
|
+
|
|
200
|
+
Base64-encoded PNG screenshot of the screen when element was found. Only available in DEBUG mode or when an error occurs.
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
element.screenshot
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Returns:** `string | null` - Base64-encoded PNG image
|
|
207
|
+
|
|
208
|
+
**Example:**
|
|
209
|
+
```javascript
|
|
210
|
+
const element = await testdriver.find('error message');
|
|
211
|
+
|
|
212
|
+
if (element.screenshot) {
|
|
213
|
+
// Save screenshot to file
|
|
214
|
+
const fs = require('fs');
|
|
215
|
+
const base64Data = element.screenshot.replace(/^data:image\/\w+;base64,/, '');
|
|
216
|
+
fs.writeFileSync('element-screenshot.png', Buffer.from(base64Data, 'base64'));
|
|
217
|
+
console.log('Screenshot saved');
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
<Warning>
|
|
222
|
+
Screenshots can be large. They're automatically excluded from error messages to prevent memory issues.
|
|
223
|
+
</Warning>
|
|
224
|
+
|
|
225
|
+
#### text
|
|
226
|
+
|
|
227
|
+
Text content extracted from the element by AI (if available).
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
element.text
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Returns:** `string | null` - Element's text content
|
|
234
|
+
|
|
235
|
+
**Example:**
|
|
236
|
+
```javascript
|
|
237
|
+
const message = await testdriver.find('notification message');
|
|
238
|
+
|
|
239
|
+
if (message.text) {
|
|
240
|
+
console.log('Message says:', message.text);
|
|
241
|
+
|
|
242
|
+
// Use text content in assertions
|
|
243
|
+
if (message.text.includes('success')) {
|
|
244
|
+
console.log('Success message detected');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Another example - extracting button label
|
|
249
|
+
const button = await testdriver.find('blue button');
|
|
250
|
+
console.log('Button text:', button.text); // "Submit"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### label
|
|
254
|
+
|
|
255
|
+
Accessible label or name of the element (if available). Useful for verifying accessibility.
|
|
256
|
+
|
|
257
|
+
```javascript
|
|
258
|
+
element.label
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Returns:** `string | null` - Accessible label
|
|
262
|
+
|
|
263
|
+
**Example:**
|
|
264
|
+
```javascript
|
|
265
|
+
const input = await testdriver.find('first input field');
|
|
266
|
+
|
|
267
|
+
if (input.label) {
|
|
268
|
+
console.log('Input label:', input.label); // "Email Address"
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### confidence
|
|
273
|
+
|
|
274
|
+
AI confidence score for the element match (0-1, where 1 is perfect confidence).
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
element.confidence
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Returns:** `number | null` - Confidence score between 0 and 1
|
|
281
|
+
|
|
282
|
+
**Example:**
|
|
283
|
+
```javascript
|
|
284
|
+
const element = await testdriver.find('submit button');
|
|
285
|
+
|
|
286
|
+
if (element.confidence !== null) {
|
|
287
|
+
const percentage = (element.confidence * 100).toFixed(1);
|
|
288
|
+
console.log(`Match confidence: ${percentage}%`);
|
|
289
|
+
|
|
290
|
+
if (element.confidence < 0.8) {
|
|
291
|
+
console.warn('⚠️ Low confidence match - element might not be correct');
|
|
292
|
+
} else if (element.confidence > 0.95) {
|
|
293
|
+
console.log('✅ High confidence match');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
<Tip>
|
|
299
|
+
Confidence scores below 0.8 may indicate the element description was ambiguous or the wrong element was found.
|
|
300
|
+
</Tip>
|
|
301
|
+
|
|
302
|
+
### Property Availability
|
|
303
|
+
|
|
304
|
+
| Property | When Available |
|
|
305
|
+
|----------|---------------|
|
|
306
|
+
| `x`, `y`, `centerX`, `centerY` | ✅ Always after successful `find()` |
|
|
307
|
+
| `coordinates` | ✅ Always after successful `find()` |
|
|
308
|
+
| `width`, `height` | ⚠️ When AI detects element bounds |
|
|
309
|
+
| `boundingBox` | ⚠️ When AI detects element bounds |
|
|
310
|
+
| `text` | ⚠️ When AI extracts text content |
|
|
311
|
+
| `label` | ⚠️ When element has accessible label |
|
|
312
|
+
| `confidence` | ✅ Always after AI element finding |
|
|
313
|
+
| `screenshot` | ⚠️ Only in DEBUG mode or on errors |
|
|
314
|
+
|
|
315
|
+
<Note>
|
|
316
|
+
Properties marked with ⚠️ may be `null` depending on what the AI could detect from the screenshot.
|
|
317
|
+
</Note>
|
|
318
|
+
|
|
319
|
+
## JSON Serialization
|
|
320
|
+
|
|
321
|
+
Element objects can be safely serialized using `JSON.stringify()` for logging, debugging, and data storage. Circular references are automatically removed:
|
|
322
|
+
|
|
323
|
+
```javascript
|
|
324
|
+
const element = await testdriver.find('login button');
|
|
325
|
+
|
|
326
|
+
// Safe to stringify - no circular reference errors!
|
|
327
|
+
console.log(JSON.stringify(element, null, 2));
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**Serialized output includes:**
|
|
331
|
+
|
|
332
|
+
```json
|
|
333
|
+
{
|
|
334
|
+
"description": "login button",
|
|
335
|
+
"coordinates": { "x": 100, "y": 200, "centerX": 150, "centerY": 225 },
|
|
336
|
+
"found": true,
|
|
337
|
+
"threshold": 0.01,
|
|
338
|
+
"x": 100,
|
|
339
|
+
"y": 200,
|
|
340
|
+
"cache": {
|
|
341
|
+
"hit": true,
|
|
342
|
+
"strategy": "pixel-diff",
|
|
343
|
+
"createdAt": "2025-12-09T10:30:00.000Z",
|
|
344
|
+
"diffPercent": 0.0023,
|
|
345
|
+
"imageUrl": "https://cache.testdriver.ai/..."
|
|
346
|
+
},
|
|
347
|
+
"similarity": 0.98,
|
|
348
|
+
"confidence": 0.95,
|
|
349
|
+
"selector": "button#login",
|
|
350
|
+
"aiResponse": "Found the blue login button in the center of the form..."
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Serialized properties:**
|
|
355
|
+
|
|
356
|
+
| Property | Type | Description |
|
|
357
|
+
|----------|------|-------------|
|
|
358
|
+
| `description` | string | Element search description |
|
|
359
|
+
| `coordinates` | object | Full coordinate object `{x, y, centerX, centerY}` |
|
|
360
|
+
| `found` | boolean | Whether element was located |
|
|
361
|
+
| `threshold` | number | Cache threshold used for this find |
|
|
362
|
+
| `x`, `y` | number | Top-left coordinates |
|
|
363
|
+
| `cache.hit` | boolean | Whether cache was used |
|
|
364
|
+
| `cache.strategy` | string | Cache strategy (e.g., "pixel-diff") |
|
|
365
|
+
| `cache.createdAt` | string | ISO timestamp when cache was created |
|
|
366
|
+
| `cache.diffPercent` | number | Pixel difference from cached image |
|
|
367
|
+
| `cache.imageUrl` | string | URL to cached screenshot |
|
|
368
|
+
| `similarity` | number | Similarity score (0-1) |
|
|
369
|
+
| `confidence` | number | AI confidence score (0-1) |
|
|
370
|
+
| `selector` | string | CSS/XPath selector if available |
|
|
371
|
+
| `aiResponse` | string | AI's explanation of what it found |
|
|
372
|
+
|
|
373
|
+
**Use cases:**
|
|
374
|
+
|
|
375
|
+
```javascript
|
|
376
|
+
// Debugging element detection
|
|
377
|
+
const element = await testdriver.find('submit button');
|
|
378
|
+
if (!element.found()) {
|
|
379
|
+
console.error('Element not found:', JSON.stringify(element, null, 2));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Logging cache performance
|
|
383
|
+
const data = JSON.parse(JSON.stringify(element));
|
|
384
|
+
if (data.cache.hit) {
|
|
385
|
+
console.log(`Cache hit! Diff: ${(data.cache.diffPercent * 100).toFixed(2)}%`);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Sharing element data across processes
|
|
389
|
+
const elementData = JSON.stringify(element);
|
|
390
|
+
// Send to another process, log to file, etc.
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
<Tip>
|
|
394
|
+
Use JSON serialization when you need to log element data or when debugging why an element wasn't found. The serialized output excludes large binary data (screenshots) and circular references.
|
|
395
|
+
</Tip>
|
|
396
|
+
|
|
397
|
+
## Best Practices
|
|
398
|
+
|
|
399
|
+
<AccordionGroup>
|
|
400
|
+
<Accordion title="Be specific with descriptions">
|
|
401
|
+
Include visual details, position context, and nearby text:
|
|
402
|
+
|
|
403
|
+
```javascript
|
|
404
|
+
// ❌ Too vague
|
|
405
|
+
await testdriver.find('button');
|
|
406
|
+
|
|
407
|
+
// ✅ Specific
|
|
408
|
+
await testdriver.find('blue submit button below the email field');
|
|
409
|
+
```
|
|
410
|
+
</Accordion>
|
|
411
|
+
|
|
412
|
+
<Accordion title="Check if element was found">
|
|
413
|
+
Always verify elements were located before interacting:
|
|
414
|
+
|
|
415
|
+
```javascript
|
|
416
|
+
const element = await testdriver.find('submit button');
|
|
417
|
+
if (!element.found()) {
|
|
418
|
+
throw new Error('Submit button not found');
|
|
419
|
+
}
|
|
420
|
+
await element.click();
|
|
421
|
+
```
|
|
422
|
+
</Accordion>
|
|
423
|
+
</AccordionGroup>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
sidebarTitle: "
|
|
2
|
+
title: "Verifying Results"
|
|
3
|
+
sidebarTitle: "Verifying Results"
|
|
4
4
|
description: "Locate elements and verify app state with AI-powered assertions"
|
|
5
5
|
icon: "circle-check"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
After a test runs, make sure that the app did the correct thing. Validation has two parts: to find the elements that you want to check, and to make assertions about the state of your app. TestDriver uses the AI as a judge. It returns a boolean and the reason. This shows if your app is in the correct state.
|
|
9
9
|
|
|
10
10
|
## Locating Elements
|
|
11
11
|
|
|
12
12
|
### Locating Single Elements
|
|
13
13
|
|
|
14
|
-
Use natural language to describe elements.
|
|
14
|
+
Use natural language to describe elements. A description must be specific enough to find the element. But it must not be so specific that it breaks with small UI changes. For example:
|
|
15
15
|
|
|
16
16
|
```javascript
|
|
17
17
|
await testdriver.find('email input field');
|
|
@@ -19,11 +19,11 @@ await testdriver.find('first product card in the grid');
|
|
|
19
19
|
await testdriver.find('dropdown menu labeled "Country"');
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
<Info>TestDriver
|
|
22
|
+
<Info>TestDriver caches the found elements for better performance on later calls. Read more about [element caching here](/caching).</Info>
|
|
23
23
|
|
|
24
24
|
### Debugging Found Elements
|
|
25
25
|
|
|
26
|
-
After
|
|
26
|
+
After TestDriver finds an element, you can look at its properties for debug:
|
|
27
27
|
|
|
28
28
|
```javascript
|
|
29
29
|
const button = await testdriver.find('submit button');
|
|
@@ -104,6 +104,6 @@ await testdriver.assert('form has red border');
|
|
|
104
104
|
|
|
105
105
|
## Next
|
|
106
106
|
|
|
107
|
-
<Card title="Adapt" icon="arrows-rotate" href="/
|
|
107
|
+
<Card title="Adapt" icon="arrows-rotate" href="/performing-actions">
|
|
108
108
|
Drive your app forward by performing actions on the elements you've located and validated.
|
|
109
109
|
</Card>
|
|
@@ -6,7 +6,7 @@ icon: "arrow-pointer"
|
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
9
|
-
The `mouseDown()` method
|
|
9
|
+
The `mouseDown()` method pushes the mouse button at the location of an element. It does not release the button. Use this for drag operations, custom gestures, or when you need precise control of the mouse events. You can call it on an [`Element`](/core-concepts/elements) instance. Or you can use it with a selector.
|
|
10
10
|
|
|
11
11
|
## Syntax
|
|
12
12
|
|
|
@@ -30,7 +30,7 @@ When called directly on the AI client:
|
|
|
30
30
|
|
|
31
31
|
## Returns
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
It returns a `Promise<void>`. The promise resolves when TestDriver pushes the mouse button.
|
|
34
34
|
|
|
35
35
|
## Examples
|
|
36
36
|
|
|
@@ -147,15 +147,15 @@ test('resizes panel', async () => {
|
|
|
147
147
|
|
|
148
148
|
## Important Notes
|
|
149
149
|
|
|
150
|
-
- Always pair `mouseDown()` with [`mouseUp()`](/
|
|
150
|
+
- Always pair `mouseDown()` with [`mouseUp()`](/mouse-up) to complete the gesture
|
|
151
151
|
- The mouse button remains pressed until `mouseUp()` is called
|
|
152
|
-
- Use [`hover()`](/
|
|
152
|
+
- Use [`hover()`](/hover) to move the mouse while the button is pressed
|
|
153
153
|
- For simple drag operations, consider using `ai()` with a natural language description like `"drag file to folder"`
|
|
154
154
|
|
|
155
155
|
## Related Methods
|
|
156
156
|
|
|
157
|
-
- [`mouseUp()`](/
|
|
158
|
-
- [`hover()`](/
|
|
159
|
-
- [`click()`](/
|
|
160
|
-
- [`doubleClick()`](/
|
|
161
|
-
- [`rightClick()`](/
|
|
157
|
+
- [`mouseUp()`](/mouse-up) - Release the mouse button
|
|
158
|
+
- [`hover()`](/hover) - Move mouse to element
|
|
159
|
+
- [`click()`](/click) - Full click (mouseDown + mouseUp)
|
|
160
|
+
- [`doubleClick()`](/double-click) - Double-click on element
|
|
161
|
+
- [`rightClick()`](/right-click) - Right-click for context menu
|
|
@@ -6,7 +6,7 @@ icon: "arrow-pointer"
|
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
9
|
-
The `mouseUp()` method releases the mouse button
|
|
9
|
+
The `mouseUp()` method releases the mouse button. It completes a drag operation or a custom mouse gesture that you started with [`mouseDown()`](/mouse-down). Call it without parameters to release the button at the present mouse position.
|
|
10
10
|
|
|
11
11
|
## Syntax
|
|
12
12
|
|
|
@@ -21,7 +21,7 @@ None. The mouse button is released at the current cursor position.
|
|
|
21
21
|
|
|
22
22
|
## Returns
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
It returns a `Promise<void>`. The promise resolves when TestDriver releases the mouse button.
|
|
25
25
|
|
|
26
26
|
## Examples
|
|
27
27
|
|
|
@@ -150,15 +150,15 @@ test('selects text with mouse drag', async () => {
|
|
|
150
150
|
|
|
151
151
|
## Important Notes
|
|
152
152
|
|
|
153
|
-
- `mouseUp()` must be preceded by [`mouseDown()`](/
|
|
153
|
+
- `mouseUp()` must be preceded by [`mouseDown()`](/mouse-down) to have an effect
|
|
154
154
|
- Releases the button at the current cursor position
|
|
155
155
|
- Completes any drag or selection operation that was in progress
|
|
156
|
-
- For simple clicks, use [`click()`](/
|
|
156
|
+
- For simple clicks, use [`click()`](/click) instead of mouseDown/mouseUp pair
|
|
157
157
|
|
|
158
158
|
## Related Methods
|
|
159
159
|
|
|
160
|
-
- [`mouseDown()`](/
|
|
161
|
-
- [`hover()`](/
|
|
162
|
-
- [`click()`](/
|
|
163
|
-
- [`doubleClick()`](/
|
|
164
|
-
- [`rightClick()`](/
|
|
160
|
+
- [`mouseDown()`](/mouse-down) - Press mouse button without releasing
|
|
161
|
+
- [`hover()`](/hover) - Move mouse to element
|
|
162
|
+
- [`click()`](/click) - Complete click (mouseDown + mouseUp)
|
|
163
|
+
- [`doubleClick()`](/double-click) - Double-click on element
|
|
164
|
+
- [`rightClick()`](/right-click) - Right-click for context menu
|