@testdriverai/agent 7.11.229-test → 7.11.231-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/docs/_data/examples-manifest.json +16 -16
- package/docs/_scripts/generate-examples.js +38 -45
- package/docs/agent.mdx +174 -93
- package/docs/assert.mdx +73 -269
- package/docs/aws-setup.mdx +196 -314
- package/docs/bring-your-own-machine.mdx +139 -206
- package/docs/cache.mdx +144 -151
- package/docs/caching.mdx +99 -89
- package/docs/captcha.mdx +126 -111
- package/docs/ci-cd.mdx +154 -543
- package/docs/click.mdx +74 -229
- package/docs/client.mdx +177 -231
- package/docs/copilot/auto-healing.mdx +86 -370
- package/docs/copilot/running-tests.mdx +121 -930
- package/docs/customizing-devices.mdx +74 -251
- package/docs/dashcam.mdx +72 -405
- package/docs/debugging-with-screenshots.mdx +105 -371
- package/docs/docs.json +75 -18
- package/docs/double-click.mdx +48 -68
- package/docs/errors.mdx +102 -176
- package/docs/events.mdx +170 -327
- package/docs/examples/{hover-text-with-description.mdx → add-to-cart.mdx} +30 -35
- package/docs/examples/assert.mdx +28 -41
- package/docs/examples/click-button.mdx +71 -0
- package/docs/examples/{hover-image.mdx → click-icon.mdx} +32 -28
- package/docs/examples/element-not-found.mdx +27 -26
- package/docs/examples/findall-coffee-icons.mdx +28 -32
- package/docs/examples/installer.mdx +61 -25
- package/docs/examples/launch-vscode-linux.mdx +28 -51
- package/docs/examples/navigate-and-scroll.mdx +82 -0
- package/docs/examples/parse.mdx +24 -28
- package/docs/examples/press-keys.mdx +28 -25
- package/docs/examples/scroll.mdx +25 -27
- package/docs/examples/type.mdx +26 -21
- package/docs/exec.mdx +92 -256
- package/docs/extract.mdx +69 -170
- package/docs/find.mdx +140 -736
- package/docs/focus-application.mdx +69 -246
- package/docs/generating-tests.mdx +103 -137
- package/docs/guide/best-practices-polling.mdx +65 -141
- package/docs/hosted.mdx +80 -144
- package/docs/hover.mdx +62 -235
- package/docs/locating-elements.mdx +74 -369
- package/docs/making-assertions.mdx +116 -74
- package/docs/mcp-setup.mdx +80 -63
- package/docs/mouse-down.mdx +48 -125
- package/docs/mouse-up.mdx +47 -129
- package/docs/options.mdx +75 -48
- package/docs/parse.mdx +95 -184
- package/docs/performing-actions.mdx +104 -94
- package/docs/press-keys.mdx +59 -299
- package/docs/provision.mdx +137 -182
- package/docs/quickstart-claude.mdx +85 -0
- package/docs/quickstart-github.mdx +62 -32
- package/docs/quickstart-manual.mdx +60 -33
- package/docs/quickstart-vscode.mdx +97 -0
- package/docs/quickstart.mdx +25 -9
- package/docs/redraw.mdx +101 -165
- package/docs/reusable-code.mdx +97 -200
- package/docs/right-click.mdx +47 -89
- package/docs/screenshot.mdx +47 -201
- package/docs/screenshots.mdx +87 -137
- package/docs/scroll.mdx +71 -154
- package/docs/secrets.mdx +96 -91
- package/docs/self-hosted.mdx +83 -142
- package/docs/snippets/enterprise.mdx +15 -0
- package/docs/styles.css +68 -0
- package/docs/test-results-json.mdx +167 -204
- package/docs/type.mdx +56 -304
- package/docs/variables.mdx +121 -81
- package/docs/wait.mdx +33 -31
- package/docs/what-is-testdriver.mdx +80 -32
- package/examples/{hover-text-with-description.test.mjs → add-to-cart.test.mjs} +4 -5
- package/examples/assert.test.mjs +3 -20
- package/examples/{hover-text.test.mjs → click-button.test.mjs} +3 -4
- package/examples/{hover-image.test.mjs → click-icon.test.mjs} +5 -6
- package/examples/element-not-found.test.mjs +3 -5
- package/examples/findall-coffee-icons.test.mjs +3 -3
- package/examples/installer.test.mjs +1 -1
- package/examples/launch-vscode-linux.test.mjs +6 -33
- package/examples/{scroll-keyboard.test.mjs → navigate-and-scroll.test.mjs} +4 -5
- package/examples/parse.test.mjs +1 -2
- package/examples/press-keys.test.mjs +4 -4
- package/examples/scroll.test.mjs +3 -6
- package/examples/type.test.mjs +5 -2
- package/lib/provision.js +6 -2
- package/package.json +1 -1
- package/sdk.d.ts +4 -2
- package/sdk.js +1 -1
- package/docs/claude-mcp-plugin.mdx +0 -244
- package/docs/elements.mdx +0 -606
- package/docs/examples/ai.mdx +0 -78
- package/docs/examples/captcha-api.mdx +0 -92
- package/docs/examples/chrome-extension.mdx +0 -156
- package/docs/examples/drag-and-drop.mdx +0 -100
- package/docs/examples/formatted-logging.mdx +0 -74
- package/docs/examples/hover-text.mdx +0 -70
- package/docs/examples/match-image.mdx +0 -97
- package/docs/examples/scroll-keyboard.mdx +0 -80
- package/docs/examples/scroll-until-text.mdx +0 -109
|
@@ -1,109 +1,151 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
sidebarTitle: "Verifying
|
|
4
|
-
description: "
|
|
2
|
+
title: "Make assertions"
|
|
3
|
+
sidebarTitle: "Verifying results"
|
|
4
|
+
description: "Check that your app reached the right state, in plain language or with expect()."
|
|
5
5
|
icon: "circle-check"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
An assertion checks that your app did the right thing after a step. TestDriver gives you two ways to check:
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
- [`assert()`](/assert) asks the AI whether a statement about the screen is true, and fails the test if it isn't.
|
|
11
|
+
- [`extract()`](/extract) reads a value off the screen, so you can compare it yourself with `expect()`.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
```javascript
|
|
14
|
+
await testdriver.find('Add to cart button').click();
|
|
15
|
+
await testdriver.assert('the cart icon shows 1 item');
|
|
16
|
+
```
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
## Check the screen with assert()
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
Pass `assert()` a statement that should be true. The AI looks at the current screen and decides.
|
|
21
|
+
|
|
22
|
+
```javascript tests/login.test.mjs
|
|
23
|
+
import { describe, it } from 'vitest';
|
|
24
|
+
import { TestDriver } from 'testdriverai/vitest/hooks';
|
|
25
|
+
|
|
26
|
+
describe('Login', () => {
|
|
27
|
+
it('signs in with valid credentials', async (context) => {
|
|
28
|
+
const testdriver = TestDriver(context);
|
|
29
|
+
await testdriver.provision.chrome({ url: 'https://testdriver-sandbox.vercel.app/login' });
|
|
30
|
+
|
|
31
|
+
// The sandbox login page shows its test password on screen
|
|
32
|
+
const password = await testdriver.extract('the password shown on the login page');
|
|
33
|
+
|
|
34
|
+
await testdriver.find('Username input field').click();
|
|
35
|
+
await testdriver.type('standard_user');
|
|
36
|
+
await testdriver.find('Password input field').click();
|
|
37
|
+
await testdriver.type(password, { secret: true });
|
|
38
|
+
await testdriver.find('Sign in button below the password field').click();
|
|
39
|
+
|
|
40
|
+
await testdriver.assert('the product list is shown');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
20
43
|
```
|
|
21
44
|
|
|
22
|
-
|
|
45
|
+
When the statement is true, `assert()` resolves to `true`. When it's false, `assert()` throws and the test fails at that line. The error message starts with `AI Assertion failed:` and includes the AI's explanation.
|
|
23
46
|
|
|
24
|
-
|
|
47
|
+
## Write statements the AI can judge
|
|
25
48
|
|
|
26
|
-
|
|
49
|
+
The AI judges only what's visible on screen right now. Write statements a person could confirm by looking.
|
|
50
|
+
|
|
51
|
+
- **Name the thing and its state.** `'the Submit button is disabled'`, not `'the form is invalid'`.
|
|
52
|
+
- **Quote exact text** when the wording matters: `'the banner says "Order placed"'`.
|
|
53
|
+
- **Check one thing per assertion.** Two short assertions tell you exactly which part failed.
|
|
54
|
+
- **Assert outcomes, not steps.** Check what the user should see after an action, such as a confirmation message.
|
|
27
55
|
|
|
28
56
|
```javascript
|
|
29
|
-
|
|
30
|
-
|
|
57
|
+
// Visibility
|
|
58
|
+
await testdriver.assert('the login form is visible');
|
|
59
|
+
await testdriver.assert('the loading spinner is not visible');
|
|
60
|
+
|
|
61
|
+
// Exact text
|
|
62
|
+
await testdriver.assert('the error message says "Invalid email address"');
|
|
63
|
+
|
|
64
|
+
// State of a control
|
|
65
|
+
await testdriver.assert('the "Remember me" checkbox is checked');
|
|
66
|
+
await testdriver.assert('the Country dropdown shows "United States"');
|
|
31
67
|
```
|
|
32
68
|
|
|
33
|
-
|
|
69
|
+
## Compare exact values with extract()
|
|
70
|
+
|
|
71
|
+
Use `extract()` when you need the value itself, for example a number to compare or reuse. It returns a string, so convert it before comparing numbers:
|
|
34
72
|
|
|
35
73
|
```javascript
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
y: 300,
|
|
41
|
-
coordinates: { x: 150, y: 300, centerX: 200, centerY: 320 },
|
|
42
|
-
threshold: 0.8,
|
|
43
|
-
confidence: 0.95,
|
|
44
|
-
similarity: 0.92,
|
|
45
|
-
selector: 'button[type="submit"]',
|
|
46
|
-
cache: {
|
|
47
|
-
hit: true,
|
|
48
|
-
strategy: 'pixel-diff',
|
|
49
|
-
createdAt: '2025-01-15T10:30:00Z',
|
|
50
|
-
diffPercent: 0.02,
|
|
51
|
-
imageUrl: 'https://...'
|
|
52
|
-
}
|
|
53
|
-
}
|
|
74
|
+
import { expect } from 'vitest';
|
|
75
|
+
|
|
76
|
+
const itemCount = await testdriver.extract('the number of items shown on the cart icon');
|
|
77
|
+
expect(Number(itemCount)).toBe(1);
|
|
54
78
|
```
|
|
55
79
|
|
|
56
|
-
|
|
80
|
+
Prefer `assert()` for yes-or-no checks. Reach for `extract()` when the test needs a value it can't know in advance, such as an order number:
|
|
57
81
|
|
|
58
|
-
|
|
82
|
+
```javascript
|
|
83
|
+
const orderNumber = await testdriver.extract('the order confirmation number');
|
|
84
|
+
expect(orderNumber).toMatch(/^A-\d+$/);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Check state before and after an action
|
|
88
|
+
|
|
89
|
+
An assertion after an action only proves the end state. Assert the starting state too, so the test catches an action that did nothing:
|
|
59
90
|
|
|
60
91
|
```javascript
|
|
61
|
-
|
|
62
|
-
const products = await testdriver.findAll('product card');
|
|
63
|
-
console.log(`Found ${products.length} products`);
|
|
92
|
+
await testdriver.assert('the cart is empty');
|
|
64
93
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
94
|
+
await testdriver.find('Add to cart button under the TestDriver Hat').click();
|
|
95
|
+
|
|
96
|
+
await testdriver.assert('the cart icon shows 1 item');
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
To check that a value changed, extract it on both sides of the action:
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
const before = await testdriver.extract('the cart total');
|
|
69
103
|
|
|
70
|
-
|
|
71
|
-
}
|
|
104
|
+
await testdriver.find('Add to cart button under the TestDriver Hat').click();
|
|
72
105
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
await firstProduct.click();
|
|
106
|
+
const after = await testdriver.extract('the cart total');
|
|
107
|
+
expect(after).not.toBe(before);
|
|
76
108
|
```
|
|
77
109
|
|
|
78
|
-
##
|
|
110
|
+
## Wait before you assert
|
|
79
111
|
|
|
80
|
-
|
|
112
|
+
`assert()` checks the screen once, at the moment you call it. If the result takes time to appear, wait for it with [`find()`](/find) first:
|
|
81
113
|
|
|
82
114
|
```javascript
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
await testdriver.
|
|
87
|
-
|
|
88
|
-
// Verify content
|
|
89
|
-
await testdriver.assert('page title is "Welcome"');
|
|
90
|
-
await testdriver.assert('success message says "Account created"');
|
|
91
|
-
await testdriver.assert('error message contains "Invalid email"');
|
|
92
|
-
|
|
93
|
-
// Verify state
|
|
94
|
-
await testdriver.assert('checkbox is checked');
|
|
95
|
-
await testdriver.assert('dropdown shows "United States"');
|
|
96
|
-
await testdriver.assert('button is disabled');
|
|
97
|
-
|
|
98
|
-
// Verify visual appearance
|
|
99
|
-
await testdriver.assert('submit button is blue');
|
|
100
|
-
await testdriver.assert('form has red border');
|
|
115
|
+
await testdriver.find('Place order button').click();
|
|
116
|
+
|
|
117
|
+
// Keep looking for up to 30 seconds while the confirmation page loads
|
|
118
|
+
await testdriver.find('Order confirmation heading', { timeout: 30000 });
|
|
119
|
+
await testdriver.assert('the confirmation shows an order number');
|
|
101
120
|
```
|
|
102
121
|
|
|
103
|
-
|
|
122
|
+
See [Perform actions](/performing-actions#wait-for-a-changing-ui) for other ways to wait.
|
|
123
|
+
|
|
124
|
+
## How assertions are cached
|
|
125
|
+
|
|
126
|
+
`assert()` results are [cached](/caching) like `find()` results. When the screen matches a passing earlier run, TestDriver reuses that result instead of asking the AI.
|
|
127
|
+
|
|
128
|
+
`extract()` is never cached. It reads the screen every time.
|
|
104
129
|
|
|
105
|
-
|
|
130
|
+
To always ask the AI for one assertion, pass `threshold: -1`:
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
await testdriver.assert('the clock shows the current time', { threshold: -1 });
|
|
134
|
+
```
|
|
106
135
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
136
|
+
## Next steps
|
|
137
|
+
|
|
138
|
+
<CardGroup cols={2}>
|
|
139
|
+
<Card title="assert()" icon="check-circle" href="/assert">
|
|
140
|
+
Every option, return value, and error.
|
|
141
|
+
</Card>
|
|
142
|
+
<Card title="extract()" icon="wand-magic-sparkles" href="/extract">
|
|
143
|
+
Read values off the screen as strings.
|
|
144
|
+
</Card>
|
|
145
|
+
<Card title="Perform actions" icon="arrow-pointer" href="/performing-actions">
|
|
146
|
+
Click, type, and wait for a changing UI.
|
|
147
|
+
</Card>
|
|
148
|
+
<Card title="Debug with screenshots" icon="bug" href="/debugging-with-screenshots">
|
|
149
|
+
See what the screen showed when an assertion failed.
|
|
150
|
+
</Card>
|
|
151
|
+
</CardGroup>
|
package/docs/mcp-setup.mdx
CHANGED
|
@@ -1,44 +1,49 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "MCP Setup"
|
|
3
|
-
sidebarTitle: "MCP
|
|
4
|
-
description: "Connect any
|
|
3
|
+
sidebarTitle: "MCP setup"
|
|
4
|
+
description: "Connect Claude, Cursor, VS Code, ChatGPT, or any MCP client to TestDriver with one URL."
|
|
5
5
|
icon: "plug"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Connect your AI client to TestDriver's hosted [Model Context Protocol](https://modelcontextprotocol.io) server, and you can drive a real sandbox from chat.
|
|
9
|
+
|
|
10
|
+
- Open your app.
|
|
11
|
+
- Find elements, click, type, and assert.
|
|
12
|
+
- Get a screenshot after every step.
|
|
13
|
+
|
|
14
|
+
There's nothing to install and no API key to copy. Add one URL and sign in through your browser:
|
|
9
15
|
|
|
10
16
|
```text
|
|
11
17
|
https://mcp.testdriver.ai/mcp
|
|
12
18
|
```
|
|
13
19
|
|
|
14
|
-
|
|
15
|
-
**Prerequisites**
|
|
20
|
+
## Before you begin
|
|
16
21
|
|
|
17
|
-
- An MCP
|
|
18
|
-
- A TestDriver account
|
|
19
|
-
</Info>
|
|
22
|
+
- **An MCP client** that supports remote servers, such as Claude, Claude Code, Cursor, VS Code, or ChatGPT.
|
|
23
|
+
- **A TestDriver account.** [Sign up at console.testdriver.ai](https://console.testdriver.ai). The free plan includes 30 testing minutes and needs no credit card.
|
|
20
24
|
|
|
21
25
|
## Add the server
|
|
22
26
|
|
|
23
|
-
Most clients accept the URL directly. Pick yours below.
|
|
24
|
-
|
|
25
27
|
<Tabs>
|
|
26
28
|
<Tab title="Claude">
|
|
29
|
+
|
|
27
30
|
1. Open **Settings → Connectors → Add custom connector**.
|
|
28
31
|
2. Paste `https://mcp.testdriver.ai/mcp`.
|
|
29
|
-
3. Click **Connect
|
|
30
|
-
</Tab>
|
|
32
|
+
3. Click **Connect**, and sign in to TestDriver when the browser opens.
|
|
31
33
|
|
|
34
|
+
</Tab>
|
|
32
35
|
<Tab title="Claude Code">
|
|
36
|
+
|
|
33
37
|
```bash
|
|
34
38
|
claude mcp add --transport http testdriver https://mcp.testdriver.ai/mcp
|
|
35
39
|
```
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
</Tab>
|
|
41
|
+
Then run `/mcp` in a Claude Code session to sign in and confirm the tools are connected.
|
|
39
42
|
|
|
43
|
+
</Tab>
|
|
40
44
|
<Tab title="VS Code">
|
|
41
|
-
|
|
45
|
+
|
|
46
|
+
Add this to `.vscode/mcp.json` in your project:
|
|
42
47
|
|
|
43
48
|
```json .vscode/mcp.json
|
|
44
49
|
{
|
|
@@ -51,11 +56,12 @@ Most clients accept the URL directly. Pick yours below.
|
|
|
51
56
|
}
|
|
52
57
|
```
|
|
53
58
|
|
|
54
|
-
VS Code
|
|
55
|
-
</Tab>
|
|
59
|
+
VS Code asks you to sign in the first time it uses the server.
|
|
56
60
|
|
|
61
|
+
</Tab>
|
|
57
62
|
<Tab title="Cursor">
|
|
58
|
-
|
|
63
|
+
|
|
64
|
+
Add this to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` for all projects:
|
|
59
65
|
|
|
60
66
|
```json .cursor/mcp.json
|
|
61
67
|
{
|
|
@@ -66,16 +72,18 @@ Most clients accept the URL directly. Pick yours below.
|
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
```
|
|
69
|
-
</Tab>
|
|
70
75
|
|
|
76
|
+
</Tab>
|
|
71
77
|
<Tab title="ChatGPT">
|
|
78
|
+
|
|
72
79
|
1. Open **Settings → Connectors → Create**.
|
|
73
80
|
2. Paste `https://mcp.testdriver.ai/mcp` as the MCP server URL.
|
|
74
|
-
3. Choose OAuth for authentication and sign in
|
|
75
|
-
</Tab>
|
|
81
|
+
3. Choose **OAuth** for authentication, and sign in to TestDriver.
|
|
76
82
|
|
|
83
|
+
</Tab>
|
|
77
84
|
<Tab title="Other clients">
|
|
78
|
-
|
|
85
|
+
|
|
86
|
+
Any client that supports the Streamable HTTP transport and OAuth sign-in can connect. Point it at the URL:
|
|
79
87
|
|
|
80
88
|
```json
|
|
81
89
|
{
|
|
@@ -86,58 +94,58 @@ Most clients accept the URL directly. Pick yours below.
|
|
|
86
94
|
}
|
|
87
95
|
}
|
|
88
96
|
```
|
|
97
|
+
|
|
89
98
|
</Tab>
|
|
90
99
|
</Tabs>
|
|
91
100
|
|
|
92
|
-
<Note>
|
|
93
|
-
Clients disagree on the top-level key. VS Code uses `servers`, most others use `mcpServers`, Zed uses `context_servers`, and Codex uses TOML `[mcp_servers]`. If the tools do not show up, check the key before anything else.
|
|
94
|
-
</Note>
|
|
95
|
-
|
|
96
101
|
## Sign in
|
|
97
102
|
|
|
98
|
-
The
|
|
103
|
+
The first time your client connects, it opens a browser window where you sign in to TestDriver.
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
https://mcp.testdriver.ai/.well-known/oauth-protected-resource
|
|
102
|
-
```
|
|
105
|
+
Every tool call afterward runs against the team you signed in with. Its usage counts toward that team's plan.
|
|
103
106
|
|
|
104
|
-
|
|
107
|
+
Clients find the sign-in page automatically. The server uses OAuth 2.1 and publishes its authorization details as [RFC 9728](https://www.rfc-editor.org/rfc/rfc9728) protected-resource metadata at `https://mcp.testdriver.ai/.well-known/oauth-protected-resource`.
|
|
105
108
|
|
|
106
|
-
##
|
|
109
|
+
## Try it
|
|
107
110
|
|
|
108
111
|
Ask your client to drive a browser:
|
|
109
112
|
|
|
110
113
|
```text
|
|
111
|
-
Use TestDriver to open example.com and assert the page
|
|
114
|
+
Use TestDriver to open example.com and assert that the page heading is visible.
|
|
112
115
|
```
|
|
113
116
|
|
|
114
|
-
The agent starts a sandbox and returns a screenshot
|
|
117
|
+
The agent starts a sandbox, opens Chrome, and returns a screenshot after each action.
|
|
115
118
|
|
|
116
|
-
|
|
119
|
+
Every connection gets its own sandbox. Several people or chats can run at once without affecting each other.
|
|
117
120
|
|
|
118
|
-
|
|
121
|
+
## Available tools
|
|
119
122
|
|
|
120
|
-
|
|
|
123
|
+
| Tools | What they do |
|
|
121
124
|
| --- | --- |
|
|
122
|
-
| `session_start`, `session_status`, `session_extend` | Start a sandbox, check
|
|
123
|
-
| `find`, `findall`, `find_and_click` | Locate elements
|
|
124
|
-
| `click`, `hover`, `type`, `press_keys`, `scroll` |
|
|
125
|
-
| `assert`, `check` | Ask yes
|
|
126
|
-
| `screenshot`, `
|
|
125
|
+
| `session_start`, `session_status`, `session_extend` | Start a sandbox, check how long it has left, and keep it alive longer |
|
|
126
|
+
| `find`, `findall`, `find_and_click` | Locate elements from a plain-language description |
|
|
127
|
+
| `click`, `hover`, `type`, `press_keys`, `scroll` | Act on the screen with the mouse and keyboard |
|
|
128
|
+
| `assert`, `check` | Ask yes-or-no questions about what's on screen |
|
|
129
|
+
| `screenshot`, `wait`, `exec`, `focus_application` | Capture the screen, pause, run a command, or switch apps |
|
|
130
|
+
| `list_test_runs`, `get_test_run_detail` | Look up past test runs and their results |
|
|
131
|
+
|
|
132
|
+
Each action also returns the SDK code for that step. The agent uses it to assemble a runnable [Vitest](https://vitest.dev) test as it works.
|
|
127
133
|
|
|
128
|
-
|
|
134
|
+
To turn that test into a file you run locally and in CI, [set up a project](/quickstart-manual).
|
|
129
135
|
|
|
130
|
-
##
|
|
136
|
+
## Run the server locally
|
|
131
137
|
|
|
132
|
-
|
|
138
|
+
Run the server as a local stdio process for headless automation, or to authenticate with an API key instead of a browser sign-in:
|
|
133
139
|
|
|
134
140
|
```bash
|
|
135
141
|
npx -p testdriverai testdriverai-mcp
|
|
136
142
|
```
|
|
137
143
|
|
|
138
|
-
It reads
|
|
144
|
+
It reads your API key from the `TD_API_KEY` environment variable. Create a key at [console.testdriver.ai/team/api-keys](https://console.testdriver.ai/team/api-keys).
|
|
139
145
|
|
|
140
|
-
|
|
146
|
+
Then configure your client to start the server:
|
|
147
|
+
|
|
148
|
+
```json .mcp.json
|
|
141
149
|
{
|
|
142
150
|
"mcpServers": {
|
|
143
151
|
"testdriver": {
|
|
@@ -151,42 +159,51 @@ It reads `TD_API_KEY` from the environment. Generate a key at [console.testdrive
|
|
|
151
159
|
```
|
|
152
160
|
|
|
153
161
|
<Tip>
|
|
154
|
-
`npx testdriverai init` writes this config for
|
|
162
|
+
`npx testdriverai init` writes this config for your client, along with the TestDriver agent, skills, an example test, and a GitHub Actions workflow. See [Set up a project](/quickstart-manual).
|
|
155
163
|
</Tip>
|
|
156
164
|
|
|
157
165
|
## Troubleshooting
|
|
158
166
|
|
|
159
167
|
<AccordionGroup>
|
|
160
|
-
<Accordion title="The tools
|
|
161
|
-
|
|
168
|
+
<Accordion title="The TestDriver tools don't appear in my client">
|
|
169
|
+
|
|
170
|
+
Check that the URL is exactly `https://mcp.testdriver.ai/mcp`. Then restart your client, since most clients read their MCP configuration only at startup.
|
|
171
|
+
|
|
162
172
|
</Accordion>
|
|
173
|
+
<Accordion title="The browser sign-in never finishes">
|
|
174
|
+
|
|
175
|
+
Your client needs to support OAuth 2.1 with Dynamic Client Registration.
|
|
176
|
+
|
|
177
|
+
Clients that only support local (stdio) servers can't connect to the hosted URL. [Run the server locally](#run-the-server-locally) with an API key instead.
|
|
163
178
|
|
|
164
|
-
<Accordion title="The browser login never completes">
|
|
165
|
-
Your client must support OAuth 2.1 with Dynamic Client Registration. Older clients, and clients that only support stdio servers, cannot connect to the hosted URL. Use the local server with `TD_API_KEY` instead.
|
|
166
179
|
</Accordion>
|
|
180
|
+
<Accordion title="The sandbox expired in the middle of a session">
|
|
181
|
+
|
|
182
|
+
A sandbox shuts down after 5 minutes with no activity.
|
|
183
|
+
|
|
184
|
+
Ask the agent to call `session_extend` to keep it alive, or `session_start` to get a new one.
|
|
167
185
|
|
|
168
|
-
<Accordion title="I ran out of device minutes">
|
|
169
|
-
Sandbox time is billed per minute. Check your usage and plan at [console.testdriver.ai](https://console.testdriver.ai).
|
|
170
186
|
</Accordion>
|
|
187
|
+
<Accordion title="I ran out of testing minutes">
|
|
188
|
+
|
|
189
|
+
Sandbox time counts against your plan's testing minutes. Check your usage and upgrade at [console.testdriver.ai/usage](https://console.testdriver.ai/usage).
|
|
171
190
|
|
|
172
|
-
<Accordion title="The sandbox expired mid-session">
|
|
173
|
-
Sessions time out after a period of inactivity. Ask the agent to call `session_extend` before it expires, or `session_start` to get a fresh sandbox.
|
|
174
191
|
</Accordion>
|
|
175
192
|
</AccordionGroup>
|
|
176
193
|
|
|
177
194
|
## Next steps
|
|
178
195
|
|
|
179
196
|
<CardGroup cols={2}>
|
|
180
|
-
<Card title="
|
|
181
|
-
|
|
197
|
+
<Card title="Generate tests" icon="wand-magic-sparkles" href="/generating-tests">
|
|
198
|
+
Prompts that get the best tests out of the agent.
|
|
182
199
|
</Card>
|
|
183
|
-
<Card title="
|
|
184
|
-
|
|
200
|
+
<Card title="Set up a project" icon="wrench" href="/quickstart-manual">
|
|
201
|
+
Save generated tests and run them locally and in CI.
|
|
185
202
|
</Card>
|
|
186
|
-
<Card title="
|
|
187
|
-
|
|
203
|
+
<Card title="Provision apps" icon="rocket" href="/provision">
|
|
204
|
+
Launch browsers, extensions, and desktop apps in the sandbox.
|
|
188
205
|
</Card>
|
|
189
|
-
<Card title="CI/CD" icon="
|
|
206
|
+
<Card title="Run in CI/CD" icon="code-branch" href="/ci-cd">
|
|
190
207
|
Run your tests on every pull request.
|
|
191
208
|
</Card>
|
|
192
209
|
</CardGroup>
|