@testdriverai/agent 7.11.229-canary → 7.11.232-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 (100) hide show
  1. package/docs/_data/examples-manifest.json +16 -16
  2. package/docs/_scripts/generate-examples.js +38 -45
  3. package/docs/agent.mdx +174 -93
  4. package/docs/assert.mdx +73 -269
  5. package/docs/aws-setup.mdx +196 -314
  6. package/docs/bring-your-own-machine.mdx +139 -206
  7. package/docs/cache.mdx +144 -151
  8. package/docs/caching.mdx +99 -89
  9. package/docs/captcha.mdx +126 -111
  10. package/docs/ci-cd.mdx +154 -543
  11. package/docs/click.mdx +74 -229
  12. package/docs/client.mdx +177 -231
  13. package/docs/copilot/auto-healing.mdx +86 -370
  14. package/docs/copilot/running-tests.mdx +121 -930
  15. package/docs/customizing-devices.mdx +74 -251
  16. package/docs/dashcam.mdx +72 -405
  17. package/docs/debugging-with-screenshots.mdx +105 -371
  18. package/docs/docs.json +79 -22
  19. package/docs/double-click.mdx +48 -68
  20. package/docs/errors.mdx +102 -176
  21. package/docs/events.mdx +170 -327
  22. package/docs/examples/{hover-text-with-description.mdx → add-to-cart.mdx} +30 -35
  23. package/docs/examples/assert.mdx +28 -41
  24. package/docs/examples/click-button.mdx +71 -0
  25. package/docs/examples/{hover-image.mdx → click-icon.mdx} +32 -28
  26. package/docs/examples/element-not-found.mdx +27 -26
  27. package/docs/examples/findall-coffee-icons.mdx +28 -32
  28. package/docs/examples/installer.mdx +61 -25
  29. package/docs/examples/launch-vscode-linux.mdx +28 -51
  30. package/docs/examples/navigate-and-scroll.mdx +82 -0
  31. package/docs/examples/parse.mdx +24 -28
  32. package/docs/examples/press-keys.mdx +28 -25
  33. package/docs/examples/scroll.mdx +25 -27
  34. package/docs/examples/type.mdx +26 -21
  35. package/docs/exec.mdx +92 -256
  36. package/docs/extract.mdx +69 -170
  37. package/docs/find.mdx +140 -736
  38. package/docs/focus-application.mdx +69 -246
  39. package/docs/generating-tests.mdx +103 -137
  40. package/docs/guide/best-practices-polling.mdx +65 -141
  41. package/docs/hosted.mdx +80 -144
  42. package/docs/hover.mdx +62 -235
  43. package/docs/locating-elements.mdx +74 -369
  44. package/docs/making-assertions.mdx +116 -74
  45. package/docs/mcp-setup.mdx +80 -63
  46. package/docs/mouse-down.mdx +48 -125
  47. package/docs/mouse-up.mdx +47 -129
  48. package/docs/options.mdx +75 -48
  49. package/docs/parse.mdx +95 -184
  50. package/docs/performing-actions.mdx +104 -94
  51. package/docs/press-keys.mdx +59 -299
  52. package/docs/provision.mdx +137 -182
  53. package/docs/quickstart-claude.mdx +85 -0
  54. package/docs/quickstart-github.mdx +62 -32
  55. package/docs/quickstart-manual.mdx +60 -33
  56. package/docs/quickstart-vscode.mdx +97 -0
  57. package/docs/quickstart.mdx +26 -9
  58. package/docs/redraw.mdx +101 -165
  59. package/docs/reusable-code.mdx +97 -200
  60. package/docs/right-click.mdx +47 -89
  61. package/docs/screenshot.mdx +47 -201
  62. package/docs/screenshots.mdx +87 -137
  63. package/docs/scroll.mdx +71 -154
  64. package/docs/secrets.mdx +96 -91
  65. package/docs/self-hosted.mdx +83 -142
  66. package/docs/snippets/enterprise.mdx +15 -0
  67. package/docs/styles.css +68 -0
  68. package/docs/test-results-json.mdx +167 -204
  69. package/docs/type.mdx +56 -304
  70. package/docs/variables.mdx +121 -81
  71. package/docs/wait.mdx +33 -31
  72. package/docs/what-is-testdriver.mdx +80 -32
  73. package/examples/{hover-text-with-description.test.mjs → add-to-cart.test.mjs} +4 -5
  74. package/examples/assert.test.mjs +3 -20
  75. package/examples/{hover-text.test.mjs → click-button.test.mjs} +3 -4
  76. package/examples/{hover-image.test.mjs → click-icon.test.mjs} +5 -6
  77. package/examples/element-not-found.test.mjs +3 -5
  78. package/examples/findall-coffee-icons.test.mjs +3 -3
  79. package/examples/installer.test.mjs +1 -1
  80. package/examples/launch-vscode-linux.test.mjs +6 -33
  81. package/examples/{scroll-keyboard.test.mjs → navigate-and-scroll.test.mjs} +4 -5
  82. package/examples/parse.test.mjs +1 -2
  83. package/examples/press-keys.test.mjs +4 -4
  84. package/examples/scroll.test.mjs +3 -6
  85. package/examples/type.test.mjs +5 -2
  86. package/lib/provision.js +6 -2
  87. package/package.json +1 -1
  88. package/sdk.d.ts +4 -2
  89. package/sdk.js +1 -1
  90. package/docs/claude-mcp-plugin.mdx +0 -244
  91. package/docs/elements.mdx +0 -606
  92. package/docs/examples/ai.mdx +0 -78
  93. package/docs/examples/captcha-api.mdx +0 -92
  94. package/docs/examples/chrome-extension.mdx +0 -156
  95. package/docs/examples/drag-and-drop.mdx +0 -100
  96. package/docs/examples/formatted-logging.mdx +0 -74
  97. package/docs/examples/hover-text.mdx +0 -70
  98. package/docs/examples/match-image.mdx +0 -97
  99. package/docs/examples/scroll-keyboard.mdx +0 -80
  100. package/docs/examples/scroll-until-text.mdx +0 -109
@@ -1,294 +1,117 @@
1
1
  ---
2
2
  title: "focusApplication()"
3
3
  sidebarTitle: "focusApplication"
4
- description: "Bring an application window to the foreground"
4
+ description: "Bring an open application window to the front of the sandbox desktop."
5
5
  icon: "window-maximize"
6
6
  ---
7
7
 
8
- ## Overview
8
+ Bring an app's window to the front, so your next clicks and keystrokes go to it.
9
9
 
10
- Move a specific application window to the front. Make it the active window for interactions.
10
+ ```javascript
11
+ await testdriver.focusApplication('Google Chrome');
12
+ ```
11
13
 
12
- ## Syntax
14
+ Use it when your test works across several apps, or after a dialog or another window has taken focus.
13
15
 
14
- ```javascript
15
- await testdriver.focusApplication(name)
16
+ <Note>
17
+ The [`provision`](/provision) methods focus the app they launch, so you don't need this right after `provision.chrome()`, `provision.vscode()`, `provision.electron()`, or `provision.installer()`.
18
+ </Note>
19
+
20
+ ## Signature
21
+
22
+ ```typescript
23
+ testdriver.focusApplication(name: string, options?: object): Promise<string>
16
24
  ```
17
25
 
18
26
  ## Parameters
19
27
 
20
28
  <ParamField path="name" type="string" required>
21
- The application name (for example, `'Google Chrome'`, `'Microsoft Edge'`, `'Notepad'`)
29
+ The app's name, as it appears in its window title. For example `'Google Chrome'`, `'Notepad'`, or `'Visual Studio Code'`.
30
+ </ParamField>
31
+
32
+ <ParamField path="options" type="object">
33
+ <Expandable title="properties">
34
+ <ParamField path="redraw" type="boolean | object">
35
+ Wait for the screen to settle after focusing. Uses the client's setting when you leave it out. See [Redraw](/redraw).
36
+ </ParamField>
37
+ </Expandable>
22
38
  </ParamField>
23
39
 
24
40
  ## Returns
25
41
 
26
- `Promise<string>` - The result message
42
+ `Promise<string>`. Always resolves to `"The application was focused."`.
27
43
 
28
- ## Examples
44
+ ## Errors
45
+
46
+ `focusApplication()` doesn't throw when no window matches. It returns the same message either way.
29
47
 
30
- ### Common Applications
48
+ To confirm the right app is in front, follow it with an [`assert()`](/assert):
31
49
 
32
50
  ```javascript
33
- // Focus Chrome browser
34
- await testdriver.focusApplication('Google Chrome');
51
+ await testdriver.focusApplication('Notepad');
52
+ await testdriver.assert('a Notepad window is in the foreground');
53
+ ```
35
54
 
36
- // Focus Edge browser
37
- await testdriver.focusApplication('Microsoft Edge');
55
+ ## How it matches windows
38
56
 
39
- // Focus Notepad
40
- await testdriver.focusApplication('Notepad');
57
+ - **Windows:** TestDriver looks for windows whose title contains `name`. It restores a minimized window, then brings it to the front.
58
+ - **Linux:** TestDriver runs `jumpapp -f <name>`. If that fails, it activates the first window whose title matches `name`, using `xdotool`.
41
59
 
42
- // Focus File Explorer
43
- await testdriver.focusApplication('File Explorer');
60
+ The app must already be running. Launch it first with [`provision`](/provision) or [`exec()`](/exec).
44
61
 
45
- // Focus Visual Studio Code
46
- await testdriver.focusApplication('Visual Studio Code');
47
- ```
62
+ ## Examples
48
63
 
49
- ### After Opening Applications
64
+ ### Switch between two apps
50
65
 
51
66
  ```javascript
52
- // Open Chrome and focus it
53
- await testdriver.exec('pwsh', `
54
- Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "https://example.com"
55
- `, 5000);
67
+ const orderNumber = await testdriver.extract('the order number');
56
68
 
57
- await new Promise(r => setTimeout(r, 2000)); // Wait for launch
69
+ await testdriver.focusApplication('Notepad');
70
+ await testdriver.type(orderNumber);
58
71
 
59
- // Focus the Chrome window
60
72
  await testdriver.focusApplication('Google Chrome');
73
+ await testdriver.find('Confirm order button').click();
61
74
  ```
62
75
 
63
- ## Best Practices
64
-
65
- <Check>
66
- **Focus before UI interactions**
67
-
68
- Always focus the target application before interacting with its UI:
69
-
70
- ```javascript
71
- await testdriver.focusApplication('Google Chrome');
72
-
73
- const button = await testdriver.find('submit button');
74
- await button.click();
75
- ```
76
- </Check>
77
-
78
- <Check>
79
- **Wait after launching apps**
80
-
81
- Give applications time to open before focusing:
82
-
83
- ```javascript
84
- await testdriver.exec('pwsh', 'Start-Process notepad', 5000);
85
- await new Promise(r => setTimeout(r, 1000)); // Wait for launch
86
- await testdriver.focusApplication('Notepad');
87
- ```
88
- </Check>
89
-
90
- <Check>
91
- **Use exact application names**
92
-
93
- ```javascript
94
- // ✅ Correct
95
- await testdriver.focusApplication('Google Chrome');
96
-
97
- // ❌ May not work
98
- await testdriver.focusApplication('Chrome');
99
- await testdriver.focusApplication('chrome.exe');
100
- ```
101
- </Check>
102
-
103
- <Warning>
104
- **Application must be running**
105
-
106
- The application must already be running. `focusApplication()` won't launch applications, only bring existing windows to the foreground.
107
- </Warning>
108
-
109
- ## Use Cases
110
-
111
- <AccordionGroup>
112
- <Accordion title="Multi-Application Testing">
113
- ```javascript
114
- // Test workflow across multiple apps
115
- await testdriver.focusApplication('Google Chrome');
116
- const data = await testdriver.extract('the order number');
117
-
118
- await testdriver.focusApplication('Notepad');
119
- await testdriver.type(data);
120
- await testdriver.pressKeys(['ctrl', 's']);
121
-
122
- await testdriver.focusApplication('Google Chrome');
123
- const nextButton = await testdriver.find('next button');
124
- await nextButton.click();
125
- ```
126
- </Accordion>
127
-
128
- <Accordion title="Browser Switching">
129
- ```javascript
130
- // Compare behavior in different browsers
131
- await testdriver.focusApplication('Google Chrome');
132
- await testdriver.assert('page loaded correctly in Chrome');
133
-
134
- await testdriver.focusApplication('Microsoft Edge');
135
- await testdriver.assert('page loaded correctly in Edge');
136
- ```
137
- </Accordion>
138
-
139
- <Accordion title="Desktop Application Testing">
140
- ```javascript
141
- // Launch and focus desktop app
142
- await testdriver.exec('pwsh', 'Start-Process notepad', 5000);
143
- await new Promise(r => setTimeout(r, 1000));
144
-
145
- await testdriver.focusApplication('Notepad');
146
- await testdriver.type('Test content');
147
- ```
148
- </Accordion>
149
-
150
- <Accordion title="Window Management">
151
- ```javascript
152
- // Show desktop first
153
- await testdriver.pressKeys(['winleft', 'd']);
154
-
155
- // Click desktop icon
156
- const icon = await testdriver.find('Chrome icon on desktop');
157
- await icon.click();
158
-
159
- await new Promise(r => setTimeout(r, 2000));
160
-
161
- // Focus the opened window
162
- await testdriver.focusApplication('Google Chrome');
163
- ```
164
- </Accordion>
165
- </AccordionGroup>
166
-
167
- ## Common Application Names
168
-
169
- ### Browsers
170
- - `'Google Chrome'`
171
- - `'Microsoft Edge'`
172
- - `'Mozilla Firefox'`
173
- - `'Safari'` (macOS)
174
-
175
- ### Office Applications
176
- - `'Microsoft Word'`
177
- - `'Microsoft Excel'`
178
- - `'Microsoft PowerPoint'`
179
- - `'Microsoft Outlook'`
180
-
181
- ### Development Tools
182
- - `'Visual Studio Code'`
183
- - `'Visual Studio'`
184
- - `'IntelliJ IDEA'`
185
- - `'Sublime Text'`
186
-
187
- ### System Applications
188
- - `'Notepad'`
189
- - `'File Explorer'`
190
- - `'Command Prompt'`
191
- - `'Windows PowerShell'`
192
- - `'Task Manager'`
193
-
194
- ### Communication
195
- - `'Microsoft Teams'`
196
- - `'Slack'`
197
- - `'Discord'`
198
- - `'Zoom'`
199
-
200
- ## Complete Example
76
+ ### Launch an app and focus it on Windows
201
77
 
202
78
  ```javascript
203
- import { beforeAll, afterAll, describe, it } from 'vitest';
204
- import TestDriver from 'testdriverai';
79
+ await testdriver.exec({ language: 'pwsh', code: 'Start-Process notepad' });
80
+ await testdriver.focusApplication('Notepad');
81
+ await testdriver.type('Meeting notes');
82
+ ```
205
83
 
206
- describe('Multi-Application Workflow', () => {
207
- let testdriver;
84
+ ### Return to the browser after a dialog
208
85
 
209
- beforeAll(async () => {
210
- client = new TestDriver(process.env.TD_API_KEY);
211
- await testdriver.auth();
212
- await testdriver.connect();
213
- });
86
+ ```javascript
87
+ await testdriver.find('Download report button').click();
88
+ await testdriver.focusApplication('Google Chrome');
89
+ ```
214
90
 
215
- afterAll(async () => {
216
- await testdriver.disconnect();
217
- });
91
+ ## Complete example
92
+
93
+ ```javascript tests/notepad.test.mjs
94
+ import { describe, expect, it } from 'vitest';
95
+ import { TestDriver } from 'testdriverai/vitest/hooks';
218
96
 
219
- it('should work across multiple applications', async () => {
220
- // Start in browser
221
- await testdriver.focusApplication('Google Chrome');
222
-
223
- // Get data from web page
224
- const orderNumber = await testdriver.extract('the order number');
225
- console.log('Order:', orderNumber);
226
-
227
- // Open Notepad
228
- await testdriver.exec('pwsh', 'Start-Process notepad', 5000);
229
- await new Promise(r => setTimeout(r, 1500));
230
-
231
- // Focus Notepad and save data
97
+ describe('Notepad', () => {
98
+ it('types into Notepad', async (context) => {
99
+ // Windows sandboxes are available on Enterprise plans
100
+ const testdriver = TestDriver(context, { os: 'windows' });
101
+
102
+ await testdriver.exec({ language: 'pwsh', code: 'Start-Process notepad' });
232
103
  await testdriver.focusApplication('Notepad');
233
- await testdriver.type(`Order Number: ${orderNumber}`);
234
- await testdriver.type('\n');
235
- await testdriver.type(`Date: ${new Date().toISOString()}`);
236
-
237
- // Save file
238
- await testdriver.pressKeys(['ctrl', 's']);
239
- await new Promise(r => setTimeout(r, 500));
240
-
241
- await testdriver.type('C:\\order-info.txt');
242
- await testdriver.pressKeys(['enter']);
243
-
244
- // Return to browser
245
- await testdriver.focusApplication('Google Chrome');
246
-
247
- const confirmButton = await testdriver.find('confirm order button');
248
- await confirmButton.click();
249
-
250
- await testdriver.assert('order confirmed');
251
- });
252
104
 
253
- it('should switch between browser tabs', async () => {
254
- await testdriver.focusApplication('Google Chrome');
255
-
256
- // Open new tab
257
- await testdriver.pressKeys(['ctrl', 't']);
258
- await new Promise(r => setTimeout(r, 500));
259
-
260
- // Navigate to URL
261
- await testdriver.pressKeys(['ctrl', 'l']);
262
- await testdriver.type('https://example.com');
263
- await testdriver.pressKeys(['enter']);
264
-
265
- await new Promise(r => setTimeout(r, 2000));
266
-
267
- // Ensure Chrome is still focused
268
- await testdriver.focusApplication('Google Chrome');
269
-
270
- await testdriver.assert('example.com page is loaded');
271
- });
105
+ await testdriver.type('Hello from TestDriver');
272
106
 
273
- it('should handle dialog boxes', async () => {
274
- await testdriver.focusApplication('Google Chrome');
275
-
276
- const deleteButton = await testdriver.find('delete account button');
277
- await deleteButton.click();
278
-
279
- await new Promise(r => setTimeout(r, 500));
280
-
281
- // Dialog appears - make sure it's focused
282
- await testdriver.focusApplication('Google Chrome');
283
-
284
- const confirmBtn = await testdriver.find('confirm deletion button');
285
- await confirmBtn.click();
107
+ const result = await testdriver.assert('Notepad shows "Hello from TestDriver"');
108
+ expect(result).toBe(true);
286
109
  });
287
110
  });
288
111
  ```
289
112
 
290
- ## Related Methods
113
+ ## Related
291
114
 
292
- - [`exec()`](/exec) - Launch applications with PowerShell
293
- - [`pressKeys()`](/press-keys) - Use Alt+Tab to switch windows
294
- - [`find()`](/find) - Locate elements in the focused window
115
+ - [Launch apps](/provision): open an app and focus it in one step
116
+ - [exec()](/exec): start an app with a shell command
117
+ - [pressKeys()](/press-keys): switch windows with keyboard shortcuts
@@ -1,192 +1,158 @@
1
1
  ---
2
- title: "Explore"
2
+ title: "Generate tests with AI"
3
3
  sidebarTitle: "Generating tests"
4
- description: "Generate tests by exploring your app with the AI vision agent"
4
+ description: "Describe a flow in plain language, and the agent writes and runs the test."
5
5
  icon: "compass"
6
6
  ---
7
7
 
8
- Start with an exploration of your app. Tests begin here: you describe a flow in plain English. Then the TestDriver vision agent clicks, types, and reads the screen to understand it. Then it writes the test for you. There are no selectors, no DOM, and no weak locators. Only describe what you want to test. Let the agent find the other parts.
8
+ Describe a flow in plain language, and the TestDriver agent writes the test for you.
9
9
 
10
- There are two methods for an exploration. You can chat with your AI assistant through the TestDriver MCP server. Or you can give a coding agent our instructions file and tell it to generate a test.
10
+ - The agent runs in your AI coding assistant.
11
+ - It runs the flow in a live sandbox and writes a Vitest test.
12
+ - It finds elements by looking at the screen, so you never write selectors.
11
13
 
12
- <Info>
13
- Both paths need an MCP-capable AI coding assistant. If you don't have one yet, start with **GitHub Copilot** — there's a [free tier](https://github.com/features/copilot/plans), no credit card required. See [Run → Setup](/copilot/running-tests#setup) for the full install and sign-in walkthrough.
14
- </Info>
14
+ ## Before you begin
15
15
 
16
- ## Instructions for Coding Agents
16
+ Install TestDriver in an AI coding assistant that can edit files in your repository:
17
17
 
18
- Start with [our quickstart](./quickstart). Then give your coding agent our agent instructions file.
18
+ - **Claude Code:** [install the plugin](/quickstart-claude).
19
+ - **VS Code or Cursor:** [install the extension](/quickstart-vscode).
20
+ - **Any other assistant:** run `npx testdriverai init` in your repository and choose your assistant. See [Set up a project](/quickstart-manual).
19
21
 
20
- <Card title="TestDriver Agent Instructions" icon="link" arrow="true" horizontal href="https://github.com/testdriverai/testdriverai/blob/main/ai/agents/testdriver.md?plain=1">
21
- Copy the current version of our agent instructions to provide your coding agent with up-to-date instructions on how to generate TestDriver tests.
22
- </Card>
22
+ ## Start the agent
23
23
 
24
- Then, you can prompt your coding agent to generate tests. Here is an example prompt:
24
+ Ask for the TestDriver agent by name in your assistant's chat:
25
25
 
26
- ```md
27
- Make me a TestDriver test that does the following steps:
28
-
29
- Navigate to practicetestautomation.com
30
- Type username student into Username field
31
- Type password Password123 into Password field
32
- Push Submit button
33
- Verify new page contains expected text 'logged in'
34
- ```
35
-
36
- <Info>Use explicit commands for production tests. They are at a lower cost, faster, and more reliable.</Info>
37
-
38
- ## Start a Conversation
39
-
40
- Use the TestDriver MCP server and your AI assistant (GitHub Copilot, Cursor, or Claude Desktop) to make tests. You chat with an AI agent. The agent starts a virtual machine, does actions, and writes the test code for you.
41
-
42
- Open the chat of your AI assistant. If your project has no other agents, TestDriver uses the TestDriver agent by default. If not, select **testdriver** from the agent dropdown in the chat panel.
43
-
44
- Describe what you want to test:
45
-
46
- ```
47
- Create a test that logs into my app at https://myapp.com
26
+ ```text
27
+ Use the testdriver agent to write a test that logs in to https://testdriver-sandbox.vercel.app/login
48
28
  ```
49
29
 
50
- The agent will:
51
- 1. Start a new session and spawn a Linux virtual machine
52
- 2. Launch Chrome and navigate to your URL
53
- 3. Execute actions based on your instructions
54
- 4. Write the test code to a `.test.mjs` file
30
+ In VS Code, you can also pick **testdriver** from the agent dropdown in the Copilot chat panel.
55
31
 
56
- <Note>
57
- The TestDriver agent appears in the agent selection dropdown if you have other agents configured (like `copilot-instructions.md` or other `.agent.md` files). Make sure to select **testdriver** to use TestDriver's MCP tools.
58
- </Note>
32
+ If your assistant doesn't support agent files, give it the [TestDriver agent instructions](https://github.com/testdriverai/testdriverai/blob/main/ai/agents/testdriver.md?plain=1) directly.
59
33
 
60
- ## Live Preview Panel
34
+ ## Describe the test
61
35
 
62
- When the agent starts a session, a **live preview panel** opens in your editor. This lets you:
36
+ Write the flow as the steps a user takes and what they should see at the end.
63
37
 
64
- - **Watch tests execute** in real-time
65
- - **Interact with the VM** — click, type, and navigate manually
66
- - **Debug issues** — see exactly what the AI sees
38
+ Explicit steps make a test faster, cheaper, and more reliable than one where the agent works out the flow itself:
67
39
 
68
- <Note>
69
- The live preview panel requires the TestDriver VS Code extension. Set `TD_PREVIEW=ide` in your MCP configuration to enable it. See the [Run page](/copilot/running-tests) for all device and preview options.
70
- </Note>
40
+ ```text
41
+ Write a TestDriver test that does the following:
71
42
 
72
- ## Interactive Workflow
73
-
74
- The recommended workflow for exploring and creating tests:
75
-
76
- <Steps>
77
- <Step title="Describe Your Test">
78
- Tell the agent what you want to test:
79
-
80
- ```
81
- Test the checkout flow on https://shop.example.com
82
- ```
83
- </Step>
84
-
85
- <Step title="Watch and Guide">
86
- The agent will start executing. Watch the preview panel and provide guidance if needed:
87
-
88
- ```
89
- The login modal appeared. Use test@example.com and password123
90
- ```
91
- </Step>
92
-
93
- <Step title="Add Assertions">
94
- Ask the agent to verify specific conditions:
43
+ 1. Open https://practicetestautomation.com/practice-test-login/
44
+ 2. Type "student" into the Username field
45
+ 3. Type "Password123" into the Password field
46
+ 4. Click the Submit button
47
+ 5. Verify the new page says "Logged In Successfully"
48
+ ```
95
49
 
96
- ```
97
- Assert that the order confirmation page is shown with the order number
98
- ```
99
- </Step>
50
+ ## Watch and steer the run
100
51
 
101
- <Step title="Review the Code">
102
- The agent writes test code as it works. Review the generated `.test.mjs` file and make any adjustments.
103
- </Step>
104
- </Steps>
52
+ The agent sends a screenshot after every action, so you see what it sees.
105
53
 
106
- ## Example Conversation
54
+ - In clients that support MCP Apps, each screenshot appears inline in the chat, with the targeted element highlighted.
55
+ - With the [TestDriver extension](/quickstart-vscode) in VS Code or Cursor, the sandbox also plays live in a panel beside your code.
107
56
 
108
- Here's a complete example of exploring and creating a login test:
57
+ If the agent gets stuck or takes a wrong turn, tell it what to do next:
109
58
 
59
+ ```text
60
+ A cookie banner is covering the form. Accept it, then continue.
110
61
  ```
111
- You: Create a test for the login flow at https://console.testdriver.ai
112
-
113
- Agent: I'll create a test for the login flow. Starting a session...
114
- [Screenshot: Login page loaded]
115
62
 
116
- I can see the login page. Let me find the email input.
117
- [Screenshot: Email input highlighted]
63
+ You can also ask for more checks at any point:
118
64
 
119
- Now I'll type the email and find the password field...
120
-
121
- You: Use test@example.com for the email
122
-
123
- Agent: Got it. Typing test@example.com...
124
- [Screenshot: Email entered]
65
+ ```text
66
+ Also assert that the page shows a Log out button.
67
+ ```
125
68
 
126
- Now entering the password and clicking Sign In...
127
- [Screenshot: Dashboard loaded]
69
+ ## What the agent does
128
70
 
129
- ✅ Login successful! I've written the test to tests/login.test.mjs
130
- ```
71
+ 1. **Starts a session.** It provisions a sandbox (Linux by default) and opens your app, for example Chrome at the URL you gave it.
72
+ 2. **Performs each step.** It finds each element from a description, acts on it, and checks the screenshot to confirm the step worked.
73
+ 3. **Writes code as it goes.** After each successful action, it appends the matching SDK code to a test file under `tests/`. The file always reflects what has actually run.
74
+ 4. **Runs the test.** It runs the file with `vitest run` and keeps fixing it until it passes.
131
75
 
132
- ## Generated Test Code
76
+ ## Review the generated test
133
77
 
134
- The agent generates standard Vitest test files:
78
+ The result is an ordinary Vitest file. Read, edit, commit, and run it in CI like any other test:
135
79
 
136
80
  ```javascript tests/login.test.mjs
137
- import { describe, expect, it } from "vitest";
138
- import { TestDriver } from "testdriverai/vitest/hooks";
81
+ import { describe, expect, it } from 'vitest';
82
+ import { TestDriver } from 'testdriverai/vitest/hooks';
139
83
 
140
- describe("Login Flow", () => {
141
- it("should log in successfully", async (context) => {
84
+ describe('Practice login', () => {
85
+ it('logs in with valid credentials', async (context) => {
142
86
  const testdriver = TestDriver(context);
143
87
 
144
88
  await testdriver.provision.chrome({
145
- url: "https://console.testdriver.ai"
89
+ url: 'https://practicetestautomation.com/practice-test-login/',
146
90
  });
147
91
 
148
- const emailInput = await testdriver.find("email input field");
149
- await emailInput.click();
150
- await testdriver.type("test@example.com");
92
+ const usernameField = await testdriver.find('Username input field');
93
+ await usernameField.click();
94
+ await testdriver.type('student');
151
95
 
152
- const passwordInput = await testdriver.find("password input field");
153
- await passwordInput.click();
154
- await testdriver.type("password123");
96
+ const passwordField = await testdriver.find('Password input field');
97
+ await passwordField.click();
98
+ await testdriver.type('Password123', { secret: true });
155
99
 
156
- const signInButton = await testdriver.find("Sign In button");
157
- await signInButton.click();
100
+ const submitButton = await testdriver.find('Submit button');
101
+ await submitButton.click();
158
102
 
159
- const result = await testdriver.assert("dashboard is visible");
160
- expect(result).toBeTruthy();
103
+ const result = await testdriver.assert('the page says "Logged In Successfully"');
104
+ expect(result).toBe(true);
161
105
  });
162
106
  });
163
107
  ```
164
108
 
165
- ## Tips for Better Tests
109
+ Before you commit, check two things:
110
+
111
+ - Each `find()` description would still pick the right element if the page changed.
112
+ - The assertions cover what you care about.
113
+
114
+ <Tip>
115
+ If the test calls `ai()`, which works out a step on its own at run time, ask the agent to replace it with explicit `find()`, `click()`, and `type()` steps before you commit. Explicit steps run faster and do the same thing every time.
116
+ </Tip>
117
+
118
+ ## Tips for better tests
166
119
 
167
120
  <AccordionGroup>
168
- <Accordion title="Be specific with element descriptions">
169
- Instead of "click the button", say "click the blue Sign In button in the header". More context helps the AI find the right element.
121
+ <Accordion title="Describe elements by what they look like">
122
+
123
+ "The blue Sign In button in the header" works better than "the button". Include the visible label. Add position or color when several elements look alike. See [Locate elements](/locating-elements).
124
+
170
125
  </Accordion>
171
- <Accordion title="Add waits for dynamic content">
172
- If your app has animations or loading states, tell the agent to wait:
173
- ```
174
- Wait for the loading spinner to disappear before continuing
175
- ```
126
+ <Accordion title="Mention loading and animations">
127
+
128
+ If part of your app loads slowly, say so. For example: "wait for the loading spinner to disappear before continuing". The agent then waits instead of acting too early.
129
+
176
130
  </Accordion>
177
- <Accordion title="Use assertions liberally">
178
- Add assertions after each major action to catch regressions early:
179
- ```
180
- Assert that the product was added to the cart
181
- ```
131
+ <Accordion title="Assert after each important step">
132
+
133
+ Assert after each meaningful action, such as "the item appears in the cart". When the test fails later, you see where the regression starts.
134
+
182
135
  </Accordion>
183
- <Accordion title="Break complex flows into steps">
184
- For long workflows, create the test incrementally and verify each step works before moving on.
136
+ <Accordion title="Build long flows in pieces">
137
+
138
+ Don't describe a long workflow all at once. Have the agent get the first part passing, then describe the next.
139
+
185
140
  </Accordion>
186
141
  </AccordionGroup>
187
142
 
188
- ## Next
189
-
190
- <Card title="Learn" icon="brain" arrow="true" horizontal href="/caching">
191
- Once the agent has explored your app, TestDriver caches what it discovers so your tests replay instantly without re-reasoning over the screen every time.
192
- </Card>
143
+ ## Next steps
144
+
145
+ <CardGroup cols={2}>
146
+ <Card title="Run tests" icon="play" href="/copilot/running-tests">
147
+ Choose a device, preview mode, and how to run your tests.
148
+ </Card>
149
+ <Card title="Speed up reruns with caching" icon="bolt" href="/caching">
150
+ Reuse what TestDriver found so reruns skip the AI.
151
+ </Card>
152
+ <Card title="Make assertions" icon="circle-check" href="/making-assertions">
153
+ Write checks that catch the regressions you care about.
154
+ </Card>
155
+ <Card title="Run in CI/CD" icon="code-branch" href="/ci-cd">
156
+ Run generated tests on every pull request.
157
+ </Card>
158
+ </CardGroup>