@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.
Files changed (52) hide show
  1. package/ai/skills/testdriver-agent/SKILL.md +174 -91
  2. package/ai/skills/testdriver-assert/SKILL.md +73 -269
  3. package/ai/skills/testdriver-aws-setup/SKILL.md +194 -312
  4. package/ai/skills/testdriver-bring-your-own-machine/SKILL.md +137 -204
  5. package/ai/skills/testdriver-cache/SKILL.md +142 -149
  6. package/ai/skills/testdriver-caching/SKILL.md +97 -87
  7. package/ai/skills/testdriver-captcha/SKILL.md +126 -111
  8. package/ai/skills/testdriver-ci-cd/SKILL.md +153 -542
  9. package/ai/skills/testdriver-click/SKILL.md +74 -229
  10. package/ai/skills/testdriver-client/SKILL.md +175 -229
  11. package/ai/skills/testdriver-customizing-devices/SKILL.md +72 -250
  12. package/ai/skills/testdriver-dashcam/SKILL.md +71 -404
  13. package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +103 -369
  14. package/ai/skills/testdriver-double-click/SKILL.md +46 -67
  15. package/ai/skills/testdriver-errors/SKILL.md +102 -176
  16. package/ai/skills/testdriver-events/SKILL.md +170 -327
  17. package/ai/skills/testdriver-exec/SKILL.md +92 -256
  18. package/ai/skills/testdriver-extract/SKILL.md +69 -170
  19. package/ai/skills/testdriver-find/SKILL.md +140 -736
  20. package/ai/skills/testdriver-focus-application/SKILL.md +69 -246
  21. package/ai/skills/testdriver-generating-tests/SKILL.md +102 -136
  22. package/ai/skills/testdriver-hosted/SKILL.md +79 -143
  23. package/ai/skills/testdriver-hover/SKILL.md +62 -235
  24. package/ai/skills/testdriver-locating-elements/SKILL.md +71 -366
  25. package/ai/skills/testdriver-making-assertions/SKILL.md +114 -72
  26. package/ai/skills/testdriver-mcp-setup/SKILL.md +79 -62
  27. package/ai/skills/testdriver-mouse-down/SKILL.md +46 -124
  28. package/ai/skills/testdriver-mouse-up/SKILL.md +45 -128
  29. package/ai/skills/testdriver-options/SKILL.md +73 -46
  30. package/ai/skills/testdriver-parse/SKILL.md +95 -184
  31. package/ai/skills/testdriver-performing-actions/SKILL.md +101 -91
  32. package/ai/skills/testdriver-press-keys/SKILL.md +59 -299
  33. package/ai/skills/testdriver-provision/SKILL.md +135 -179
  34. package/ai/skills/testdriver-quickstart/SKILL.md +24 -8
  35. package/ai/skills/testdriver-quickstart-claude/SKILL.md +84 -0
  36. package/ai/skills/testdriver-quickstart-github/SKILL.md +62 -32
  37. package/ai/skills/testdriver-quickstart-manual/SKILL.md +59 -32
  38. package/ai/skills/testdriver-quickstart-vscode/SKILL.md +96 -0
  39. package/ai/skills/testdriver-redraw/SKILL.md +100 -164
  40. package/ai/skills/testdriver-reusable-code/SKILL.md +95 -199
  41. package/ai/skills/testdriver-right-click/SKILL.md +45 -88
  42. package/ai/skills/testdriver-screenshot/SKILL.md +47 -201
  43. package/ai/skills/testdriver-screenshots/SKILL.md +86 -136
  44. package/ai/skills/testdriver-scroll/SKILL.md +71 -154
  45. package/ai/skills/testdriver-secrets/SKILL.md +94 -90
  46. package/ai/skills/testdriver-self-hosted/SKILL.md +82 -140
  47. package/ai/skills/testdriver-test-results-json/SKILL.md +165 -202
  48. package/ai/skills/testdriver-type/SKILL.md +56 -304
  49. package/ai/skills/testdriver-variables/SKILL.md +119 -80
  50. package/ai/skills/testdriver-wait/SKILL.md +31 -29
  51. package/ai/skills/testdriver-what-is-testdriver/SKILL.md +80 -32
  52. package/package.json +1 -1
@@ -1,108 +1,150 @@
1
1
  ---
2
2
  name: testdriver:making-assertions
3
- description: Locate elements and verify app state with AI-powered assertions
3
+ description: Check that your app reached the right state, in plain language or with expect().
4
4
  ---
5
5
  <!-- Generated from making-assertions.mdx. DO NOT EDIT. -->
6
6
 
7
- 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.
7
+ An assertion checks that your app did the right thing after a step. TestDriver gives you two ways to check:
8
8
 
9
- ## Locating Elements
9
+ - [`assert()`](/assert) asks the AI whether a statement about the screen is true, and fails the test if it isn't.
10
+ - [`extract()`](/extract) reads a value off the screen, so you can compare it yourself with `expect()`.
10
11
 
11
- ### Locating Single Elements
12
+ ```javascript
13
+ await testdriver.find('Add to cart button').click();
14
+ await testdriver.assert('the cart icon shows 1 item');
15
+ ```
12
16
 
13
- 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:
17
+ ## Check the screen with assert()
14
18
 
15
- ```javascript
16
- await testdriver.find('email input field');
17
- await testdriver.find('first product card in the grid');
18
- await testdriver.find('dropdown menu labeled "Country"');
19
+ Pass `assert()` a statement that should be true. The AI looks at the current screen and decides.
20
+
21
+ ```javascript tests/login.test.mjs
22
+ import { describe, it } from 'vitest';
23
+ import { TestDriver } from 'testdriverai/vitest/hooks';
24
+
25
+ describe('Login', () => {
26
+ it('signs in with valid credentials', async (context) => {
27
+ const testdriver = TestDriver(context);
28
+ await testdriver.provision.chrome({ url: 'https://testdriver-sandbox.vercel.app/login' });
29
+
30
+ // The sandbox login page shows its test password on screen
31
+ const password = await testdriver.extract('the password shown on the login page');
32
+
33
+ await testdriver.find('Username input field').click();
34
+ await testdriver.type('standard_user');
35
+ await testdriver.find('Password input field').click();
36
+ await testdriver.type(password, { secret: true });
37
+ await testdriver.find('Sign in button below the password field').click();
38
+
39
+ await testdriver.assert('the product list is shown');
40
+ });
41
+ });
19
42
  ```
20
43
 
21
- <Info>TestDriver caches the found elements for better performance on later calls. Read more about [element caching here](/caching).</Info>
44
+ 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.
22
45
 
23
- ### Debugging Found Elements
46
+ ## Write statements the AI can judge
24
47
 
25
- After TestDriver finds an element, you can look at its properties for debug:
48
+ The AI judges only what's visible on screen right now. Write statements a person could confirm by looking.
49
+
50
+ - **Name the thing and its state.** `'the Submit button is disabled'`, not `'the form is invalid'`.
51
+ - **Quote exact text** when the wording matters: `'the banner says "Order placed"'`.
52
+ - **Check one thing per assertion.** Two short assertions tell you exactly which part failed.
53
+ - **Assert outcomes, not steps.** Check what the user should see after an action, such as a confirmation message.
26
54
 
27
55
  ```javascript
28
- const button = await testdriver.find('submit button');
29
- console.log(button);
56
+ // Visibility
57
+ await testdriver.assert('the login form is visible');
58
+ await testdriver.assert('the loading spinner is not visible');
59
+
60
+ // Exact text
61
+ await testdriver.assert('the error message says "Invalid email address"');
62
+
63
+ // State of a control
64
+ await testdriver.assert('the "Remember me" checkbox is checked');
65
+ await testdriver.assert('the Country dropdown shows "United States"');
30
66
  ```
31
67
 
32
- This outputs all element properties:
68
+ ## Compare exact values with extract()
69
+
70
+ 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:
33
71
 
34
72
  ```javascript
35
- {
36
- description: 'submit button',
37
- found: true,
38
- x: 150,
39
- y: 300,
40
- coordinates: { x: 150, y: 300, centerX: 200, centerY: 320 },
41
- threshold: 0.8,
42
- confidence: 0.95,
43
- similarity: 0.92,
44
- selector: 'button[type="submit"]',
45
- cache: {
46
- hit: true,
47
- strategy: 'pixel-diff',
48
- createdAt: '2025-01-15T10:30:00Z',
49
- diffPercent: 0.02,
50
- imageUrl: 'https://...'
51
- }
52
- }
73
+ import { expect } from 'vitest';
74
+
75
+ const itemCount = await testdriver.extract('the number of items shown on the cart icon');
76
+ expect(Number(itemCount)).toBe(1);
53
77
  ```
54
78
 
55
- ### Working with Multiple Elements
79
+ 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:
56
80
 
57
- Find and interact with multiple elements:
81
+ ```javascript
82
+ const orderNumber = await testdriver.extract('the order confirmation number');
83
+ expect(orderNumber).toMatch(/^A-\d+$/);
84
+ ```
85
+
86
+ ## Check state before and after an action
87
+
88
+ An assertion after an action only proves the end state. Assert the starting state too, so the test catches an action that did nothing:
58
89
 
59
90
  ```javascript
60
- // Find all matching elements
61
- const products = await testdriver.findAll('product card');
62
- console.log(`Found ${products.length} products`);
91
+ await testdriver.assert('the cart is empty');
63
92
 
64
- // Interact with each
65
- for (const product of products) {
66
- const title = await product.find('title text');
67
- console.log('Product:', title.text);
93
+ await testdriver.find('Add to cart button under the TestDriver Hat').click();
94
+
95
+ await testdriver.assert('the cart icon shows 1 item');
96
+ ```
97
+
98
+ To check that a value changed, extract it on both sides of the action:
99
+
100
+ ```javascript
101
+ const before = await testdriver.extract('the cart total');
68
102
 
69
- await product.find('add to cart button').click();
70
- }
103
+ await testdriver.find('Add to cart button under the TestDriver Hat').click();
71
104
 
72
- // Or find specific element
73
- const firstProduct = products[0];
74
- await firstProduct.click();
105
+ const after = await testdriver.extract('the cart total');
106
+ expect(after).not.toBe(before);
75
107
  ```
76
108
 
77
- ## Making Assertions
109
+ ## Wait before you assert
78
110
 
79
- Use AI-powered assertions to verify application state. TestDriver acts as a judge: it evaluates your natural-language statement against the current state of the app and returns a boolean plus reasoning explaining the verdict.
111
+ `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:
80
112
 
81
113
  ```javascript
82
- // Verify visibility
83
- await testdriver.assert('login page is displayed');
84
- await testdriver.assert('submit button is visible');
85
- await testdriver.assert('loading spinner is not visible');
86
-
87
- // Verify content
88
- await testdriver.assert('page title is "Welcome"');
89
- await testdriver.assert('success message says "Account created"');
90
- await testdriver.assert('error message contains "Invalid email"');
91
-
92
- // Verify state
93
- await testdriver.assert('checkbox is checked');
94
- await testdriver.assert('dropdown shows "United States"');
95
- await testdriver.assert('button is disabled');
96
-
97
- // Verify visual appearance
98
- await testdriver.assert('submit button is blue');
99
- await testdriver.assert('form has red border');
114
+ await testdriver.find('Place order button').click();
115
+
116
+ // Keep looking for up to 30 seconds while the confirmation page loads
117
+ await testdriver.find('Order confirmation heading', { timeout: 30000 });
118
+ await testdriver.assert('the confirmation shows an order number');
100
119
  ```
101
120
 
102
- <Info>Assertions are not cached and always re-evaluated to ensure accuracy.</Info>
121
+ See [Perform actions](/performing-actions#wait-for-a-changing-ui) for other ways to wait.
122
+
123
+ ## How assertions are cached
124
+
125
+ `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.
126
+
127
+ `extract()` is never cached. It reads the screen every time.
103
128
 
104
- ## Next
129
+ To always ask the AI for one assertion, pass `threshold: -1`:
130
+
131
+ ```javascript
132
+ await testdriver.assert('the clock shows the current time', { threshold: -1 });
133
+ ```
105
134
 
106
- <Card title="Adapt" icon="arrows-rotate" href="/performing-actions">
107
- Drive your app forward by performing actions on the elements you've located and validated.
108
- </Card>
135
+ ## Next steps
136
+
137
+ <CardGroup cols={2}>
138
+ <Card title="assert()" icon="check-circle" href="/assert">
139
+ Every option, return value, and error.
140
+ </Card>
141
+ <Card title="extract()" icon="wand-magic-sparkles" href="/extract">
142
+ Read values off the screen as strings.
143
+ </Card>
144
+ <Card title="Perform actions" icon="arrow-pointer" href="/performing-actions">
145
+ Click, type, and wait for a changing UI.
146
+ </Card>
147
+ <Card title="Debug with screenshots" icon="bug" href="/debugging-with-screenshots">
148
+ See what the screen showed when an assertion failed.
149
+ </Card>
150
+ </CardGroup>
@@ -1,43 +1,48 @@
1
1
  ---
2
2
  name: testdriver:mcp-setup
3
- description: Connect any AI client to TestDriver by adding one URL.
3
+ description: Connect Claude, Cursor, VS Code, ChatGPT, or any MCP client to TestDriver with one URL.
4
4
  ---
5
5
  <!-- Generated from mcp-setup.mdx. DO NOT EDIT. -->
6
6
 
7
- TestDriver runs a hosted [Model Context Protocol](https://modelcontextprotocol.io) server. There is nothing to install and no API key to paste. Add one URL to your AI client, sign in through the browser, and the computer-use tools appear in chat.
7
+ Connect your AI client to TestDriver's hosted [Model Context Protocol](https://modelcontextprotocol.io) server, and you can drive a real sandbox from chat.
8
+
9
+ - Open your app.
10
+ - Find elements, click, type, and assert.
11
+ - Get a screenshot after every step.
12
+
13
+ There's nothing to install and no API key to copy. Add one URL and sign in through your browser:
8
14
 
9
15
  ```text
10
16
  https://mcp.testdriver.ai/mcp
11
17
  ```
12
18
 
13
- <Info>
14
- **Prerequisites**
19
+ ## Before you begin
15
20
 
16
- - An MCP-compatible AI client (Claude, Claude Code, VS Code, Cursor, ChatGPT, and others)
17
- - A TestDriver account. [Create one for free](https://console.testdriver.ai/settings). You get 60 device minutes, no credit card required.
18
- </Info>
21
+ - **An MCP client** that supports remote servers, such as Claude, Claude Code, Cursor, VS Code, or ChatGPT.
22
+ - **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.
19
23
 
20
24
  ## Add the server
21
25
 
22
- Most clients accept the URL directly. Pick yours below.
23
-
24
26
  <Tabs>
25
27
  <Tab title="Claude">
28
+
26
29
  1. Open **Settings → Connectors → Add custom connector**.
27
30
  2. Paste `https://mcp.testdriver.ai/mcp`.
28
- 3. Click **Connect** and sign in with TestDriver when the browser opens.
29
- </Tab>
31
+ 3. Click **Connect**, and sign in to TestDriver when the browser opens.
30
32
 
33
+ </Tab>
31
34
  <Tab title="Claude Code">
35
+
32
36
  ```bash
33
37
  claude mcp add --transport http testdriver https://mcp.testdriver.ai/mcp
34
38
  ```
35
39
 
36
- Run `/mcp` in a session to start the browser login and confirm the tools are connected.
37
- </Tab>
40
+ Then run `/mcp` in a Claude Code session to sign in and confirm the tools are connected.
38
41
 
42
+ </Tab>
39
43
  <Tab title="VS Code">
40
- Add this to `.vscode/mcp.json` in your project. VS Code uses the `servers` key:
44
+
45
+ Add this to `.vscode/mcp.json` in your project:
41
46
 
42
47
  ```json .vscode/mcp.json
43
48
  {
@@ -50,11 +55,12 @@ Most clients accept the URL directly. Pick yours below.
50
55
  }
51
56
  ```
52
57
 
53
- VS Code prompts you to authorize the server the first time you use it.
54
- </Tab>
58
+ VS Code asks you to sign in the first time it uses the server.
55
59
 
60
+ </Tab>
56
61
  <Tab title="Cursor">
57
- Add this to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):
62
+
63
+ Add this to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` for all projects:
58
64
 
59
65
  ```json .cursor/mcp.json
60
66
  {
@@ -65,16 +71,18 @@ Most clients accept the URL directly. Pick yours below.
65
71
  }
66
72
  }
67
73
  ```
68
- </Tab>
69
74
 
75
+ </Tab>
70
76
  <Tab title="ChatGPT">
77
+
71
78
  1. Open **Settings → Connectors → Create**.
72
79
  2. Paste `https://mcp.testdriver.ai/mcp` as the MCP server URL.
73
- 3. Choose OAuth for authentication and sign in with TestDriver.
74
- </Tab>
80
+ 3. Choose **OAuth** for authentication, and sign in to TestDriver.
75
81
 
82
+ </Tab>
76
83
  <Tab title="Other clients">
77
- Any spec-compliant client works. Point it at the URL using the streamable HTTP transport:
84
+
85
+ Any client that supports the Streamable HTTP transport and OAuth sign-in can connect. Point it at the URL:
78
86
 
79
87
  ```json
80
88
  {
@@ -85,58 +93,58 @@ Most clients accept the URL directly. Pick yours below.
85
93
  }
86
94
  }
87
95
  ```
96
+
88
97
  </Tab>
89
98
  </Tabs>
90
99
 
91
- <Note>
92
- 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.
93
- </Note>
94
-
95
100
  ## Sign in
96
101
 
97
- The server speaks OAuth 2.1 and advertises its authorization server via [RFC 9728](https://www.rfc-editor.org/rfc/rfc9728) protected-resource metadata:
102
+ The first time your client connects, it opens a browser window where you sign in to TestDriver.
98
103
 
99
- ```text
100
- https://mcp.testdriver.ai/.well-known/oauth-protected-resource
101
- ```
104
+ Every tool call afterward runs against the team you signed in with. Its usage counts toward that team's plan.
102
105
 
103
- Spec-compliant clients read that metadata, open a browser, and complete the handshake for you. Every tool is scoped to the team you sign in with.
106
+ 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`.
104
107
 
105
- ## Verify it works
108
+ ## Try it
106
109
 
107
110
  Ask your client to drive a browser:
108
111
 
109
112
  ```text
110
- Use TestDriver to open example.com and assert the page title is visible.
113
+ Use TestDriver to open example.com and assert that the page heading is visible.
111
114
  ```
112
115
 
113
- The agent starts a sandbox and returns a screenshot with every action. Each connection gets its own isolated sandbox, so multiple people and multiple chats can run tests at the same time without interfering.
116
+ The agent starts a sandbox, opens Chrome, and returns a screenshot after each action.
114
117
 
115
- ## What you get
118
+ Every connection gets its own sandbox. Several people or chats can run at once without affecting each other.
116
119
 
117
- The hosted server exposes the full live tool set:
120
+ ## Available tools
118
121
 
119
- | Tool | Purpose |
122
+ | Tools | What they do |
120
123
  | --- | --- |
121
- | `session_start`, `session_status`, `session_extend` | Start a sandbox, check its health, add more time |
122
- | `find`, `findall`, `find_and_click` | Locate elements by plain-English description |
123
- | `click`, `hover`, `type`, `press_keys`, `scroll` | Perform actions |
124
- | `assert`, `check` | Ask yes/no questions about the screen |
125
- | `screenshot`, `exec`, `wait`, `focus_application` | Capture state, run commands, pause |
124
+ | `session_start`, `session_status`, `session_extend` | Start a sandbox, check how long it has left, and keep it alive longer |
125
+ | `find`, `findall`, `find_and_click` | Locate elements from a plain-language description |
126
+ | `click`, `hover`, `type`, `press_keys`, `scroll` | Act on the screen with the mouse and keyboard |
127
+ | `assert`, `check` | Ask yes-or-no questions about what's on screen |
128
+ | `screenshot`, `wait`, `exec`, `focus_application` | Capture the screen, pause, run a command, or switch apps |
129
+ | `list_test_runs`, `get_test_run_detail` | Look up past test runs and their results |
130
+
131
+ 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.
126
132
 
127
- Every action also returns the SDK code for that step, so the agent can write a runnable [Vitest](https://vitest.dev) test as it goes.
133
+ To turn that test into a file you run locally and in CI, [set up a project](/quickstart-manual).
128
134
 
129
- ## Local server for CI and automation
135
+ ## Run the server locally
130
136
 
131
- For headless automation, or when you would rather use an API key than a browser login, run the server as a local stdio process:
137
+ Run the server as a local stdio process for headless automation, or to authenticate with an API key instead of a browser sign-in:
132
138
 
133
139
  ```bash
134
140
  npx -p testdriverai testdriverai-mcp
135
141
  ```
136
142
 
137
- It reads `TD_API_KEY` from the environment. Generate a key at [console.testdriver.ai/settings](https://console.testdriver.ai/settings).
143
+ 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).
138
144
 
139
- ```json
145
+ Then configure your client to start the server:
146
+
147
+ ```json .mcp.json
140
148
  {
141
149
  "mcpServers": {
142
150
  "testdriver": {
@@ -150,42 +158,51 @@ It reads `TD_API_KEY` from the environment. Generate a key at [console.testdrive
150
158
  ```
151
159
 
152
160
  <Tip>
153
- `npx testdriverai init` writes this config for you, plus the TestDriver agent, skills, an example test, and a GitHub Actions workflow. See [Setting up your workspace](/quickstart-manual).
161
+ `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).
154
162
  </Tip>
155
163
 
156
164
  ## Troubleshooting
157
165
 
158
166
  <AccordionGroup>
159
- <Accordion title="The tools do not appear in my client">
160
- Confirm the URL is exactly `https://mcp.testdriver.ai/mcp`, check that you used the correct top-level config key for your client, and restart the client. Most clients read their MCP config only at startup.
167
+ <Accordion title="The TestDriver tools don't appear in my client">
168
+
169
+ 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.
170
+
161
171
  </Accordion>
172
+ <Accordion title="The browser sign-in never finishes">
173
+
174
+ Your client needs to support OAuth 2.1 with Dynamic Client Registration.
175
+
176
+ 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.
162
177
 
163
- <Accordion title="The browser login never completes">
164
- 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.
165
178
  </Accordion>
179
+ <Accordion title="The sandbox expired in the middle of a session">
180
+
181
+ A sandbox shuts down after 5 minutes with no activity.
182
+
183
+ Ask the agent to call `session_extend` to keep it alive, or `session_start` to get a new one.
166
184
 
167
- <Accordion title="I ran out of device minutes">
168
- Sandbox time is billed per minute. Check your usage and plan at [console.testdriver.ai](https://console.testdriver.ai).
169
185
  </Accordion>
186
+ <Accordion title="I ran out of testing minutes">
187
+
188
+ Sandbox time counts against your plan's testing minutes. Check your usage and upgrade at [console.testdriver.ai/usage](https://console.testdriver.ai/usage).
170
189
 
171
- <Accordion title="The sandbox expired mid-session">
172
- 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.
173
190
  </Accordion>
174
191
  </AccordionGroup>
175
192
 
176
193
  ## Next steps
177
194
 
178
195
  <CardGroup cols={2}>
179
- <Card title="Generating tests" icon="wand-magic-sparkles" href="/generating-tests" arrow horizontal>
180
- Prompting patterns that get the best tests out of the agent.
196
+ <Card title="Generate tests" icon="wand-magic-sparkles" href="/generating-tests">
197
+ Prompts that get the best tests out of the agent.
181
198
  </Card>
182
- <Card title="Setting up your workspace" icon="wrench" href="/quickstart-manual" arrow horizontal>
183
- Add the SDK to a project so generated tests run locally and in CI.
199
+ <Card title="Set up a project" icon="wrench" href="/quickstart-manual">
200
+ Save generated tests and run them locally and in CI.
184
201
  </Card>
185
- <Card title="Walkthrough" icon="map" href="/provision" arrow horizontal>
186
- Provision apps, locate elements, perform actions, and make assertions.
202
+ <Card title="Provision apps" icon="rocket" href="/provision">
203
+ Launch browsers, extensions, and desktop apps in the sandbox.
187
204
  </Card>
188
- <Card title="CI/CD" icon="circle-play" href="/ci-cd" arrow horizontal>
205
+ <Card title="Run in CI/CD" icon="code-branch" href="/ci-cd">
189
206
  Run your tests on every pull request.
190
207
  </Card>
191
208
  </CardGroup>