@testdriverai/agent 7.11.240-test → 7.11.241-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-agent/SKILL.md +174 -91
- package/ai/skills/testdriver-assert/SKILL.md +73 -269
- package/ai/skills/testdriver-aws-setup/SKILL.md +194 -312
- package/ai/skills/testdriver-bring-your-own-machine/SKILL.md +137 -204
- package/ai/skills/testdriver-cache/SKILL.md +142 -149
- package/ai/skills/testdriver-caching/SKILL.md +97 -87
- package/ai/skills/testdriver-captcha/SKILL.md +126 -111
- package/ai/skills/testdriver-ci-cd/SKILL.md +153 -542
- package/ai/skills/testdriver-click/SKILL.md +74 -229
- package/ai/skills/testdriver-client/SKILL.md +175 -229
- package/ai/skills/testdriver-customizing-devices/SKILL.md +72 -250
- package/ai/skills/testdriver-dashcam/SKILL.md +71 -404
- package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +103 -369
- package/ai/skills/testdriver-double-click/SKILL.md +46 -67
- package/ai/skills/testdriver-errors/SKILL.md +102 -176
- package/ai/skills/testdriver-events/SKILL.md +170 -327
- package/ai/skills/testdriver-exec/SKILL.md +92 -256
- package/ai/skills/testdriver-extract/SKILL.md +69 -170
- package/ai/skills/testdriver-find/SKILL.md +140 -736
- package/ai/skills/testdriver-focus-application/SKILL.md +69 -246
- package/ai/skills/testdriver-generating-tests/SKILL.md +102 -136
- package/ai/skills/testdriver-hosted/SKILL.md +79 -143
- package/ai/skills/testdriver-hover/SKILL.md +62 -235
- package/ai/skills/testdriver-locating-elements/SKILL.md +71 -366
- package/ai/skills/testdriver-making-assertions/SKILL.md +114 -72
- package/ai/skills/testdriver-mcp-setup/SKILL.md +79 -62
- package/ai/skills/testdriver-mouse-down/SKILL.md +46 -124
- package/ai/skills/testdriver-mouse-up/SKILL.md +45 -128
- package/ai/skills/testdriver-options/SKILL.md +73 -46
- package/ai/skills/testdriver-parse/SKILL.md +95 -184
- package/ai/skills/testdriver-performing-actions/SKILL.md +101 -91
- package/ai/skills/testdriver-press-keys/SKILL.md +59 -299
- package/ai/skills/testdriver-provision/SKILL.md +135 -179
- package/ai/skills/testdriver-quickstart/SKILL.md +24 -8
- package/ai/skills/testdriver-quickstart-claude/SKILL.md +84 -0
- package/ai/skills/testdriver-quickstart-github/SKILL.md +62 -32
- package/ai/skills/testdriver-quickstart-manual/SKILL.md +59 -32
- package/ai/skills/testdriver-quickstart-vscode/SKILL.md +96 -0
- package/ai/skills/testdriver-redraw/SKILL.md +100 -164
- package/ai/skills/testdriver-reusable-code/SKILL.md +95 -199
- package/ai/skills/testdriver-right-click/SKILL.md +45 -88
- package/ai/skills/testdriver-screenshot/SKILL.md +47 -201
- package/ai/skills/testdriver-screenshots/SKILL.md +86 -136
- package/ai/skills/testdriver-scroll/SKILL.md +71 -154
- package/ai/skills/testdriver-secrets/SKILL.md +94 -90
- package/ai/skills/testdriver-self-hosted/SKILL.md +82 -140
- package/ai/skills/testdriver-test-results-json/SKILL.md +165 -202
- package/ai/skills/testdriver-type/SKILL.md +56 -304
- package/ai/skills/testdriver-variables/SKILL.md +119 -80
- package/ai/skills/testdriver-wait/SKILL.md +31 -29
- package/ai/skills/testdriver-what-is-testdriver/SKILL.md +80 -32
- package/package.json +1 -1
|
@@ -1,102 +1,81 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: testdriver:double-click
|
|
3
|
-
description:
|
|
3
|
+
description: Double-click an element you found, for example to open a file or select a word.
|
|
4
4
|
---
|
|
5
5
|
<!-- Generated from double-click.mdx. DO NOT EDIT. -->
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
The `doubleClick()` method does a double-click action on an element. You can call it on an [`Element`](/core-concepts/elements) instance. Or you can use it with a selector.
|
|
10
|
-
|
|
11
|
-
## Syntax
|
|
7
|
+
Double-click an element you've located with [`find()`](/find):
|
|
12
8
|
|
|
13
9
|
```javascript
|
|
14
|
-
|
|
15
|
-
await element.doubleClick();
|
|
16
|
-
|
|
17
|
-
// Double-click using a selector
|
|
18
|
-
await ai.doubleClick('selector');
|
|
10
|
+
await testdriver.find('report.pdf in the file list').doubleClick();
|
|
19
11
|
```
|
|
20
12
|
|
|
21
|
-
##
|
|
13
|
+
## element.doubleClick()
|
|
22
14
|
|
|
23
|
-
|
|
15
|
+
Double-clicks the element at the point where `find()` located it. It's the same as `element.click('double-click')`.
|
|
24
16
|
|
|
25
|
-
|
|
17
|
+
```typescript
|
|
18
|
+
element.doubleClick(): Promise<void>
|
|
19
|
+
```
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|-----------|------|-------------|
|
|
29
|
-
| `selector` | `string` | The selector describing the element to double-click |
|
|
21
|
+
It takes no parameters.
|
|
30
22
|
|
|
31
|
-
|
|
23
|
+
### Errors
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
Throws an `ElementNotFoundError` if `find()` didn't locate the element. See [click()](/click#errors) for how to check `found()` first.
|
|
34
26
|
|
|
35
|
-
##
|
|
27
|
+
## Double-click at coordinates
|
|
36
28
|
|
|
37
|
-
|
|
29
|
+
The client has no `doubleClick()` method. To double-click a point on the screen, pass `action: 'double-click'` to [`testdriver.click()`](/click#testdriver-click-options):
|
|
38
30
|
|
|
39
31
|
```javascript
|
|
40
|
-
|
|
41
|
-
await fileItem.doubleClick();
|
|
32
|
+
await testdriver.click({ x: 640, y: 360, action: 'double-click' });
|
|
42
33
|
```
|
|
43
34
|
|
|
44
|
-
|
|
35
|
+
Prefer `element.doubleClick()`, which keeps working when the layout or screen size changes.
|
|
45
36
|
|
|
46
|
-
|
|
47
|
-
await ai.doubleClick('README.md in the file list');
|
|
48
|
-
```
|
|
37
|
+
## Examples
|
|
49
38
|
|
|
50
|
-
###
|
|
39
|
+
### Open a file in VS Code
|
|
51
40
|
|
|
52
41
|
```javascript
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
test('opens a file by double-clicking', async () => {
|
|
57
|
-
const { ai } = await vscode();
|
|
58
|
-
|
|
59
|
-
// Double-click to open a file in the explorer
|
|
60
|
-
await ai.doubleClick('package.json in the file explorer');
|
|
61
|
-
|
|
62
|
-
// Verify the file opened
|
|
63
|
-
const editor = await ai.find('text editor showing package.json');
|
|
64
|
-
expect(editor).toBeTruthy();
|
|
65
|
-
});
|
|
42
|
+
await testdriver.find('package.json in the Explorer sidebar').doubleClick();
|
|
43
|
+
await testdriver.assert('package.json is open in the editor');
|
|
66
44
|
```
|
|
67
45
|
|
|
68
|
-
###
|
|
46
|
+
### Select a word
|
|
69
47
|
|
|
70
48
|
```javascript
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
test('navigates folders in Google Drive', async () => {
|
|
75
|
-
const { ai } = await chrome('https://drive.google.com');
|
|
76
|
-
|
|
77
|
-
// Double-click to open a folder
|
|
78
|
-
await ai.doubleClick('Documents folder');
|
|
79
|
-
|
|
80
|
-
// Wait for folder to open
|
|
81
|
-
await ai.find('breadcrumb showing Documents');
|
|
82
|
-
});
|
|
49
|
+
await testdriver.find('the word "Checkout" in the page heading').doubleClick();
|
|
50
|
+
await testdriver.pressKeys(['ctrl', 'c']);
|
|
83
51
|
```
|
|
84
52
|
|
|
85
|
-
|
|
53
|
+
## Complete example
|
|
86
54
|
|
|
87
|
-
```javascript
|
|
88
|
-
|
|
89
|
-
|
|
55
|
+
```javascript tests/open-file.test.mjs
|
|
56
|
+
import { describe, expect, it } from 'vitest';
|
|
57
|
+
import { TestDriver } from 'testdriverai/vitest/hooks';
|
|
90
58
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
59
|
+
describe('VS Code', () => {
|
|
60
|
+
it('opens a file from the Explorer', async (context) => {
|
|
61
|
+
const testdriver = TestDriver(context);
|
|
62
|
+
await testdriver.exec({
|
|
63
|
+
language: 'sh',
|
|
64
|
+
code: 'mkdir -p /tmp/my-project && echo "{}" > /tmp/my-project/package.json',
|
|
65
|
+
});
|
|
66
|
+
await testdriver.provision.vscode({ workspace: '/tmp/my-project' });
|
|
67
|
+
|
|
68
|
+
await testdriver.find('package.json in the Explorer sidebar').doubleClick();
|
|
69
|
+
|
|
70
|
+
const result = await testdriver.assert('package.json is open in the editor');
|
|
71
|
+
expect(result).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
94
74
|
```
|
|
95
75
|
|
|
96
|
-
## Related
|
|
76
|
+
## Related
|
|
97
77
|
|
|
98
|
-
- [
|
|
99
|
-
- [
|
|
100
|
-
- [
|
|
101
|
-
- [
|
|
102
|
-
- [`hover()`](/hover) - Move mouse over element without clicking
|
|
78
|
+
- [click()](/click): single clicks, and clicks at coordinates
|
|
79
|
+
- [rightClick()](/right-click): open a context menu
|
|
80
|
+
- [find()](/find): locate the element to double-click
|
|
81
|
+
- [Perform actions](/performing-actions): every kind of action in one guide
|
|
@@ -1,246 +1,172 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: testdriver:errors
|
|
3
|
-
description:
|
|
3
|
+
description: The errors TestDriver throws, what they contain, and how to catch them.
|
|
4
4
|
---
|
|
5
5
|
<!-- Generated from errors.mdx. DO NOT EDIT. -->
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
TestDriver gives custom error classes with full debug information. The SDK exports them. You can use them for `instanceof` checks in your tests.
|
|
7
|
+
TestDriver exports two error classes you can check with `instanceof`:
|
|
10
8
|
|
|
11
9
|
```javascript
|
|
12
|
-
import
|
|
10
|
+
import { ElementNotFoundError, AIError } from 'testdriverai';
|
|
13
11
|
```
|
|
14
12
|
|
|
13
|
+
- [`ElementNotFoundError`](#elementnotfounderror): you acted on an element that `find()` didn't locate.
|
|
14
|
+
- [`AIError`](#aierror): an `ai()` task failed.
|
|
15
|
+
|
|
16
|
+
Other failures, such as a failed assertion, throw a plain `Error` with a recognizable message. See [Other errors](#other-errors).
|
|
17
|
+
|
|
15
18
|
## ElementNotFoundError
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
Thrown when you call an action on an element that [`find()`](/find) didn't locate:
|
|
21
|
+
|
|
22
|
+
- `click()`, `doubleClick()`, `rightClick()`
|
|
23
|
+
- `hover()`
|
|
24
|
+
- `mouseDown()`, `mouseUp()`
|
|
25
|
+
|
|
26
|
+
`find()` itself doesn't throw when nothing matches. It returns an element whose `found()` is `false`. Check `found()` when the element might not be there:
|
|
18
27
|
|
|
19
28
|
```javascript
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (error instanceof ElementNotFoundError) {
|
|
24
|
-
console.log(error.description); // "nonexistent button"
|
|
25
|
-
console.log(error.screenshotPath); // path to debug screenshot
|
|
26
|
-
console.log(error.pixelDiffPath); // path to pixel diff image
|
|
27
|
-
}
|
|
29
|
+
const cookieBanner = await testdriver.find('Cookie consent banner', { timeout: 0 });
|
|
30
|
+
if (cookieBanner.found()) {
|
|
31
|
+
await testdriver.find('Accept all cookies button').click();
|
|
28
32
|
}
|
|
29
33
|
```
|
|
30
34
|
|
|
31
35
|
### Properties
|
|
32
36
|
|
|
33
|
-
<
|
|
37
|
+
<ResponseField name="name" type="string">
|
|
34
38
|
Always `"ElementNotFoundError"`.
|
|
35
|
-
</
|
|
39
|
+
</ResponseField>
|
|
36
40
|
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
</
|
|
41
|
+
<ResponseField name="description" type="string">
|
|
42
|
+
The description you passed to `find()`.
|
|
43
|
+
</ResponseField>
|
|
40
44
|
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
</
|
|
45
|
+
<ResponseField name="message" type="string">
|
|
46
|
+
Says which element wasn't found, followed by a debug block. See below.
|
|
47
|
+
</ResponseField>
|
|
44
48
|
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
</
|
|
49
|
+
<ResponseField name="aiResponse" type="object | null">
|
|
50
|
+
The response from the `find()` call, with screenshots and other large images removed. Includes fields such as `cacheHit`, `similarity`, and `reasoning` when the API returned them.
|
|
51
|
+
</ResponseField>
|
|
48
52
|
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
</
|
|
53
|
+
<ResponseField name="timestamp" type="string">
|
|
54
|
+
When the error was created, as an ISO 8601 string.
|
|
55
|
+
</ResponseField>
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
URL to the cached image that was compared against.
|
|
55
|
-
</ParamField>
|
|
57
|
+
### Message
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
Sanitized AI response object. Large binary fields (`croppedImage`, `screenshot`, `pixelDiffImage`) are removed. Contains cache metadata like `similarity`, `cacheHit`, `cacheStrategy`, `cacheDiffPercent`, and `threshold`.
|
|
59
|
-
</ParamField>
|
|
59
|
+
The message starts with the element's description, then adds what TestDriver knows about the failed `find()`:
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
</ParamField>
|
|
61
|
+
```text
|
|
62
|
+
Element "Sign in button" not found.
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
=== Debug Information ===
|
|
65
|
+
Element searched for: "Sign in button"
|
|
66
|
+
Cache: MISS
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
```
|
|
70
|
-
Element not found: "submit button"
|
|
71
|
-
|
|
72
|
-
=== Element Debug Info ===
|
|
73
|
-
Element: submit button
|
|
74
|
-
Cache Hit: false
|
|
75
|
-
Similarity: 0.23
|
|
76
|
-
Cache Strategy: pixel-diff
|
|
77
|
-
Threshold: 0.05
|
|
78
|
-
AI Response Element: null
|
|
68
|
+
AI Response:
|
|
69
|
+
The page shows a loading spinner. There is no sign in button yet.
|
|
79
70
|
```
|
|
80
71
|
|
|
81
|
-
|
|
72
|
+
Depending on the `find()` call, the debug block can also include:
|
|
82
73
|
|
|
83
|
-
|
|
74
|
+
- The cache threshold and the required similarity.
|
|
75
|
+
- When the cache was hit: the cache strategy, the entry's age, and the pixel difference.
|
|
76
|
+
- The similarity score, marked `(below threshold)` when it's too low.
|
|
77
|
+
|
|
78
|
+
The stack trace starts at your test code, not inside the SDK.
|
|
84
79
|
|
|
85
80
|
## AIError
|
|
86
81
|
|
|
87
|
-
Thrown when `
|
|
82
|
+
Thrown when a task you give to `ai()` fails:
|
|
88
83
|
|
|
89
84
|
```javascript
|
|
85
|
+
import { AIError } from 'testdriverai';
|
|
86
|
+
|
|
90
87
|
try {
|
|
91
|
-
await testdriver.
|
|
88
|
+
await testdriver.ai('Add the blue T-shirt to the cart', { tries: 3 });
|
|
92
89
|
} catch (error) {
|
|
93
90
|
if (error instanceof AIError) {
|
|
94
|
-
console.log(error.
|
|
95
|
-
console.log(error.
|
|
96
|
-
console.log(error.duration); // 15234 (ms)
|
|
97
|
-
console.log(error.cause); // underlying Error
|
|
91
|
+
console.log(`Stopped after ${error.tries} of ${error.maxTries} tries`);
|
|
92
|
+
console.log(error.cause?.message); // the error that stopped the task
|
|
98
93
|
}
|
|
94
|
+
throw error;
|
|
99
95
|
}
|
|
100
96
|
```
|
|
101
97
|
|
|
98
|
+
`act()` is the same method under another name and throws the same error.
|
|
99
|
+
|
|
102
100
|
### Properties
|
|
103
101
|
|
|
104
|
-
<
|
|
102
|
+
<ResponseField name="name" type="string">
|
|
105
103
|
Always `"AIError"`.
|
|
106
|
-
</
|
|
104
|
+
</ResponseField>
|
|
107
105
|
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
</
|
|
106
|
+
<ResponseField name="task" type="string">
|
|
107
|
+
The task you passed to `ai()`.
|
|
108
|
+
</ResponseField>
|
|
111
109
|
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
</
|
|
110
|
+
<ResponseField name="tries" type="number">
|
|
111
|
+
How many check attempts were made.
|
|
112
|
+
</ResponseField>
|
|
115
113
|
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
</
|
|
114
|
+
<ResponseField name="maxTries" type="number">
|
|
115
|
+
The `tries` limit for the call. Defaults to `7`.
|
|
116
|
+
</ResponseField>
|
|
119
117
|
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
</
|
|
118
|
+
<ResponseField name="duration" type="number">
|
|
119
|
+
How long the task ran, in milliseconds.
|
|
120
|
+
</ResponseField>
|
|
123
121
|
|
|
124
|
-
<
|
|
125
|
-
|
|
126
|
-
</
|
|
122
|
+
<ResponseField name="cause" type="Error">
|
|
123
|
+
The error that stopped the task.
|
|
124
|
+
</ResponseField>
|
|
127
125
|
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
</
|
|
126
|
+
<ResponseField name="timestamp" type="string">
|
|
127
|
+
When the error was created, as an ISO 8601 string.
|
|
128
|
+
</ResponseField>
|
|
131
129
|
|
|
132
|
-
|
|
133
|
-
ISO 8601 timestamp of when the error was created.
|
|
134
|
-
</ParamField>
|
|
130
|
+
### Message
|
|
135
131
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
```
|
|
139
|
-
AI failed: Element not found after 3 attempts
|
|
132
|
+
```text
|
|
133
|
+
AI failed: <the cause's message>
|
|
140
134
|
|
|
141
135
|
=== AI Execution Details ===
|
|
142
|
-
Task:
|
|
143
|
-
Tries: 3
|
|
144
|
-
Duration:
|
|
145
|
-
|
|
136
|
+
Task: "Add the blue T-shirt to the cart"
|
|
137
|
+
Tries: 3/3
|
|
138
|
+
Duration: 41250ms
|
|
139
|
+
Timestamp: 2026-10-21T14:30:00.000Z
|
|
140
|
+
Underlying error: <the cause's message>
|
|
146
141
|
```
|
|
147
142
|
|
|
148
|
-
##
|
|
149
|
-
|
|
150
|
-
These errors are used internally by the agent and are not exported, but may appear as the `cause` of an `AIError`:
|
|
151
|
-
|
|
152
|
-
### MatchError
|
|
153
|
-
|
|
154
|
-
Thrown when element matching fails (text, image, or assertion).
|
|
155
|
-
|
|
156
|
-
| Property | Type | Description |
|
|
157
|
-
|---|---|---|
|
|
158
|
-
| `fatal` | `boolean` | If `true`, cannot be healed. Default: `false` |
|
|
159
|
-
| `attachScreenshot` | `boolean` | Always `true` — a screenshot is attached to the error |
|
|
160
|
-
|
|
161
|
-
### CommandError
|
|
143
|
+
## Other errors
|
|
162
144
|
|
|
163
|
-
|
|
145
|
+
These failures throw an error whose class isn't exported. Check the message instead.
|
|
164
146
|
|
|
165
|
-
|
|
|
166
|
-
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
|
|
170
|
-
## Soft Assert Mode
|
|
171
|
-
|
|
172
|
-
Inside `act()`, assertions run in **soft assert mode**. When an assertion fails, it returns the failure result instead of throwing, allowing the AI to process the failure and adjust its approach.
|
|
173
|
-
|
|
174
|
-
```javascript
|
|
175
|
-
// Inside act(), assertion failures don't throw
|
|
176
|
-
await testdriver.act('verify the dashboard shows correct data', {
|
|
177
|
-
tries: 3,
|
|
178
|
-
});
|
|
179
|
-
// The AI can see assertion results and self-correct
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
This is automatic — you don't need to configure it. Regular `assert()` calls outside of `act()` will throw normally on failure.
|
|
183
|
-
|
|
184
|
-
## Error Handling Patterns
|
|
185
|
-
|
|
186
|
-
### Catching Specific Errors
|
|
147
|
+
| What failed | Message starts with |
|
|
148
|
+
| --- | --- |
|
|
149
|
+
| [`assert()`](/assert) | `AI Assertion failed:` followed by the assertion and the AI's explanation |
|
|
150
|
+
| [`exec()`](/exec) with `sh` or `pwsh`, when the command exits non-zero | `Command failed with exit code <code>:` followed by stderr |
|
|
187
151
|
|
|
188
152
|
```javascript
|
|
189
|
-
import TestDriver, { ElementNotFoundError, AIError } from 'testdriverai';
|
|
190
|
-
|
|
191
153
|
try {
|
|
192
|
-
await testdriver.
|
|
154
|
+
await testdriver.assert('the cart shows 2 items');
|
|
193
155
|
} catch (error) {
|
|
194
|
-
if (error
|
|
195
|
-
//
|
|
196
|
-
console.log('Debug screenshot:', error.screenshotPath);
|
|
197
|
-
} else if (error instanceof AIError) {
|
|
198
|
-
// AI exhausted retries
|
|
199
|
-
console.log(`Failed after ${error.tries} tries in ${error.duration}ms`);
|
|
200
|
-
} else {
|
|
201
|
-
throw error; // Unexpected error
|
|
156
|
+
if (error.message.startsWith('AI Assertion failed:')) {
|
|
157
|
+
// The assertion didn't hold
|
|
202
158
|
}
|
|
159
|
+
throw error;
|
|
203
160
|
}
|
|
204
161
|
```
|
|
205
162
|
|
|
206
|
-
|
|
163
|
+
<Note>
|
|
164
|
+
Inside `ai()`, a failed `assert()` resolves to `false` instead of throwing, so the AI can see the result and try another approach.
|
|
165
|
+
</Note>
|
|
207
166
|
|
|
208
|
-
|
|
209
|
-
try {
|
|
210
|
-
const el = await testdriver.find('checkout button');
|
|
211
|
-
await el.click();
|
|
212
|
-
} catch (error) {
|
|
213
|
-
if (error instanceof ElementNotFoundError) {
|
|
214
|
-
// Screenshot of what the screen looked like
|
|
215
|
-
console.log('Screen:', error.screenshotPath);
|
|
216
|
-
// Pixel diff showing cache comparison
|
|
217
|
-
console.log('Diff:', error.pixelDiffPath);
|
|
218
|
-
// Full AI response metadata
|
|
219
|
-
console.log('AI:', JSON.stringify(error.aiResponse, null, 2));
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
```
|
|
167
|
+
## Related
|
|
223
168
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
name: 'ElementNotFoundError';
|
|
229
|
-
description: string;
|
|
230
|
-
screenshotPath: string | null;
|
|
231
|
-
pixelDiffPath: string | null;
|
|
232
|
-
cachedImagePath: string | null;
|
|
233
|
-
aiResponse: Record<string, any> | null;
|
|
234
|
-
timestamp: string;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
class AIError extends Error {
|
|
238
|
-
name: 'AIError';
|
|
239
|
-
task: string;
|
|
240
|
-
tries: number;
|
|
241
|
-
maxTries: number;
|
|
242
|
-
duration: number;
|
|
243
|
-
cause?: Error;
|
|
244
|
-
timestamp: string;
|
|
245
|
-
}
|
|
246
|
-
```
|
|
169
|
+
- [find()](/find): returns an element whose `found()` tells you whether it was located
|
|
170
|
+
- [assert()](/assert): check what's on screen
|
|
171
|
+
- [Debug a failing test](/debugging-with-screenshots): find out why a test failed
|
|
172
|
+
- [Events](/events): listen for errors as they happen
|