@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,293 +1,116 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: testdriver:focus-application
|
|
3
|
-
description: Bring an application window to the
|
|
3
|
+
description: Bring an open application window to the front of the sandbox desktop.
|
|
4
4
|
---
|
|
5
5
|
<!-- Generated from focus-application.mdx. DO NOT EDIT. -->
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Bring an app's window to the front, so your next clicks and keystrokes go to it.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```javascript
|
|
10
|
+
await testdriver.focusApplication('Google Chrome');
|
|
11
|
+
```
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
Use it when your test works across several apps, or after a dialog or another window has taken focus.
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
<Note>
|
|
16
|
+
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()`.
|
|
17
|
+
</Note>
|
|
18
|
+
|
|
19
|
+
## Signature
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
testdriver.focusApplication(name: string, options?: object): Promise<string>
|
|
15
23
|
```
|
|
16
24
|
|
|
17
25
|
## Parameters
|
|
18
26
|
|
|
19
27
|
<ParamField path="name" type="string" required>
|
|
20
|
-
The
|
|
28
|
+
The app's name, as it appears in its window title. For example `'Google Chrome'`, `'Notepad'`, or `'Visual Studio Code'`.
|
|
29
|
+
</ParamField>
|
|
30
|
+
|
|
31
|
+
<ParamField path="options" type="object">
|
|
32
|
+
<Expandable title="properties">
|
|
33
|
+
<ParamField path="redraw" type="boolean | object">
|
|
34
|
+
Wait for the screen to settle after focusing. Uses the client's setting when you leave it out. See [Redraw](/redraw).
|
|
35
|
+
</ParamField>
|
|
36
|
+
</Expandable>
|
|
21
37
|
</ParamField>
|
|
22
38
|
|
|
23
39
|
## Returns
|
|
24
40
|
|
|
25
|
-
`Promise<string
|
|
41
|
+
`Promise<string>`. Always resolves to `"The application was focused."`.
|
|
26
42
|
|
|
27
|
-
##
|
|
43
|
+
## Errors
|
|
44
|
+
|
|
45
|
+
`focusApplication()` doesn't throw when no window matches. It returns the same message either way.
|
|
28
46
|
|
|
29
|
-
|
|
47
|
+
To confirm the right app is in front, follow it with an [`assert()`](/assert):
|
|
30
48
|
|
|
31
49
|
```javascript
|
|
32
|
-
|
|
33
|
-
await testdriver.
|
|
50
|
+
await testdriver.focusApplication('Notepad');
|
|
51
|
+
await testdriver.assert('a Notepad window is in the foreground');
|
|
52
|
+
```
|
|
34
53
|
|
|
35
|
-
|
|
36
|
-
await testdriver.focusApplication('Microsoft Edge');
|
|
54
|
+
## How it matches windows
|
|
37
55
|
|
|
38
|
-
|
|
39
|
-
|
|
56
|
+
- **Windows:** TestDriver looks for windows whose title contains `name`. It restores a minimized window, then brings it to the front.
|
|
57
|
+
- **Linux:** TestDriver runs `jumpapp -f <name>`. If that fails, it activates the first window whose title matches `name`, using `xdotool`.
|
|
40
58
|
|
|
41
|
-
|
|
42
|
-
await testdriver.focusApplication('File Explorer');
|
|
59
|
+
The app must already be running. Launch it first with [`provision`](/provision) or [`exec()`](/exec).
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
await testdriver.focusApplication('Visual Studio Code');
|
|
46
|
-
```
|
|
61
|
+
## Examples
|
|
47
62
|
|
|
48
|
-
###
|
|
63
|
+
### Switch between two apps
|
|
49
64
|
|
|
50
65
|
```javascript
|
|
51
|
-
|
|
52
|
-
await testdriver.exec('pwsh', `
|
|
53
|
-
Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "https://example.com"
|
|
54
|
-
`, 5000);
|
|
66
|
+
const orderNumber = await testdriver.extract('the order number');
|
|
55
67
|
|
|
56
|
-
await
|
|
68
|
+
await testdriver.focusApplication('Notepad');
|
|
69
|
+
await testdriver.type(orderNumber);
|
|
57
70
|
|
|
58
|
-
// Focus the Chrome window
|
|
59
71
|
await testdriver.focusApplication('Google Chrome');
|
|
72
|
+
await testdriver.find('Confirm order button').click();
|
|
60
73
|
```
|
|
61
74
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
<Check>
|
|
65
|
-
**Focus before UI interactions**
|
|
66
|
-
|
|
67
|
-
Always focus the target application before interacting with its UI:
|
|
68
|
-
|
|
69
|
-
```javascript
|
|
70
|
-
await testdriver.focusApplication('Google Chrome');
|
|
71
|
-
|
|
72
|
-
const button = await testdriver.find('submit button');
|
|
73
|
-
await button.click();
|
|
74
|
-
```
|
|
75
|
-
</Check>
|
|
76
|
-
|
|
77
|
-
<Check>
|
|
78
|
-
**Wait after launching apps**
|
|
79
|
-
|
|
80
|
-
Give applications time to open before focusing:
|
|
81
|
-
|
|
82
|
-
```javascript
|
|
83
|
-
await testdriver.exec('pwsh', 'Start-Process notepad', 5000);
|
|
84
|
-
await new Promise(r => setTimeout(r, 1000)); // Wait for launch
|
|
85
|
-
await testdriver.focusApplication('Notepad');
|
|
86
|
-
```
|
|
87
|
-
</Check>
|
|
88
|
-
|
|
89
|
-
<Check>
|
|
90
|
-
**Use exact application names**
|
|
91
|
-
|
|
92
|
-
```javascript
|
|
93
|
-
// ✅ Correct
|
|
94
|
-
await testdriver.focusApplication('Google Chrome');
|
|
95
|
-
|
|
96
|
-
// ❌ May not work
|
|
97
|
-
await testdriver.focusApplication('Chrome');
|
|
98
|
-
await testdriver.focusApplication('chrome.exe');
|
|
99
|
-
```
|
|
100
|
-
</Check>
|
|
101
|
-
|
|
102
|
-
<Warning>
|
|
103
|
-
**Application must be running**
|
|
104
|
-
|
|
105
|
-
The application must already be running. `focusApplication()` won't launch applications, only bring existing windows to the foreground.
|
|
106
|
-
</Warning>
|
|
107
|
-
|
|
108
|
-
## Use Cases
|
|
109
|
-
|
|
110
|
-
<AccordionGroup>
|
|
111
|
-
<Accordion title="Multi-Application Testing">
|
|
112
|
-
```javascript
|
|
113
|
-
// Test workflow across multiple apps
|
|
114
|
-
await testdriver.focusApplication('Google Chrome');
|
|
115
|
-
const data = await testdriver.extract('the order number');
|
|
116
|
-
|
|
117
|
-
await testdriver.focusApplication('Notepad');
|
|
118
|
-
await testdriver.type(data);
|
|
119
|
-
await testdriver.pressKeys(['ctrl', 's']);
|
|
120
|
-
|
|
121
|
-
await testdriver.focusApplication('Google Chrome');
|
|
122
|
-
const nextButton = await testdriver.find('next button');
|
|
123
|
-
await nextButton.click();
|
|
124
|
-
```
|
|
125
|
-
</Accordion>
|
|
126
|
-
|
|
127
|
-
<Accordion title="Browser Switching">
|
|
128
|
-
```javascript
|
|
129
|
-
// Compare behavior in different browsers
|
|
130
|
-
await testdriver.focusApplication('Google Chrome');
|
|
131
|
-
await testdriver.assert('page loaded correctly in Chrome');
|
|
132
|
-
|
|
133
|
-
await testdriver.focusApplication('Microsoft Edge');
|
|
134
|
-
await testdriver.assert('page loaded correctly in Edge');
|
|
135
|
-
```
|
|
136
|
-
</Accordion>
|
|
137
|
-
|
|
138
|
-
<Accordion title="Desktop Application Testing">
|
|
139
|
-
```javascript
|
|
140
|
-
// Launch and focus desktop app
|
|
141
|
-
await testdriver.exec('pwsh', 'Start-Process notepad', 5000);
|
|
142
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
143
|
-
|
|
144
|
-
await testdriver.focusApplication('Notepad');
|
|
145
|
-
await testdriver.type('Test content');
|
|
146
|
-
```
|
|
147
|
-
</Accordion>
|
|
148
|
-
|
|
149
|
-
<Accordion title="Window Management">
|
|
150
|
-
```javascript
|
|
151
|
-
// Show desktop first
|
|
152
|
-
await testdriver.pressKeys(['winleft', 'd']);
|
|
153
|
-
|
|
154
|
-
// Click desktop icon
|
|
155
|
-
const icon = await testdriver.find('Chrome icon on desktop');
|
|
156
|
-
await icon.click();
|
|
157
|
-
|
|
158
|
-
await new Promise(r => setTimeout(r, 2000));
|
|
159
|
-
|
|
160
|
-
// Focus the opened window
|
|
161
|
-
await testdriver.focusApplication('Google Chrome');
|
|
162
|
-
```
|
|
163
|
-
</Accordion>
|
|
164
|
-
</AccordionGroup>
|
|
165
|
-
|
|
166
|
-
## Common Application Names
|
|
167
|
-
|
|
168
|
-
### Browsers
|
|
169
|
-
- `'Google Chrome'`
|
|
170
|
-
- `'Microsoft Edge'`
|
|
171
|
-
- `'Mozilla Firefox'`
|
|
172
|
-
- `'Safari'` (macOS)
|
|
173
|
-
|
|
174
|
-
### Office Applications
|
|
175
|
-
- `'Microsoft Word'`
|
|
176
|
-
- `'Microsoft Excel'`
|
|
177
|
-
- `'Microsoft PowerPoint'`
|
|
178
|
-
- `'Microsoft Outlook'`
|
|
179
|
-
|
|
180
|
-
### Development Tools
|
|
181
|
-
- `'Visual Studio Code'`
|
|
182
|
-
- `'Visual Studio'`
|
|
183
|
-
- `'IntelliJ IDEA'`
|
|
184
|
-
- `'Sublime Text'`
|
|
185
|
-
|
|
186
|
-
### System Applications
|
|
187
|
-
- `'Notepad'`
|
|
188
|
-
- `'File Explorer'`
|
|
189
|
-
- `'Command Prompt'`
|
|
190
|
-
- `'Windows PowerShell'`
|
|
191
|
-
- `'Task Manager'`
|
|
192
|
-
|
|
193
|
-
### Communication
|
|
194
|
-
- `'Microsoft Teams'`
|
|
195
|
-
- `'Slack'`
|
|
196
|
-
- `'Discord'`
|
|
197
|
-
- `'Zoom'`
|
|
198
|
-
|
|
199
|
-
## Complete Example
|
|
75
|
+
### Launch an app and focus it on Windows
|
|
200
76
|
|
|
201
77
|
```javascript
|
|
202
|
-
|
|
203
|
-
|
|
78
|
+
await testdriver.exec({ language: 'pwsh', code: 'Start-Process notepad' });
|
|
79
|
+
await testdriver.focusApplication('Notepad');
|
|
80
|
+
await testdriver.type('Meeting notes');
|
|
81
|
+
```
|
|
204
82
|
|
|
205
|
-
|
|
206
|
-
let testdriver;
|
|
83
|
+
### Return to the browser after a dialog
|
|
207
84
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
});
|
|
85
|
+
```javascript
|
|
86
|
+
await testdriver.find('Download report button').click();
|
|
87
|
+
await testdriver.focusApplication('Google Chrome');
|
|
88
|
+
```
|
|
213
89
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
90
|
+
## Complete example
|
|
91
|
+
|
|
92
|
+
```javascript tests/notepad.test.mjs
|
|
93
|
+
import { describe, expect, it } from 'vitest';
|
|
94
|
+
import { TestDriver } from 'testdriverai/vitest/hooks';
|
|
217
95
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
console.log('Order:', orderNumber);
|
|
225
|
-
|
|
226
|
-
// Open Notepad
|
|
227
|
-
await testdriver.exec('pwsh', 'Start-Process notepad', 5000);
|
|
228
|
-
await new Promise(r => setTimeout(r, 1500));
|
|
229
|
-
|
|
230
|
-
// Focus Notepad and save data
|
|
96
|
+
describe('Notepad', () => {
|
|
97
|
+
it('types into Notepad', async (context) => {
|
|
98
|
+
// Windows sandboxes are available on Enterprise plans
|
|
99
|
+
const testdriver = TestDriver(context, { os: 'windows' });
|
|
100
|
+
|
|
101
|
+
await testdriver.exec({ language: 'pwsh', code: 'Start-Process notepad' });
|
|
231
102
|
await testdriver.focusApplication('Notepad');
|
|
232
|
-
await testdriver.type(`Order Number: ${orderNumber}`);
|
|
233
|
-
await testdriver.type('\n');
|
|
234
|
-
await testdriver.type(`Date: ${new Date().toISOString()}`);
|
|
235
|
-
|
|
236
|
-
// Save file
|
|
237
|
-
await testdriver.pressKeys(['ctrl', 's']);
|
|
238
|
-
await new Promise(r => setTimeout(r, 500));
|
|
239
|
-
|
|
240
|
-
await testdriver.type('C:\\order-info.txt');
|
|
241
|
-
await testdriver.pressKeys(['enter']);
|
|
242
|
-
|
|
243
|
-
// Return to browser
|
|
244
|
-
await testdriver.focusApplication('Google Chrome');
|
|
245
|
-
|
|
246
|
-
const confirmButton = await testdriver.find('confirm order button');
|
|
247
|
-
await confirmButton.click();
|
|
248
|
-
|
|
249
|
-
await testdriver.assert('order confirmed');
|
|
250
|
-
});
|
|
251
103
|
|
|
252
|
-
|
|
253
|
-
await testdriver.focusApplication('Google Chrome');
|
|
254
|
-
|
|
255
|
-
// Open new tab
|
|
256
|
-
await testdriver.pressKeys(['ctrl', 't']);
|
|
257
|
-
await new Promise(r => setTimeout(r, 500));
|
|
258
|
-
|
|
259
|
-
// Navigate to URL
|
|
260
|
-
await testdriver.pressKeys(['ctrl', 'l']);
|
|
261
|
-
await testdriver.type('https://example.com');
|
|
262
|
-
await testdriver.pressKeys(['enter']);
|
|
263
|
-
|
|
264
|
-
await new Promise(r => setTimeout(r, 2000));
|
|
265
|
-
|
|
266
|
-
// Ensure Chrome is still focused
|
|
267
|
-
await testdriver.focusApplication('Google Chrome');
|
|
268
|
-
|
|
269
|
-
await testdriver.assert('example.com page is loaded');
|
|
270
|
-
});
|
|
104
|
+
await testdriver.type('Hello from TestDriver');
|
|
271
105
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const deleteButton = await testdriver.find('delete account button');
|
|
276
|
-
await deleteButton.click();
|
|
277
|
-
|
|
278
|
-
await new Promise(r => setTimeout(r, 500));
|
|
279
|
-
|
|
280
|
-
// Dialog appears - make sure it's focused
|
|
281
|
-
await testdriver.focusApplication('Google Chrome');
|
|
282
|
-
|
|
283
|
-
const confirmBtn = await testdriver.find('confirm deletion button');
|
|
284
|
-
await confirmBtn.click();
|
|
106
|
+
const result = await testdriver.assert('Notepad shows "Hello from TestDriver"');
|
|
107
|
+
expect(result).toBe(true);
|
|
285
108
|
});
|
|
286
109
|
});
|
|
287
110
|
```
|
|
288
111
|
|
|
289
|
-
## Related
|
|
112
|
+
## Related
|
|
290
113
|
|
|
291
|
-
- [
|
|
292
|
-
- [
|
|
293
|
-
- [
|
|
114
|
+
- [Launch apps](/provision): open an app and focus it in one step
|
|
115
|
+
- [exec()](/exec): start an app with a shell command
|
|
116
|
+
- [pressKeys()](/press-keys): switch windows with keyboard shortcuts
|
|
@@ -1,191 +1,157 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: testdriver:generating-tests
|
|
3
|
-
description:
|
|
3
|
+
description: Describe a flow in plain language, and the agent writes and runs the test.
|
|
4
4
|
---
|
|
5
5
|
<!-- Generated from generating-tests.mdx. DO NOT EDIT. -->
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Describe a flow in plain language, and the TestDriver agent writes the test for you.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- The agent runs in your AI coding assistant.
|
|
10
|
+
- It runs the flow in a live sandbox and writes a Vitest test.
|
|
11
|
+
- It finds elements by looking at the screen, so you never write selectors.
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
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.
|
|
13
|
-
</Info>
|
|
13
|
+
## Before you begin
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Install TestDriver in an AI coding assistant that can edit files in your repository:
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
- **Claude Code:** [install the plugin](/quickstart-claude).
|
|
18
|
+
- **VS Code or Cursor:** [install the extension](/quickstart-vscode).
|
|
19
|
+
- **Any other assistant:** run `npx testdriverai init` in your repository and choose your assistant. See [Set up a project](/quickstart-manual).
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
Copy the current version of our agent instructions to provide your coding agent with up-to-date instructions on how to generate TestDriver tests.
|
|
21
|
-
</Card>
|
|
21
|
+
## Start the agent
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Ask for the TestDriver agent by name in your assistant's chat:
|
|
24
24
|
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Navigate to practicetestautomation.com
|
|
29
|
-
Type username student into Username field
|
|
30
|
-
Type password Password123 into Password field
|
|
31
|
-
Push Submit button
|
|
32
|
-
Verify new page contains expected text 'logged in'
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
<Info>Use explicit commands for production tests. They are at a lower cost, faster, and more reliable.</Info>
|
|
36
|
-
|
|
37
|
-
## Start a Conversation
|
|
38
|
-
|
|
39
|
-
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.
|
|
40
|
-
|
|
41
|
-
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.
|
|
42
|
-
|
|
43
|
-
Describe what you want to test:
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
Create a test that logs into my app at https://myapp.com
|
|
25
|
+
```text
|
|
26
|
+
Use the testdriver agent to write a test that logs in to https://testdriver-sandbox.vercel.app/login
|
|
47
27
|
```
|
|
48
28
|
|
|
49
|
-
|
|
50
|
-
1. Start a new session and spawn a Linux virtual machine
|
|
51
|
-
2. Launch Chrome and navigate to your URL
|
|
52
|
-
3. Execute actions based on your instructions
|
|
53
|
-
4. Write the test code to a `.test.mjs` file
|
|
29
|
+
In VS Code, you can also pick **testdriver** from the agent dropdown in the Copilot chat panel.
|
|
54
30
|
|
|
55
|
-
|
|
56
|
-
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.
|
|
57
|
-
</Note>
|
|
31
|
+
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.
|
|
58
32
|
|
|
59
|
-
##
|
|
33
|
+
## Describe the test
|
|
60
34
|
|
|
61
|
-
|
|
35
|
+
Write the flow as the steps a user takes and what they should see at the end.
|
|
62
36
|
|
|
63
|
-
|
|
64
|
-
- **Interact with the VM** — click, type, and navigate manually
|
|
65
|
-
- **Debug issues** — see exactly what the AI sees
|
|
37
|
+
Explicit steps make a test faster, cheaper, and more reliable than one where the agent works out the flow itself:
|
|
66
38
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
</Note>
|
|
39
|
+
```text
|
|
40
|
+
Write a TestDriver test that does the following:
|
|
70
41
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Tell the agent what you want to test:
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
Test the checkout flow on https://shop.example.com
|
|
81
|
-
```
|
|
82
|
-
</Step>
|
|
83
|
-
|
|
84
|
-
<Step title="Watch and Guide">
|
|
85
|
-
The agent will start executing. Watch the preview panel and provide guidance if needed:
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
The login modal appeared. Use test@example.com and password123
|
|
89
|
-
```
|
|
90
|
-
</Step>
|
|
91
|
-
|
|
92
|
-
<Step title="Add Assertions">
|
|
93
|
-
Ask the agent to verify specific conditions:
|
|
42
|
+
1. Open https://practicetestautomation.com/practice-test-login/
|
|
43
|
+
2. Type "student" into the Username field
|
|
44
|
+
3. Type "Password123" into the Password field
|
|
45
|
+
4. Click the Submit button
|
|
46
|
+
5. Verify the new page says "Logged In Successfully"
|
|
47
|
+
```
|
|
94
48
|
|
|
95
|
-
|
|
96
|
-
Assert that the order confirmation page is shown with the order number
|
|
97
|
-
```
|
|
98
|
-
</Step>
|
|
49
|
+
## Watch and steer the run
|
|
99
50
|
|
|
100
|
-
|
|
101
|
-
The agent writes test code as it works. Review the generated `.test.mjs` file and make any adjustments.
|
|
102
|
-
</Step>
|
|
103
|
-
</Steps>
|
|
51
|
+
The agent sends a screenshot after every action, so you see what it sees.
|
|
104
52
|
|
|
105
|
-
|
|
53
|
+
- In clients that support MCP Apps, each screenshot appears inline in the chat, with the targeted element highlighted.
|
|
54
|
+
- With the [TestDriver extension](/quickstart-vscode) in VS Code or Cursor, the sandbox also plays live in a panel beside your code.
|
|
106
55
|
|
|
107
|
-
|
|
56
|
+
If the agent gets stuck or takes a wrong turn, tell it what to do next:
|
|
108
57
|
|
|
58
|
+
```text
|
|
59
|
+
A cookie banner is covering the form. Accept it, then continue.
|
|
109
60
|
```
|
|
110
|
-
You: Create a test for the login flow at https://console.testdriver.ai
|
|
111
|
-
|
|
112
|
-
Agent: I'll create a test for the login flow. Starting a session...
|
|
113
|
-
[Screenshot: Login page loaded]
|
|
114
61
|
|
|
115
|
-
|
|
116
|
-
[Screenshot: Email input highlighted]
|
|
62
|
+
You can also ask for more checks at any point:
|
|
117
63
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
Agent: Got it. Typing test@example.com...
|
|
123
|
-
[Screenshot: Email entered]
|
|
64
|
+
```text
|
|
65
|
+
Also assert that the page shows a Log out button.
|
|
66
|
+
```
|
|
124
67
|
|
|
125
|
-
|
|
126
|
-
[Screenshot: Dashboard loaded]
|
|
68
|
+
## What the agent does
|
|
127
69
|
|
|
128
|
-
|
|
129
|
-
|
|
70
|
+
1. **Starts a session.** It provisions a sandbox (Linux by default) and opens your app, for example Chrome at the URL you gave it.
|
|
71
|
+
2. **Performs each step.** It finds each element from a description, acts on it, and checks the screenshot to confirm the step worked.
|
|
72
|
+
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.
|
|
73
|
+
4. **Runs the test.** It runs the file with `vitest run` and keeps fixing it until it passes.
|
|
130
74
|
|
|
131
|
-
##
|
|
75
|
+
## Review the generated test
|
|
132
76
|
|
|
133
|
-
The
|
|
77
|
+
The result is an ordinary Vitest file. Read, edit, commit, and run it in CI like any other test:
|
|
134
78
|
|
|
135
79
|
```javascript tests/login.test.mjs
|
|
136
|
-
import { describe, expect, it } from
|
|
137
|
-
import { TestDriver } from
|
|
80
|
+
import { describe, expect, it } from 'vitest';
|
|
81
|
+
import { TestDriver } from 'testdriverai/vitest/hooks';
|
|
138
82
|
|
|
139
|
-
describe(
|
|
140
|
-
it(
|
|
83
|
+
describe('Practice login', () => {
|
|
84
|
+
it('logs in with valid credentials', async (context) => {
|
|
141
85
|
const testdriver = TestDriver(context);
|
|
142
86
|
|
|
143
87
|
await testdriver.provision.chrome({
|
|
144
|
-
url:
|
|
88
|
+
url: 'https://practicetestautomation.com/practice-test-login/',
|
|
145
89
|
});
|
|
146
90
|
|
|
147
|
-
const
|
|
148
|
-
await
|
|
149
|
-
await testdriver.type(
|
|
91
|
+
const usernameField = await testdriver.find('Username input field');
|
|
92
|
+
await usernameField.click();
|
|
93
|
+
await testdriver.type('student');
|
|
150
94
|
|
|
151
|
-
const
|
|
152
|
-
await
|
|
153
|
-
await testdriver.type(
|
|
95
|
+
const passwordField = await testdriver.find('Password input field');
|
|
96
|
+
await passwordField.click();
|
|
97
|
+
await testdriver.type('Password123', { secret: true });
|
|
154
98
|
|
|
155
|
-
const
|
|
156
|
-
await
|
|
99
|
+
const submitButton = await testdriver.find('Submit button');
|
|
100
|
+
await submitButton.click();
|
|
157
101
|
|
|
158
|
-
const result = await testdriver.assert("
|
|
159
|
-
expect(result).
|
|
102
|
+
const result = await testdriver.assert('the page says "Logged In Successfully"');
|
|
103
|
+
expect(result).toBe(true);
|
|
160
104
|
});
|
|
161
105
|
});
|
|
162
106
|
```
|
|
163
107
|
|
|
164
|
-
|
|
108
|
+
Before you commit, check two things:
|
|
109
|
+
|
|
110
|
+
- Each `find()` description would still pick the right element if the page changed.
|
|
111
|
+
- The assertions cover what you care about.
|
|
112
|
+
|
|
113
|
+
<Tip>
|
|
114
|
+
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.
|
|
115
|
+
</Tip>
|
|
116
|
+
|
|
117
|
+
## Tips for better tests
|
|
165
118
|
|
|
166
119
|
<AccordionGroup>
|
|
167
|
-
<Accordion title="
|
|
168
|
-
|
|
120
|
+
<Accordion title="Describe elements by what they look like">
|
|
121
|
+
|
|
122
|
+
"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).
|
|
123
|
+
|
|
169
124
|
</Accordion>
|
|
170
|
-
<Accordion title="
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
```
|
|
125
|
+
<Accordion title="Mention loading and animations">
|
|
126
|
+
|
|
127
|
+
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.
|
|
128
|
+
|
|
175
129
|
</Accordion>
|
|
176
|
-
<Accordion title="
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
```
|
|
130
|
+
<Accordion title="Assert after each important step">
|
|
131
|
+
|
|
132
|
+
Assert after each meaningful action, such as "the item appears in the cart". When the test fails later, you see where the regression starts.
|
|
133
|
+
|
|
181
134
|
</Accordion>
|
|
182
|
-
<Accordion title="
|
|
183
|
-
|
|
135
|
+
<Accordion title="Build long flows in pieces">
|
|
136
|
+
|
|
137
|
+
Don't describe a long workflow all at once. Have the agent get the first part passing, then describe the next.
|
|
138
|
+
|
|
184
139
|
</Accordion>
|
|
185
140
|
</AccordionGroup>
|
|
186
141
|
|
|
187
|
-
## Next
|
|
188
|
-
|
|
189
|
-
<
|
|
190
|
-
|
|
191
|
-
|
|
142
|
+
## Next steps
|
|
143
|
+
|
|
144
|
+
<CardGroup cols={2}>
|
|
145
|
+
<Card title="Run tests" icon="play" href="/copilot/running-tests">
|
|
146
|
+
Choose a device, preview mode, and how to run your tests.
|
|
147
|
+
</Card>
|
|
148
|
+
<Card title="Speed up reruns with caching" icon="bolt" href="/caching">
|
|
149
|
+
Reuse what TestDriver found so reruns skip the AI.
|
|
150
|
+
</Card>
|
|
151
|
+
<Card title="Make assertions" icon="circle-check" href="/making-assertions">
|
|
152
|
+
Write checks that catch the regressions you care about.
|
|
153
|
+
</Card>
|
|
154
|
+
<Card title="Run in CI/CD" icon="code-branch" href="/ci-cd">
|
|
155
|
+
Run generated tests on every pull request.
|
|
156
|
+
</Card>
|
|
157
|
+
</CardGroup>
|