@testdriverai/agent 7.11.239-test → 7.11.241-canary

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,148 +1,158 @@
1
1
  ---
2
2
  name: testdriver:performing-actions
3
- description: Perform actions and handle dynamic, async UI so tests adapt to change
3
+ description: Click, type, scroll, and read the screen, and wait for a changing UI.
4
4
  ---
5
5
  <!-- Generated from performing-actions.mdx. DO NOT EDIT. -->
6
6
 
7
- Real apps move, load, and change. Adapt your tests to these conditions.
7
+ A TestDriver test acts on the screen the way a person does, with the real mouse and keyboard.
8
8
 
9
- You [generated](/generating-tests) and [learned](/caching) your tests. Then you got them to [run](/copilot/running-tests). Now the challenge is the real world: buttons show after a spinner, pages navigate, animations play, and content comes in over the network. To keep the tests reliable, do the correct actions and control the timing. Then your tests adapt to the true behavior of the UI. They do not break.
9
+ - Find an element by describing it.
10
+ - Click it, type into it, or scroll past it.
11
+ - Wait for a UI that loads, animates, or changes as you use it.
10
12
 
11
- ## Performing Actions
13
+ ## Find an element, then act on it
12
14
 
13
- TestDriver gives you many actions. You can [click](/click), [type](/type), [hover](/hover), and [scroll](/scroll). For a full list, read the [API Reference](/click).
15
+ `find()` returns an element, and the element has methods for mouse actions:
14
16
 
15
17
  ```javascript
16
- // Clicking
17
- await testdriver.find('submit button').click();
18
- await testdriver.find('file item').doubleClick();
19
- await testdriver.find('text area').rightClick();
20
-
21
- // Typing
22
- await testdriver.find('email input').type('user@example.com');
23
- await testdriver.find('password input').type('secret', { secret: true });
18
+ const submitButton = await testdriver.find('Submit button');
19
+ await submitButton.click();
20
+ ```
24
21
 
25
- // Keyboard shortcuts
26
- await testdriver.pressKeys(['enter']);
27
- await testdriver.pressKeys(['ctrl', 'c']);
22
+ You can also chain the action straight onto `find()`:
28
23
 
29
- // Hovering
30
- await testdriver.find('dropdown menu').hover();
24
+ ```javascript
25
+ await testdriver.find('Submit button').click();
26
+ ```
31
27
 
32
- // Scrolling
33
- await testdriver.scroll('down', 500);
28
+ | Method | What it does |
29
+ | --- | --- |
30
+ | [`click()`](/click) | Left-clicks the element |
31
+ | [`doubleClick()`](/double-click) | Double-clicks the element |
32
+ | [`rightClick()`](/right-click) | Right-clicks the element, for example to open a context menu |
33
+ | [`hover()`](/hover) | Moves the mouse over the element without clicking |
34
+ | [`mouseDown()`](/mouse-down) and [`mouseUp()`](/mouse-up) | Press and release the mouse button separately, for dragging |
34
35
 
35
- // Waiting
36
- await testdriver.wait(2000); // Wait 2 seconds for animation/state change
36
+ If `find()` can't locate the element, it returns an element whose `found()` is `false`. Calling one of these methods on it throws an `ElementNotFoundError`.
37
37
 
38
- // Extracting information from screen
39
- const price = await testdriver.extract('the total price');
40
- const orderNumber = await testdriver.extract('the order confirmation number');
41
- ```
38
+ See [Locate elements](/locating-elements) to write descriptions that find the right element.
42
39
 
43
- ### Chaining Actions
40
+ ## Type text
44
41
 
45
- TestDriver lets you chain methods for cleaner code:
42
+ [`type()`](/type) types into whatever has keyboard focus, so click the field first:
46
43
 
47
44
  ```javascript
48
- // Chain find() with actions
49
- const button = await testdriver.find('submit button').click();
45
+ const emailField = await testdriver.find('Email input field');
46
+ await emailField.click();
47
+ await testdriver.type('user@example.com');
50
48
  ```
51
49
 
52
- Or keep the element reference for later use:
50
+ Pass `secret: true` for passwords and other sensitive values. TestDriver then doesn't log or store the text:
53
51
 
54
52
  ```javascript
55
- const button = await testdriver.find('submit button');
56
- await button.click();
53
+ await testdriver.find('Password input field').click();
54
+ await testdriver.type(process.env.TD_PASSWORD, { secret: true });
57
55
  ```
58
56
 
59
- ## Waiting for Dynamic Content
57
+ See [Secrets](/secrets) for keeping credentials out of your test code.
60
58
 
61
- By default, `find()` polls automatically for a maximum of 10 seconds. It tries again each 5 seconds until it finds the element. Thus TestDriver finds most elements that show after short async operations. You do not need more configuration.
59
+ ## Press keys and shortcuts
62
60
 
63
- For longer operations, make the `timeout` larger:
61
+ [`pressKeys()`](/press-keys) takes an array of keys and presses them together:
64
62
 
65
63
  ```javascript
66
- // Default behavior - polls for up to 10 seconds automatically
67
- const element = await testdriver.find('Loading complete indicator');
68
- await element.click();
64
+ await testdriver.pressKeys(['enter']);
65
+ await testdriver.pressKeys(['ctrl', 'a']);
66
+ await testdriver.pressKeys(['ctrl', 'shift', 'i']);
67
+ ```
69
68
 
70
- // Wait up to 30 seconds for slower operations
71
- const element = await testdriver.find('Loading complete indicator', { timeout: 30000 });
72
- await element.click();
69
+ ## Scroll
73
70
 
74
- // Useful after actions that trigger loading states
75
- await testdriver.find('submit button').click();
76
- await testdriver.find('success message', { timeout: 15000 });
71
+ [`scroll()`](/scroll) scrolls the page up or down with the mouse wheel. The default `amount` is 300:
77
72
 
78
- // Disable polling for instant checks
79
- const toast = await testdriver.find('notification toast', { timeout: 0 });
73
+ ```javascript
74
+ await testdriver.scroll('down', { amount: 1000 });
80
75
  ```
81
76
 
82
- ### Flake Prevention
77
+ If scrolling doesn't move the page, click somewhere on it first. That gives the page focus instead of another window.
83
78
 
84
- TestDriver automatically waits for the screen and network to stabilize after each action using **redraw detection**. This prevents flaky tests caused by animations, loading states, or dynamic content updates.
79
+ ## Read values from the screen
85
80
 
86
- <Note>
87
- Redraw detection adds a small delay after each action but significantly reduces test flakiness.
88
- </Note>
89
-
90
- For example, when clicking a submit button that navigates to a new page:
81
+ [`extract()`](/extract) reads information off the screen in plain language and returns it as a string. Use it for values the test needs later:
91
82
 
92
83
  ```javascript
93
- // Click submit - TestDriver automatically waits for the new page to load
94
- await testdriver.find('submit button').click();
95
-
96
- // By the time this runs, the page has fully loaded and stabilized
97
- await testdriver.assert('dashboard is displayed');
98
- await testdriver.find('welcome message');
84
+ const orderNumber = await testdriver.extract('the order confirmation number');
85
+ console.log(orderNumber); // for example "A-10482"
99
86
  ```
100
87
 
101
- Without redraw detection, you'd need manual waits or retries to handle the page transition. TestDriver handles this automatically by detecting when the screen stops changing and network requests complete.
88
+ ## Wait for a changing UI
89
+
90
+ Most timing problems come from acting before the app is ready. Wait for what the next step depends on, not for a fixed time.
91
+
92
+ ### Wait for an element with find()
102
93
 
103
- You can disable redraw detection or customize its behavior:
94
+ `find()` already waits. It checks the screen every 5 seconds, for up to 10 seconds, until the element appears.
95
+
96
+ For something slower, such as a page that loads after a form submits, raise the `timeout`:
104
97
 
105
98
  ```javascript
106
- // Disable redraw detection for faster tests (less reliable)
107
- const testdriver = TestDriver(context, {
108
- redraw: false
109
- });
99
+ await testdriver.find('Submit button').click();
100
+
101
+ // Keep looking for up to 30 seconds while the next page loads
102
+ const confirmation = await testdriver.find('Order confirmation message', { timeout: 30000 });
110
103
  ```
111
104
 
112
- Here is an example of customizing redraw detection:
105
+ Set `timeout: 0` to check once without waiting. For example, check whether an optional banner is showing:
113
106
 
114
107
  ```javascript
115
- // Fine-tune redraw detection
116
- const testdriver = TestDriver(context, {
117
- redraw: {
118
- enabled: true,
119
- diffThreshold: 0.1, // Pixel difference threshold (0-1)
120
- screenRedraw: true, // Monitor screen changes
121
- networkMonitor: true, // Wait for network idle
122
- }
123
- });
108
+ const cookieBanner = await testdriver.find('cookie consent banner', { timeout: 0 });
109
+ if (cookieBanner.found()) {
110
+ await testdriver.find('Accept all cookies button').click();
111
+ }
124
112
  ```
125
113
 
126
- ### Simple Delays with `wait()`
114
+ ### Pause with wait()
127
115
 
128
- For simple pauses — waiting for animations, transitions, or state changes after an action — use `wait()`:
116
+ [`wait()`](/wait) pauses for a fixed number of milliseconds. Use it only when there's nothing specific to wait for, such as an animation:
129
117
 
130
118
  ```javascript
131
- // Wait for an animation to complete
132
- await testdriver.find('menu toggle').click();
133
- await testdriver.wait(2000);
134
-
135
- // Wait for a page transition to settle
136
- await testdriver.find('next page button').click();
119
+ await testdriver.find('Menu toggle').click();
137
120
  await testdriver.wait(1000);
138
121
  ```
139
122
 
140
- <Note>
141
- For waiting for specific **elements** to appear, prefer `find()` with a `timeout` option. Use `wait()` only for simple time-based pauses.
142
- </Note>
123
+ ### Wait for the screen to settle with redraw detection
124
+
125
+ For apps with a lot of animation or loading states, turn on redraw detection. After each action, TestDriver waits until the screen stops changing:
126
+
127
+ ```javascript
128
+ const testdriver = TestDriver(context, { redraw: true });
129
+ ```
130
+
131
+ Redraw detection is off by default because it adds a short delay after every action.
132
+
133
+ To also wait for network activity to finish, enable network monitoring:
143
134
 
144
- Once your tests can reliably act on a changing UI and [assert](/making-assertions) the results, the next step is figuring out what happened when something does go wrong.
135
+ ```javascript
136
+ const testdriver = TestDriver(context, {
137
+ redraw: { thresholds: { network: true } },
138
+ });
139
+ ```
145
140
 
146
- <Card title="Next: Debug" icon="bug" href="/debugging-with-screenshots">
147
- Use screenshots and run output to see exactly what your test saw and pinpoint failures.
148
- </Card>
141
+ See [Redraw](/redraw) for every option.
142
+
143
+ ## Next steps
144
+
145
+ <CardGroup cols={2}>
146
+ <Card title="Make assertions" icon="circle-check" href="/making-assertions">
147
+ Check the result of your actions in plain language.
148
+ </Card>
149
+ <Card title="Locate elements" icon="crosshairs" href="/locating-elements">
150
+ Write descriptions that find the right element.
151
+ </Card>
152
+ <Card title="Debug a failing test" icon="bug" href="/debugging-with-screenshots">
153
+ See what the screen showed at each step.
154
+ </Card>
155
+ <Card title="Prevent regressions" icon="shield-check" href="/copilot/auto-healing">
156
+ Catch regressions in CI and repair tests when your UI changes.
157
+ </Card>
158
+ </CardGroup>
@@ -1,348 +1,108 @@
1
1
  ---
2
2
  name: testdriver:press-keys
3
- description: Press keyboard keys and shortcuts
3
+ description: Press a key or a keyboard shortcut, like Enter, Tab or Ctrl+A.
4
4
  ---
5
5
  <!-- Generated from press-keys.mdx. DO NOT EDIT. -->
6
6
 
7
- ## Overview
7
+ Press a single key or a keyboard shortcut in the sandbox:
8
8
 
9
- Push one or more keyboard keys at the same time. Use this for keyboard shortcuts, navigation, and special keys.
9
+ ```javascript
10
+ await testdriver.pressKeys(['enter']);
11
+ await testdriver.pressKeys(['ctrl', 'a']);
12
+ ```
10
13
 
11
- ## Syntax
14
+ To enter text, use [`type()`](/type) instead.
12
15
 
13
- ```javascript
14
- await testdriver.pressKeys(keys)
16
+ ## Signature
17
+
18
+ ```typescript
19
+ testdriver.pressKeys(keys: KeyboardKey[]): Promise<void>
15
20
  ```
16
21
 
17
22
  ## Parameters
18
23
 
19
- <ParamField path="keys" type="Array&lt;string&gt;" required>
20
- An array of the keys to push at the same time
24
+ <ParamField path="keys" type="KeyboardKey[]" required>
25
+ The keys to press, as a shortcut. TestDriver presses them in order, holds them all down, then releases them in reverse order. So `['ctrl', 'shift', 'i']` is Ctrl+Shift+I.
26
+
27
+ Each name must be a valid `KeyboardKey`. See [Key names](#key-names).
21
28
  </ParamField>
22
29
 
23
- ## Returns
30
+ Because the keys are pressed together, `['enter', 'enter']` doesn't press Enter twice. Call `pressKeys()` once per key press instead.
24
31
 
25
- `Promise<void>`
32
+ ## Key names
26
33
 
27
- ## Common Keys
34
+ Key names are lowercase. The most common ones:
28
35
 
29
- ### Special Keys
30
- - `'enter'`, `'tab'`, `'escape'`, `'backspace'`, `'delete'`
31
- - `'space'`, `'up'`, `'down'`, `'left'`, `'right'`
32
- - `'home'`, `'end'`, `'pageup'`, `'pagedown'`
36
+ | Kind | Names |
37
+ | --- | --- |
38
+ | Letters, digits, symbols | `'a'`–`'z'`, `'0'`–`'9'`, and single characters like `'/'` or `'.'` |
39
+ | Editing | `'enter'`, `'tab'`, `'space'`, `'backspace'`, `'delete'`, `'escape'` |
40
+ | Navigation | `'up'`, `'down'`, `'left'`, `'right'`, `'home'`, `'end'`, `'pageup'`, `'pagedown'` |
41
+ | Modifiers | `'ctrl'`, `'shift'`, `'alt'`, `'win'`, and left/right forms like `'ctrlleft'` |
42
+ | Function keys | `'f1'`–`'f24'` |
33
43
 
34
- ### Modifier Keys
35
- - `'ctrl'`, `'alt'`, `'shift'`
36
- - `'command'` (macOS), `'win'` (Windows)
37
- - `'ctrlleft'`, `'ctrlright'`, `'shiftleft'`, `'shiftright'`
44
+ The full list is the `KeyboardKey` type in `sdk.d.ts`, which your editor autocompletes.
38
45
 
39
- ### Function Keys
40
- - `'f1'` through `'f24'`
46
+ <Note>
47
+ Sandboxes run Linux by default, or Windows. Use `'ctrl'` for shortcuts like copy and paste, not `'command'`.
48
+ </Note>
41
49
 
42
50
  ## Examples
43
51
 
44
- ### Navigation
52
+ ### Move between form fields
45
53
 
46
54
  ```javascript
47
- // Tab to next field
55
+ await testdriver.find('Email input field').click();
56
+ await testdriver.type('user@example.com');
48
57
  await testdriver.pressKeys(['tab']);
49
-
50
- // Shift+Tab to previous field
51
- await testdriver.pressKeys(['shift', 'tab']);
52
-
53
- // Arrow keys
54
- await testdriver.pressKeys(['down']);
55
- await testdriver.pressKeys(['up']);
56
- await testdriver.pressKeys(['left']);
57
- await testdriver.pressKeys(['right']);
58
-
59
- // Home/End
60
- await testdriver.pressKeys(['home']); // Start of line
61
- await testdriver.pressKeys(['end']); // End of line
62
-
63
- // Page navigation
64
- await testdriver.pressKeys(['pagedown']);
65
- await testdriver.pressKeys(['pageup']);
58
+ await testdriver.type(process.env.TD_PASSWORD, { secret: true });
59
+ await testdriver.pressKeys(['enter']);
66
60
  ```
67
61
 
68
- ### Keyboard Shortcuts
62
+ ### Replace the text in a field
69
63
 
70
64
  ```javascript
71
- // Copy (Ctrl+C / Cmd+C)
72
- await testdriver.pressKeys(['ctrl', 'c']);
73
-
74
- // Paste (Ctrl+V / Cmd+V)
75
- await testdriver.pressKeys(['ctrl', 'v']);
76
-
77
- // Save (Ctrl+S)
78
- await testdriver.pressKeys(['ctrl', 's']);
79
-
80
- // Select All (Ctrl+A)
65
+ await testdriver.find('Search input').click();
81
66
  await testdriver.pressKeys(['ctrl', 'a']);
82
-
83
- // Undo (Ctrl+Z)
84
- await testdriver.pressKeys(['ctrl', 'z']);
85
-
86
- // Redo (Ctrl+Y)
87
- await testdriver.pressKeys(['ctrl', 'y']);
88
-
89
- // Find (Ctrl+F)
90
- await testdriver.pressKeys(['ctrl', 'f']);
91
-
92
- // New tab (Ctrl+T)
93
- await testdriver.pressKeys(['ctrl', 't']);
94
-
95
- // Close tab (Ctrl+W)
96
- await testdriver.pressKeys(['ctrl', 'w']);
97
-
98
- // Refresh (F5 or Ctrl+R)
99
- await testdriver.pressKeys(['f5']);
100
- await testdriver.pressKeys(['ctrl', 'r']);
101
- ```
102
-
103
- ### System Shortcuts
104
-
105
- ```javascript
106
- // Alt+Tab (Windows - switch apps)
107
- await testdriver.pressKeys(['alt', 'tab']);
108
-
109
- // Alt+F4 (Windows - close window)
110
- await testdriver.pressKeys(['alt', 'f4']);
111
-
112
- // Win+D (Windows - show desktop)
113
- await testdriver.pressKeys(['winleft', 'd']);
114
-
115
- // Win+L (Windows - lock screen)
116
- await testdriver.pressKeys(['winleft', 'l']);
117
-
118
- // Cmd+Tab (macOS - switch apps)
119
- await testdriver.pressKeys(['command', 'tab']);
120
-
121
- // Cmd+Q (macOS - quit app)
122
- await testdriver.pressKeys(['command', 'q']);
67
+ await testdriver.type('wireless headphones');
123
68
  ```
124
69
 
125
- ### Form Submission
70
+ ### Go to a URL in Chrome
126
71
 
127
72
  ```javascript
128
- // Submit form
73
+ await testdriver.pressKeys(['ctrl', 'l']);
74
+ await testdriver.type('https://testdriver-sandbox.vercel.app/login');
129
75
  await testdriver.pressKeys(['enter']);
130
-
131
- // Cancel/Close
132
- await testdriver.pressKeys(['escape']);
133
-
134
- // Check checkbox
135
- await testdriver.pressKeys(['space']);
136
76
  ```
137
77
 
138
- ### Text Editing
139
-
140
- ```javascript
141
- // Delete selected text
142
- await testdriver.pressKeys(['delete']);
143
-
144
- // Backspace
145
- await testdriver.pressKeys(['backspace']);
146
-
147
- // Select all and delete
148
- await testdriver.pressKeys(['ctrl', 'a']);
149
- await testdriver.pressKeys(['delete']);
78
+ ## Complete example
150
79
 
151
- // Cut text
152
- await testdriver.pressKeys(['ctrl', 'x']);
153
- ```
80
+ ```javascript tests/keyboard-login.test.mjs
81
+ import { describe, expect, it } from 'vitest';
82
+ import { TestDriver } from 'testdriverai/vitest/hooks';
154
83
 
155
- ## Best Practices
84
+ describe('Login', () => {
85
+ it('submits the form from the keyboard', async (context) => {
86
+ const testdriver = TestDriver(context);
87
+ await testdriver.provision.chrome({ url: 'https://testdriver-sandbox.vercel.app/login' });
156
88
 
157
- <Check>
158
- **Wait after shortcuts**
159
-
160
- Some keyboard shortcuts trigger animations or navigation:
161
-
162
- ```javascript
163
- await testdriver.pressKeys(['ctrl', 't']); // New tab
164
- await new Promise(r => setTimeout(r, 500)); // Wait for tab
165
- await testdriver.pressKeys(['ctrl', 'l']); // Focus URL bar
166
- ```
167
- </Check>
89
+ // The sandbox login page shows its test password on screen
90
+ const password = await testdriver.extract('the password');
168
91
 
169
- <Check>
170
- **Use Tab for form navigation**
171
-
172
- Tab is more reliable than clicking multiple fields:
173
-
174
- ```javascript
175
- const firstField = await testdriver.find('email input');
176
- await firstField.click();
177
- await testdriver.type('user@example.com');
178
-
179
- await testdriver.pressKeys(['tab']);
180
- await testdriver.type('password123');
181
-
182
- await testdriver.pressKeys(['tab']);
183
- await testdriver.pressKeys(['enter']); // Submit
184
- ```
185
- </Check>
186
-
187
- <Warning>
188
- **Platform-specific keys**
189
-
190
- Use the appropriate modifier key for the platform:
191
- - Windows/Linux: `'ctrl'`
192
- - macOS: `'command'`
193
-
194
- ```javascript
195
- // For cross-platform, you might need to detect OS
196
- const modKey = process.platform === 'darwin' ? 'command' : 'ctrl';
197
- await testdriver.pressKeys([modKey, 'c']); // Copy
198
- ```
199
- </Warning>
200
-
201
- ## Use Cases
202
-
203
- <AccordionGroup>
204
- <Accordion title="Form Navigation">
205
- ```javascript
206
- // Fill form using Tab
207
- const firstField = await testdriver.find('name field');
208
- await firstField.click();
209
- await testdriver.type('John Doe');
210
-
211
- await testdriver.pressKeys(['tab']);
212
- await testdriver.type('john@example.com');
213
-
92
+ await testdriver.find('Username input field').click();
93
+ await testdriver.type('standard_user');
214
94
  await testdriver.pressKeys(['tab']);
215
- await testdriver.type('555-0123');
216
-
217
- await testdriver.pressKeys(['tab']);
218
- await testdriver.pressKeys(['enter']); // Submit
219
- ```
220
- </Accordion>
221
-
222
- <Accordion title="Text Manipulation">
223
- ```javascript
224
- const textArea = await testdriver.find('comment textarea');
225
- await textArea.click();
226
-
227
- // Select all existing text
228
- await testdriver.pressKeys(['ctrl', 'a']);
229
-
230
- // Copy it
231
- await testdriver.pressKeys(['ctrl', 'c']);
232
-
233
- // Type new text
234
- await testdriver.type('New comment');
235
-
236
- // Undo if needed
237
- await testdriver.pressKeys(['ctrl', 'z']);
238
- ```
239
- </Accordion>
240
-
241
- <Accordion title="Browser Navigation">
242
- ```javascript
243
- // Open new tab
244
- await testdriver.pressKeys(['ctrl', 't']);
245
- await new Promise(r => setTimeout(r, 500));
246
-
247
- // Focus address bar
248
- await testdriver.pressKeys(['ctrl', 'l']);
249
- await testdriver.type('https://example.com');
95
+ await testdriver.type(password, { secret: true });
250
96
  await testdriver.pressKeys(['enter']);
251
-
252
- // Refresh page
253
- await testdriver.pressKeys(['f5']);
254
-
255
- // Close tab
256
- await testdriver.pressKeys(['ctrl', 'w']);
257
- ```
258
- </Accordion>
259
-
260
- <Accordion title="Application Shortcuts">
261
- ```javascript
262
- // Save document
263
- await testdriver.pressKeys(['ctrl', 's']);
264
-
265
- // Print
266
- await testdriver.pressKeys(['ctrl', 'p']);
267
-
268
- // Find in page
269
- await testdriver.pressKeys(['ctrl', 'f']);
270
- await testdriver.type('search term');
271
- await testdriver.pressKeys(['escape']); // Close find
272
- ```
273
- </Accordion>
274
- </AccordionGroup>
275
-
276
- ## Complete Example
277
97
 
278
- ```javascript
279
- import { beforeAll, afterAll, describe, it } from 'vitest';
280
- import TestDriver from 'testdriverai';
281
-
282
- describe('Keyboard Navigation', () => {
283
- let testdriver;
284
-
285
- beforeAll(async () => {
286
- client = new TestDriver(process.env.TD_API_KEY);
287
- await testdriver.auth();
288
- await testdriver.connect();
289
- });
290
-
291
- afterAll(async () => {
292
- await testdriver.disconnect();
293
- });
294
-
295
- it('should navigate form with keyboard', async () => {
296
- await testdriver.focusApplication('Google Chrome');
297
-
298
- // Find first field
299
- const emailField = await testdriver.find('email input');
300
- await emailField.click();
301
- await testdriver.type('user@example.com');
302
-
303
- // Tab through fields
304
- await testdriver.pressKeys(['tab']);
305
- await testdriver.type('John');
306
-
307
- await testdriver.pressKeys(['tab']);
308
- await testdriver.type('Doe');
309
-
310
- await testdriver.pressKeys(['tab']);
311
- await testdriver.type('password123');
312
-
313
- // Submit with Enter
314
- await testdriver.pressKeys(['tab']);
315
- await testdriver.pressKeys(['enter']);
316
-
317
- await testdriver.assert('form submitted successfully');
318
- });
319
-
320
- it('should use keyboard shortcuts', async () => {
321
- // Open new browser tab
322
- await testdriver.pressKeys(['ctrl', 't']);
323
- await new Promise(r => setTimeout(r, 500));
324
-
325
- // Focus address bar
326
- await testdriver.pressKeys(['ctrl', 'l']);
327
- await testdriver.type('https://example.com');
328
- await testdriver.pressKeys(['enter']);
329
-
330
- await new Promise(r => setTimeout(r, 2000));
331
-
332
- // Select all page content
333
- await testdriver.pressKeys(['ctrl', 'a']);
334
-
335
- // Copy
336
- await testdriver.pressKeys(['ctrl', 'c']);
337
-
338
- // Refresh page
339
- await testdriver.pressKeys(['f5']);
98
+ const result = await testdriver.assert('the product list is shown');
99
+ expect(result).toBe(true);
340
100
  });
341
101
  });
342
102
  ```
343
103
 
344
- ## Related Methods
104
+ ## Related
345
105
 
346
- - [`type()`](/type) - Type text
347
- - [`click()`](/click) - Click elements
348
- - [`scroll()`](/scroll) - Scroll pages
106
+ - [type()](/type): enter text into the focused field
107
+ - [click()](/click): focus a field before you type or press keys
108
+ - [Perform actions](/performing-actions): every kind of action in one guide