testdriverai 7.2.9 → 7.2.10
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/.github/workflows/testdriver.yml +127 -0
- package/.testdriver/last-sandbox +7 -0
- package/agent/events.js +1 -0
- package/agent/index.js +71 -54
- package/agent/lib/sandbox.js +11 -1
- package/agents.md +393 -0
- package/debug/01-table-initial.png +0 -0
- package/debug/02-after-ai-explore.png +0 -0
- package/debug/02-after-scroll.png +0 -0
- package/docs/docs.json +93 -125
- package/docs/v7/_drafts/caching.mdx +2 -2
- package/docs/v7/{getting-started → _drafts}/installation.mdx +0 -66
- package/docs/v7/{features/coverage.mdx → _drafts/powerful.mdx} +1 -90
- package/docs/v7/{features → _drafts}/scalable.mdx +126 -4
- package/docs/v7/_drafts/screenshot.mdx +155 -0
- package/docs/v7/_drafts/writing-tests.mdx +25 -0
- package/docs/v7/{api/act.mdx → ai.mdx} +27 -27
- package/docs/v7/{api/assert.mdx → assert.mdx} +3 -3
- package/docs/v7/aws-setup.mdx +338 -0
- package/docs/v7/caching.mdx +128 -0
- package/docs/v7/ci-cd.mdx +605 -0
- package/docs/v7/{api/click.mdx → click.mdx} +4 -4
- package/docs/v7/cloud.mdx +120 -0
- package/docs/v7/customizing-devices.mdx +129 -0
- package/docs/v7/{api/doubleClick.mdx → double-click.mdx} +5 -5
- package/docs/v7/enterprise.mdx +135 -0
- package/docs/v7/examples.mdx +5 -0
- package/docs/v7/{api/exec.mdx → exec.mdx} +3 -3
- package/docs/v7/{api/find.mdx → find.mdx} +17 -21
- package/docs/v7/{api/focusApplication.mdx → focus-application.mdx} +3 -3
- package/docs/v7/generating-tests.mdx +32 -0
- package/docs/v7/{api/hover.mdx → hover.mdx} +3 -3
- package/docs/v7/locating-elements.mdx +71 -0
- package/docs/v7/making-assertions.mdx +32 -0
- package/docs/v7/{api/mouseDown.mdx → mouse-down.mdx} +7 -7
- package/docs/v7/{api/mouseUp.mdx → mouse-up.mdx} +8 -8
- package/docs/v7/performing-actions.mdx +51 -0
- package/docs/v7/{api/pressKeys.mdx → press-keys.mdx} +3 -3
- package/docs/v7/quickstart.mdx +162 -0
- package/docs/v7/reusable-code.mdx +240 -0
- package/docs/v7/{api/rightClick.mdx → right-click.mdx} +5 -5
- package/docs/v7/running-tests.mdx +181 -0
- package/docs/v7/{api/scroll.mdx → scroll.mdx} +3 -3
- package/docs/v7/secrets.mdx +115 -0
- package/docs/v7/self-hosted.mdx +66 -0
- package/docs/v7/{api/type.mdx → type.mdx} +3 -3
- package/docs/v7/variables.mdx +111 -0
- package/docs/v7/waiting-for-elements.mdx +66 -0
- package/docs/v7/what-is-testdriver.mdx +54 -0
- package/lib/vitest/hooks.mjs +80 -68
- package/package.json +1 -1
- package/sdk.d.ts +22 -9
- package/sdk.js +177 -44
- package/test/manual/reconnect-provision.test.mjs +49 -0
- package/test/manual/reconnect-signin.test.mjs +41 -0
- package/test/testdriver/ai.test.mjs +30 -0
- package/test/testdriver/setup/testHelpers.mjs +0 -1
- package/test/testdriver/windows-installer.test.mjs +61 -0
- package/tests/table-sort-enrollments.test.mjs +72 -0
- package/tests/table-sort-experiment.test.mjs +42 -0
- package/tests/table-sort-setup.test.mjs +59 -0
- package/vitest.config.mjs +1 -0
- package/docs/v7/api/assertions.mdx +0 -403
- package/docs/v7/features/ai-native.mdx +0 -413
- package/docs/v7/features/application-logs.mdx +0 -353
- package/docs/v7/features/browser-logs.mdx +0 -414
- package/docs/v7/features/cache-management.mdx +0 -402
- package/docs/v7/features/continuous-testing.mdx +0 -346
- package/docs/v7/features/data-driven-testing.mdx +0 -441
- package/docs/v7/features/easy-to-write.mdx +0 -280
- package/docs/v7/features/enterprise.mdx +0 -656
- package/docs/v7/features/fast.mdx +0 -406
- package/docs/v7/features/managed-sandboxes.mdx +0 -384
- package/docs/v7/features/network-monitoring.mdx +0 -568
- package/docs/v7/features/parallel-execution.mdx +0 -381
- package/docs/v7/features/powerful.mdx +0 -531
- package/docs/v7/features/sandbox-customization.mdx +0 -229
- package/docs/v7/features/stable.mdx +0 -473
- package/docs/v7/features/system-performance.mdx +0 -616
- package/docs/v7/features/test-analytics.mdx +0 -373
- package/docs/v7/features/test-cases.mdx +0 -393
- package/docs/v7/features/test-replays.mdx +0 -408
- package/docs/v7/features/test-reports.mdx +0 -308
- package/docs/v7/getting-started/debugging-tests.mdx +0 -382
- package/docs/v7/getting-started/quickstart.mdx +0 -90
- package/docs/v7/getting-started/running-tests.mdx +0 -173
- package/docs/v7/getting-started/setting-up-in-ci.mdx +0 -612
- package/docs/v7/getting-started/writing-tests.mdx +0 -534
- package/docs/v7/overview/what-is-testdriver.mdx +0 -386
- package/docs/v7/presets/chrome-extension.mdx +0 -248
- package/docs/v7/presets/chrome.mdx +0 -300
- package/docs/v7/presets/electron.mdx +0 -460
- package/docs/v7/presets/vscode.mdx +0 -417
- package/docs/v7/presets/webapp.mdx +0 -393
- package/vitest.config.js +0 -18
- /package/docs/v7/{commands → _drafts/commands}/assert.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/exec.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/focus-application.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/hover-image.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/hover-text.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/if.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/match-image.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/press-keys.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/remember.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/run.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/scroll-until-image.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/scroll-until-text.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/scroll.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/type.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/wait-for-image.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/wait-for-text.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/wait.mdx +0 -0
- /package/docs/v7/{getting-started → _drafts}/configuration.mdx +0 -0
- /package/docs/v7/{features → _drafts}/observable.mdx +0 -0
- /package/docs/v7/{platforms → _drafts/platforms}/linux.mdx +0 -0
- /package/docs/v7/{platforms → _drafts/platforms}/macos.mdx +0 -0
- /package/docs/v7/{platforms → _drafts/platforms}/windows.mdx +0 -0
- /package/docs/v7/{playwright.mdx → _drafts/playwright.mdx} +0 -0
- /package/docs/v7/{overview → _drafts}/readme.mdx +0 -0
- /package/docs/v7/{features → _drafts}/reports.mdx +0 -0
- /package/docs/v7/{api/client.mdx → client.mdx} +0 -0
- /package/docs/v7/{api/dashcam.mdx → dashcam.mdx} +0 -0
- /package/docs/v7/{api/elements.mdx → elements.mdx} +0 -0
- /package/docs/v7/{api/sandbox.mdx → sandbox.mdx} +0 -0
package/agents.md
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# TestDriver Agent Guide
|
|
2
|
+
|
|
3
|
+
This guide is designed for AI agents working with TestDriver. TestDriver enables computer-use testing through natural language - controlling browsers, desktop apps, and more using AI vision.
|
|
4
|
+
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
| Resource | Location |
|
|
8
|
+
|----------|----------|
|
|
9
|
+
| Code samples | `node_modules/testdriverai/test` |
|
|
10
|
+
| TypeScript types | `node_modules/testdriverai/sdk.d.ts` |
|
|
11
|
+
| Documentation | `node_modules/testdriverai/docs` |
|
|
12
|
+
| API Key | [console.testdriver.ai/team](https://console.testdriver.ai/team) |
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
### API Key Setup
|
|
17
|
+
|
|
18
|
+
The user **must** have a TestDriver API key set in their environment:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# .env file
|
|
22
|
+
TD_API_KEY=your_api_key_here
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Get your API key at: **https://console.testdriver.ai/team**
|
|
26
|
+
|
|
27
|
+
### Test Runner
|
|
28
|
+
|
|
29
|
+
TestDriver **only works with Vitest**. Tests must use the `.test.mjs` extension and import from vitest:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
import { describe, expect, it } from "vitest";
|
|
33
|
+
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Basic Test Structure
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import { describe, expect, it } from "vitest";
|
|
40
|
+
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
|
|
41
|
+
|
|
42
|
+
describe("My Test Suite", () => {
|
|
43
|
+
it("should do something", async (context) => {
|
|
44
|
+
// Initialize TestDriver with options
|
|
45
|
+
const testdriver = TestDriver(context, { newSandbox: true, headless: false });
|
|
46
|
+
|
|
47
|
+
// Start with provision - this launches the sandbox and browser
|
|
48
|
+
await testdriver.provision.chrome({
|
|
49
|
+
url: 'https://example.com',
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Find elements and interact
|
|
53
|
+
const button = await testdriver.find("Sign In button");
|
|
54
|
+
await button.click();
|
|
55
|
+
|
|
56
|
+
// Assert using natural language
|
|
57
|
+
const result = await testdriver.assert("the dashboard is visible");
|
|
58
|
+
expect(result).toBeTruthy();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Provisioning Options
|
|
64
|
+
|
|
65
|
+
Most tests start with `testdriver.provision`. Choose the right one:
|
|
66
|
+
|
|
67
|
+
### `provision.chrome` - Web Testing (Most Common)
|
|
68
|
+
```javascript
|
|
69
|
+
await testdriver.provision.chrome({
|
|
70
|
+
url: 'https://your-app.com',
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `provision.installer` - Desktop App Testing
|
|
75
|
+
```javascript
|
|
76
|
+
// Download and install an application
|
|
77
|
+
const filePath = await testdriver.provision.installer({
|
|
78
|
+
url: 'https://example.com/app.deb', // or .msi, .exe, .sh
|
|
79
|
+
launch: true, // auto-launch after install
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Key SDK Methods
|
|
84
|
+
|
|
85
|
+
The SDK has TypeScript types in `sdk.d.ts`. Key methods:
|
|
86
|
+
|
|
87
|
+
| Method | Purpose |
|
|
88
|
+
|--------|---------|
|
|
89
|
+
| `find(description)` | Find element by natural language |
|
|
90
|
+
| `findAll(description)` | Find all matching elements |
|
|
91
|
+
| `assert(assertion)` | AI-powered assertion |
|
|
92
|
+
| `type(text)` | Type text |
|
|
93
|
+
| `pressKeys([keys])` | Press keyboard keys |
|
|
94
|
+
| `scroll(direction)` | Scroll the page |
|
|
95
|
+
| `exec(language, code)` | Execute code in sandbox |
|
|
96
|
+
| `ai(task)` | AI exploratory loop (see note below) |
|
|
97
|
+
|
|
98
|
+
### About `ai()` - Use for Exploration, Not Final Tests
|
|
99
|
+
|
|
100
|
+
The `ai(task)` method lets the AI figure out how to accomplish a task autonomously. It's useful for:
|
|
101
|
+
- **Exploring** how to accomplish something when you're unsure of the steps
|
|
102
|
+
- **Discovering** element descriptions and UI flow
|
|
103
|
+
- **Last resort** when explicit methods fail repeatedly
|
|
104
|
+
|
|
105
|
+
However, **prefer explicit methods** (`find`, `click`, `type`) in final tests because:
|
|
106
|
+
- They're more predictable and repeatable
|
|
107
|
+
- They're faster (no AI reasoning loop)
|
|
108
|
+
- They're easier to debug when they fail
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// ✅ GOOD: Explicit steps (preferred for final tests)
|
|
112
|
+
const emailInput = await testdriver.find("email input field");
|
|
113
|
+
await emailInput.click();
|
|
114
|
+
await testdriver.type("user@example.com");
|
|
115
|
+
|
|
116
|
+
// ⚠️ OK for exploration, but convert to explicit steps later
|
|
117
|
+
await testdriver.ai("fill in the email field with user@example.com");
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Element Properties (for debugging)
|
|
121
|
+
|
|
122
|
+
Elements returned by `find()` have properties you can inspect:
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const element = await testdriver.find("Sign In button");
|
|
126
|
+
|
|
127
|
+
// Debugging properties
|
|
128
|
+
console.log(element.x, element.y); // coordinates
|
|
129
|
+
console.log(element.centerX, element.centerY); // center coordinates
|
|
130
|
+
console.log(element.width, element.height); // dimensions
|
|
131
|
+
console.log(element.confidence); // AI confidence score
|
|
132
|
+
console.log(element.text); // detected text
|
|
133
|
+
console.log(element.boundingBox); // full bounding box
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Element Methods
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
const element = await testdriver.find("button");
|
|
140
|
+
await element.click(); // click
|
|
141
|
+
await element.hover(); // hover
|
|
142
|
+
await element.doubleClick(); // double-click
|
|
143
|
+
await element.rightClick(); // right-click
|
|
144
|
+
await element.mouseDown(); // press mouse down
|
|
145
|
+
await element.mouseUp(); // release mouse
|
|
146
|
+
element.found(); // check if found (boolean)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Best Workflow: Two-File Pattern
|
|
150
|
+
|
|
151
|
+
**The most efficient workflow for building tests uses two files.** This prevents having to restart from scratch when experimenting with new steps.
|
|
152
|
+
|
|
153
|
+
### IMPORTANT: When to Use This Pattern
|
|
154
|
+
|
|
155
|
+
- **If a working test already exists**: Only create an `experiment.test.mjs` file to add new steps. Do NOT recreate the stable file.
|
|
156
|
+
- **If starting from scratch**: Start with a MINIMAL setup file, run it, verify it passes, THEN create the experiment file.
|
|
157
|
+
|
|
158
|
+
### Step 1: Create a Minimal Setup File
|
|
159
|
+
|
|
160
|
+
Start with the bare minimum - just provision and one assertion. **Do NOT call it "stable" yet** - name it `setup.test.mjs` until it's proven to work:
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
/**
|
|
164
|
+
* Setup file - MINIMAL steps to get to starting state
|
|
165
|
+
* Only add more steps AFTER this passes!
|
|
166
|
+
*/
|
|
167
|
+
import { afterAll, describe, expect, it } from "vitest";
|
|
168
|
+
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
|
|
169
|
+
|
|
170
|
+
describe("Setup State", () => {
|
|
171
|
+
|
|
172
|
+
afterAll(async () => {
|
|
173
|
+
// DO NOT disconnect - keep sandbox alive for reconnect
|
|
174
|
+
console.log("Sandbox staying alive for 30 seconds (keepAlive)");
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("should set up the application state", async (context) => {
|
|
178
|
+
const testdriver = TestDriver(context, {
|
|
179
|
+
newSandbox: true,
|
|
180
|
+
headless: false
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await testdriver.provision.chrome({
|
|
184
|
+
url: 'https://your-app.com/login',
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Start with just ONE assertion to verify we're on the right page
|
|
188
|
+
const result = await testdriver.assert("I can see the login page");
|
|
189
|
+
expect(result).toBeTruthy();
|
|
190
|
+
|
|
191
|
+
console.log("✅ Setup ready - run experiment.test.mjs now");
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Step 2: Run Setup File and Verify It Passes
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
vitest run tests/setup.test.mjs
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Only proceed to Step 3 if this passes!** If it fails, fix it first.
|
|
203
|
+
|
|
204
|
+
### Step 3: Create Experiment File
|
|
205
|
+
|
|
206
|
+
Only AFTER the setup file passes, create the experiment file.
|
|
207
|
+
|
|
208
|
+
**CRITICAL: The experiment file must NOT call `provision`!** It reconnects to the existing sandbox where provision already ran:
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
/**
|
|
212
|
+
* Experiment file - reconnects to existing sandbox
|
|
213
|
+
* Run AFTER setup.test.mjs passes (within 2 minutes)
|
|
214
|
+
*/
|
|
215
|
+
import { describe, expect, it } from "vitest";
|
|
216
|
+
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
|
|
217
|
+
|
|
218
|
+
describe("Experiment", () => {
|
|
219
|
+
|
|
220
|
+
it("should continue from existing state", async (context) => {
|
|
221
|
+
const testdriver = TestDriver(context, {
|
|
222
|
+
newSandbox: true,
|
|
223
|
+
headless: false,
|
|
224
|
+
reconnect: true // ← Key: reconnects to last sandbox
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// NO provision here! The sandbox is already running from setup.test.mjs
|
|
228
|
+
|
|
229
|
+
// Experiment with new steps here - try ONE thing at a time
|
|
230
|
+
const element = await testdriver.find("email input");
|
|
231
|
+
console.log("Found element:", element.found(), element.getCoordinates());
|
|
232
|
+
|
|
233
|
+
await element.click();
|
|
234
|
+
await testdriver.type("user@example.com");
|
|
235
|
+
|
|
236
|
+
// Assert after each major step
|
|
237
|
+
const result = await testdriver.assert("email is filled in");
|
|
238
|
+
console.log("Assertion result:", result);
|
|
239
|
+
expect(result).toBeTruthy();
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Step 4: Iterate in Experiment File
|
|
245
|
+
|
|
246
|
+
- Run experiment, see output, fix issues
|
|
247
|
+
- Once steps work, move them to the setup file
|
|
248
|
+
- Re-run setup file to verify it still passes
|
|
249
|
+
- Repeat until complete
|
|
250
|
+
|
|
251
|
+
### Running the Two-File Pattern
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# Step 1: Run setup file (must pass first!)
|
|
255
|
+
vitest run tests/setup.test.mjs
|
|
256
|
+
|
|
257
|
+
# Step 2: Within 2 minutes, run experiment file
|
|
258
|
+
vitest run tests/experiment.test.mjs
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### After Experimentation: Combine and Rename
|
|
262
|
+
|
|
263
|
+
**IMPORTANT:** Once the test is working, combine both files into a single, properly-named test file:
|
|
264
|
+
|
|
265
|
+
1. **Merge the code** - Copy the working steps from `experiment.test.mjs` into `setup.test.mjs`
|
|
266
|
+
2. **Remove reconnect options** - Delete `reconnect: true` since the final test runs standalone
|
|
267
|
+
3. **Rename the file** - Give it a meaningful name like `login-flow.test.mjs` or `checkout-process.test.mjs`
|
|
268
|
+
4. **Delete the experiment file** - Clean up `experiment.test.mjs`
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
// Final combined test: login-flow.test.mjs
|
|
272
|
+
import { describe, expect, it } from "vitest";
|
|
273
|
+
import { TestDriver } from "testdriverai/lib/vitest/hooks.mjs";
|
|
274
|
+
|
|
275
|
+
describe("Login Flow", () => {
|
|
276
|
+
it("should log in and open settings", async (context) => {
|
|
277
|
+
const testdriver = TestDriver(context, { newSandbox: true, headless: false });
|
|
278
|
+
|
|
279
|
+
await testdriver.provision.chrome({ url: 'https://your-app.com/login' });
|
|
280
|
+
|
|
281
|
+
// Steps from stable file
|
|
282
|
+
await testdriver.find("email input").click();
|
|
283
|
+
await testdriver.type("user@example.com");
|
|
284
|
+
await testdriver.find("password input").click();
|
|
285
|
+
await testdriver.type("password123");
|
|
286
|
+
await testdriver.find("Login button").click();
|
|
287
|
+
|
|
288
|
+
// Steps from experiment file
|
|
289
|
+
const settingsBtn = await testdriver.find("Settings button");
|
|
290
|
+
await settingsBtn.click();
|
|
291
|
+
|
|
292
|
+
const result = await testdriver.assert("Settings panel is open");
|
|
293
|
+
expect(result).toBeTruthy();
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Recommended Development Workflow
|
|
299
|
+
|
|
300
|
+
1. **Write a few steps** - Don't write the entire test at once
|
|
301
|
+
2. **Run the test** - See what happens on the sandbox
|
|
302
|
+
3. **Inspect outputs** - Use element properties to debug
|
|
303
|
+
4. **Assert/expect** - Verify the step worked
|
|
304
|
+
5. **Iterate** - Add more steps incrementally
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
// Development workflow example
|
|
308
|
+
it("should incrementally build test", async (context) => {
|
|
309
|
+
const testdriver = TestDriver(context, { newSandbox: true });
|
|
310
|
+
await testdriver.provision.chrome({ url: 'https://example.com' });
|
|
311
|
+
|
|
312
|
+
// Step 1: Find and inspect
|
|
313
|
+
const element = await testdriver.find("Some button");
|
|
314
|
+
console.log("Element found:", element.found());
|
|
315
|
+
console.log("Coordinates:", element.x, element.y);
|
|
316
|
+
console.log("Confidence:", element.confidence);
|
|
317
|
+
|
|
318
|
+
// Step 2: Interact
|
|
319
|
+
await element.click();
|
|
320
|
+
|
|
321
|
+
// Step 3: Assert and log
|
|
322
|
+
const result = await testdriver.assert("Something happened");
|
|
323
|
+
console.log("Assertion result:", result);
|
|
324
|
+
expect(result).toBeTruthy();
|
|
325
|
+
|
|
326
|
+
// Then add more steps...
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## TestDriver Options Reference
|
|
331
|
+
|
|
332
|
+
```javascript
|
|
333
|
+
const testdriver = TestDriver(context, {
|
|
334
|
+
newSandbox: true, // Create new sandbox (default: true)
|
|
335
|
+
headless: false, // Run in headless mode (default: false)
|
|
336
|
+
reconnect: false, // Reconnect to last sandbox (default: false)
|
|
337
|
+
keepAlive: 30000, // Keep sandbox alive after test (default: 30000ms / 30 seconds)
|
|
338
|
+
os: 'linux', // 'linux' | 'windows' (default: 'linux')
|
|
339
|
+
resolution: '1366x768', // Sandbox resolution
|
|
340
|
+
cache: true, // Enable element caching (default: true)
|
|
341
|
+
cacheKey: 'my-test', // Cache key for element finding
|
|
342
|
+
});
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Common Patterns
|
|
346
|
+
|
|
347
|
+
### Typing in Fields
|
|
348
|
+
```javascript
|
|
349
|
+
await testdriver.find("Email input").click();
|
|
350
|
+
await testdriver.type("user@example.com");
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Keyboard Shortcuts
|
|
354
|
+
```javascript
|
|
355
|
+
await testdriver.pressKeys(["ctrl", "a"]); // Select all
|
|
356
|
+
await testdriver.pressKeys(["ctrl", "c"]); // Copy
|
|
357
|
+
await testdriver.pressKeys(["enter"]); // Submit
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Waiting and Polling
|
|
361
|
+
```javascript
|
|
362
|
+
// Use timeout option to poll until element is found (retries every 5 seconds)
|
|
363
|
+
const element = await testdriver.find("Loading complete indicator", { timeout: 30000 });
|
|
364
|
+
await element.click();
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Scrolling
|
|
368
|
+
```javascript
|
|
369
|
+
await testdriver.scroll("down");
|
|
370
|
+
await testdriver.scrollUntilText("Footer text");
|
|
371
|
+
await testdriver.scrollUntilImage("Product image at bottom");
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Executing Code in Sandbox
|
|
375
|
+
```javascript
|
|
376
|
+
// JavaScript
|
|
377
|
+
const result = await testdriver.exec("js", "return document.title", 5000);
|
|
378
|
+
|
|
379
|
+
// Shell (Linux)
|
|
380
|
+
const output = await testdriver.exec("sh", "ls -la", 5000);
|
|
381
|
+
|
|
382
|
+
// PowerShell (Windows)
|
|
383
|
+
const date = await testdriver.exec("pwsh", "Get-Date", 5000);
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Tips for Agents
|
|
387
|
+
|
|
388
|
+
1. **Always check `sdk.d.ts`** for method signatures and types
|
|
389
|
+
2. **Look at test samples** in `node_modules/testdriverai/test` for working examples
|
|
390
|
+
3. **Use reconnect pattern** when iterating on test steps
|
|
391
|
+
4. **Log element properties** to understand what the AI sees
|
|
392
|
+
5. **Use `assert()` with specific, descriptive natural language**
|
|
393
|
+
6. **Start simple** - get one step working before adding more
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/docs.json
CHANGED
|
@@ -187,132 +187,100 @@
|
|
|
187
187
|
}
|
|
188
188
|
]
|
|
189
189
|
},
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
"/v7/api/act",
|
|
283
|
-
"/v7/api/assert",
|
|
284
|
-
"/v7/api/assertions",
|
|
285
|
-
"/v7/api/click",
|
|
286
|
-
"/v7/api/doubleClick",
|
|
287
|
-
"/v7/api/exec",
|
|
288
|
-
"/v7/api/find",
|
|
289
|
-
"/v7/api/focusApplication",
|
|
290
|
-
"/v7/api/hover",
|
|
291
|
-
"/v7/api/mouseDown",
|
|
292
|
-
"/v7/api/mouseUp",
|
|
293
|
-
"/v7/api/pressKeys",
|
|
294
|
-
"/v7/api/rightClick",
|
|
295
|
-
"/v7/api/type",
|
|
296
|
-
"/v7/api/scroll"
|
|
297
|
-
]
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
"group": "Client SDK",
|
|
301
|
-
"icon": "code",
|
|
302
|
-
"pages": [
|
|
303
|
-
"/v7/api/client",
|
|
304
|
-
"/v7/api/elements",
|
|
305
|
-
"/v7/api/sandbox",
|
|
306
|
-
"/v7/api/dashcam"
|
|
307
|
-
]
|
|
308
|
-
}
|
|
309
|
-
]
|
|
310
|
-
}
|
|
311
|
-
]
|
|
312
|
-
}
|
|
313
|
-
|
|
190
|
+
{
|
|
191
|
+
"version": "v7",
|
|
192
|
+
"groups": [
|
|
193
|
+
{
|
|
194
|
+
"group": "Overview",
|
|
195
|
+
"pages": [
|
|
196
|
+
"/v7/what-is-testdriver",
|
|
197
|
+
"/v7/quickstart",
|
|
198
|
+
"/v7/examples",
|
|
199
|
+
{
|
|
200
|
+
"group": "Plans & Pricing",
|
|
201
|
+
"icon": "server",
|
|
202
|
+
"pages": [
|
|
203
|
+
"/v7/cloud",
|
|
204
|
+
{
|
|
205
|
+
"group": "Self-Hosted",
|
|
206
|
+
"icon": "server",
|
|
207
|
+
"pages": [
|
|
208
|
+
"/v7/self-hosted",
|
|
209
|
+
"/v7/aws-setup"
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
"/v7/enterprise"
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"group": "Creating Tests",
|
|
219
|
+
"pages": [
|
|
220
|
+
"/v7/generating-tests",
|
|
221
|
+
"/v7/locating-elements",
|
|
222
|
+
"/v7/waiting-for-elements",
|
|
223
|
+
"/v7/performing-actions",
|
|
224
|
+
"/v7/making-assertions"
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"group": "Running Tests",
|
|
229
|
+
"pages": [
|
|
230
|
+
"/v7/running-tests",
|
|
231
|
+
"/v7/caching",
|
|
232
|
+
"/v7/ci-cd"
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"group": "Scaling",
|
|
237
|
+
"pages": [
|
|
238
|
+
"/v7/variables",
|
|
239
|
+
"/v7/secrets",
|
|
240
|
+
"/v7/reusable-code",
|
|
241
|
+
"/v7/customizing-devices"
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"group": "Reference",
|
|
246
|
+
"icon": "book",
|
|
247
|
+
"pages": [
|
|
248
|
+
{
|
|
249
|
+
"group": "Actions",
|
|
250
|
+
"icon": "bolt",
|
|
251
|
+
"pages": [
|
|
252
|
+
"/v7/ai",
|
|
253
|
+
"/v7/assert",
|
|
254
|
+
"/v7/click",
|
|
255
|
+
"/v7/double-click",
|
|
256
|
+
"/v7/exec",
|
|
257
|
+
"/v7/find",
|
|
258
|
+
"/v7/focus-application",
|
|
259
|
+
"/v7/hover",
|
|
260
|
+
"/v7/mouse-down",
|
|
261
|
+
"/v7/mouse-up",
|
|
262
|
+
"/v7/press-keys",
|
|
263
|
+
"/v7/right-click",
|
|
264
|
+
"/v7/type",
|
|
265
|
+
"/v7/scroll"
|
|
266
|
+
]
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"group": "Client SDK",
|
|
270
|
+
"icon": "code",
|
|
271
|
+
"pages": [
|
|
272
|
+
"/v7/client",
|
|
273
|
+
"/v7/elements",
|
|
274
|
+
"/v7/sandbox",
|
|
275
|
+
"/v7/dashcam"
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
}
|
|
314
282
|
]
|
|
315
|
-
|
|
283
|
+
},
|
|
316
284
|
"logo": {
|
|
317
285
|
"light": "/images/template/light.png",
|
|
318
286
|
"dark": "/images/template/dark.png",
|