testdriverai 7.2.3 → 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.
Files changed (142) hide show
  1. package/.github/workflows/publish.yaml +15 -7
  2. package/.github/workflows/testdriver.yml +163 -0
  3. package/.testdriver/last-sandbox +7 -0
  4. package/agent/events.js +1 -0
  5. package/agent/index.js +99 -163
  6. package/agent/lib/sandbox.js +11 -1
  7. package/agents.md +393 -0
  8. package/bin/testdriverai.js +8 -0
  9. package/debug/01-table-initial.png +0 -0
  10. package/debug/02-after-ai-explore.png +0 -0
  11. package/debug/02-after-scroll.png +0 -0
  12. package/debugger/index.html +37 -0
  13. package/docs/docs.json +93 -125
  14. package/docs/v7/_drafts/architecture.mdx +1 -26
  15. package/docs/v7/_drafts/caching.mdx +2 -2
  16. package/docs/v7/{getting-started → _drafts}/installation.mdx +0 -66
  17. package/docs/v7/{features/coverage.mdx → _drafts/powerful.mdx} +1 -90
  18. package/docs/v7/_drafts/quick-start-test-recording.mdx +0 -1
  19. package/docs/v7/{features → _drafts}/scalable.mdx +126 -4
  20. package/docs/v7/_drafts/screenshot.mdx +155 -0
  21. package/docs/v7/_drafts/test-recording.mdx +0 -6
  22. package/docs/v7/_drafts/writing-tests.mdx +25 -0
  23. package/docs/v7/{api/act.mdx → ai.mdx} +28 -27
  24. package/docs/v7/{api/assert.mdx → assert.mdx} +3 -3
  25. package/docs/v7/aws-setup.mdx +338 -0
  26. package/docs/v7/caching.mdx +128 -0
  27. package/docs/v7/ci-cd.mdx +605 -0
  28. package/docs/v7/{api/click.mdx → click.mdx} +4 -4
  29. package/docs/v7/cloud.mdx +120 -0
  30. package/docs/v7/customizing-devices.mdx +129 -0
  31. package/docs/v7/{api/doubleClick.mdx → double-click.mdx} +5 -5
  32. package/docs/v7/enterprise.mdx +135 -0
  33. package/docs/v7/examples.mdx +5 -0
  34. package/docs/v7/{api/exec.mdx → exec.mdx} +3 -3
  35. package/docs/v7/{api/find.mdx → find.mdx} +17 -21
  36. package/docs/v7/{api/focusApplication.mdx → focus-application.mdx} +3 -3
  37. package/docs/v7/generating-tests.mdx +32 -0
  38. package/docs/v7/{api/hover.mdx → hover.mdx} +3 -3
  39. package/docs/v7/locating-elements.mdx +71 -0
  40. package/docs/v7/making-assertions.mdx +32 -0
  41. package/docs/v7/{api/mouseDown.mdx → mouse-down.mdx} +7 -7
  42. package/docs/v7/{api/mouseUp.mdx → mouse-up.mdx} +8 -8
  43. package/docs/v7/performing-actions.mdx +51 -0
  44. package/docs/v7/{api/pressKeys.mdx → press-keys.mdx} +3 -3
  45. package/docs/v7/quickstart.mdx +162 -0
  46. package/docs/v7/reusable-code.mdx +240 -0
  47. package/docs/v7/{api/rightClick.mdx → right-click.mdx} +5 -5
  48. package/docs/v7/running-tests.mdx +181 -0
  49. package/docs/v7/{api/scroll.mdx → scroll.mdx} +3 -3
  50. package/docs/v7/secrets.mdx +115 -0
  51. package/docs/v7/self-hosted.mdx +66 -0
  52. package/docs/v7/{api/type.mdx → type.mdx} +3 -3
  53. package/docs/v7/variables.mdx +111 -0
  54. package/docs/v7/waiting-for-elements.mdx +66 -0
  55. package/docs/v7/what-is-testdriver.mdx +54 -0
  56. package/interfaces/cli/commands/init.js +33 -19
  57. package/interfaces/cli/lib/base.js +24 -0
  58. package/interfaces/cli.js +8 -1
  59. package/interfaces/logger.js +8 -3
  60. package/interfaces/vitest-plugin.mjs +16 -71
  61. package/lib/sentry.js +343 -0
  62. package/lib/vitest/hooks.mjs +81 -81
  63. package/package.json +4 -3
  64. package/sdk-log-formatter.js +41 -0
  65. package/sdk.d.ts +22 -9
  66. package/sdk.js +344 -100
  67. package/test/manual/reconnect-provision.test.mjs +49 -0
  68. package/test/manual/reconnect-signin.test.mjs +41 -0
  69. package/test/testdriver/act.test.mjs +30 -0
  70. package/test/testdriver/ai.test.mjs +30 -0
  71. package/test/testdriver/assert.test.mjs +1 -1
  72. package/test/testdriver/hover-text.test.mjs +1 -1
  73. package/test/testdriver/setup/testHelpers.mjs +8 -119
  74. package/test/testdriver/windows-installer.test.mjs +61 -0
  75. package/tests/example.test.js +33 -0
  76. package/tests/login.js +28 -0
  77. package/tests/table-sort-enrollments.test.mjs +72 -0
  78. package/tests/table-sort-experiment.test.mjs +42 -0
  79. package/tests/table-sort-setup.test.mjs +59 -0
  80. package/vitest.config.mjs +3 -1
  81. package/agent/lib/cache.js +0 -142
  82. package/docs/v7/api/assertions.mdx +0 -403
  83. package/docs/v7/features/ai-native.mdx +0 -413
  84. package/docs/v7/features/application-logs.mdx +0 -353
  85. package/docs/v7/features/browser-logs.mdx +0 -414
  86. package/docs/v7/features/cache-management.mdx +0 -402
  87. package/docs/v7/features/continuous-testing.mdx +0 -346
  88. package/docs/v7/features/data-driven-testing.mdx +0 -441
  89. package/docs/v7/features/easy-to-write.mdx +0 -280
  90. package/docs/v7/features/enterprise.mdx +0 -656
  91. package/docs/v7/features/fast.mdx +0 -406
  92. package/docs/v7/features/managed-sandboxes.mdx +0 -384
  93. package/docs/v7/features/network-monitoring.mdx +0 -568
  94. package/docs/v7/features/parallel-execution.mdx +0 -381
  95. package/docs/v7/features/powerful.mdx +0 -531
  96. package/docs/v7/features/sandbox-customization.mdx +0 -229
  97. package/docs/v7/features/stable.mdx +0 -473
  98. package/docs/v7/features/system-performance.mdx +0 -616
  99. package/docs/v7/features/test-analytics.mdx +0 -373
  100. package/docs/v7/features/test-cases.mdx +0 -393
  101. package/docs/v7/features/test-replays.mdx +0 -408
  102. package/docs/v7/features/test-reports.mdx +0 -308
  103. package/docs/v7/getting-started/debugging-tests.mdx +0 -382
  104. package/docs/v7/getting-started/quickstart.mdx +0 -90
  105. package/docs/v7/getting-started/running-tests.mdx +0 -173
  106. package/docs/v7/getting-started/setting-up-in-ci.mdx +0 -612
  107. package/docs/v7/getting-started/writing-tests.mdx +0 -534
  108. package/docs/v7/overview/what-is-testdriver.mdx +0 -386
  109. package/docs/v7/presets/chrome-extension.mdx +0 -248
  110. package/docs/v7/presets/chrome.mdx +0 -300
  111. package/docs/v7/presets/electron.mdx +0 -460
  112. package/docs/v7/presets/vscode.mdx +0 -417
  113. package/docs/v7/presets/webapp.mdx +0 -393
  114. /package/docs/v7/{commands → _drafts/commands}/assert.mdx +0 -0
  115. /package/docs/v7/{commands → _drafts/commands}/exec.mdx +0 -0
  116. /package/docs/v7/{commands → _drafts/commands}/focus-application.mdx +0 -0
  117. /package/docs/v7/{commands → _drafts/commands}/hover-image.mdx +0 -0
  118. /package/docs/v7/{commands → _drafts/commands}/hover-text.mdx +0 -0
  119. /package/docs/v7/{commands → _drafts/commands}/if.mdx +0 -0
  120. /package/docs/v7/{commands → _drafts/commands}/match-image.mdx +0 -0
  121. /package/docs/v7/{commands → _drafts/commands}/press-keys.mdx +0 -0
  122. /package/docs/v7/{commands → _drafts/commands}/remember.mdx +0 -0
  123. /package/docs/v7/{commands → _drafts/commands}/run.mdx +0 -0
  124. /package/docs/v7/{commands → _drafts/commands}/scroll-until-image.mdx +0 -0
  125. /package/docs/v7/{commands → _drafts/commands}/scroll-until-text.mdx +0 -0
  126. /package/docs/v7/{commands → _drafts/commands}/scroll.mdx +0 -0
  127. /package/docs/v7/{commands → _drafts/commands}/type.mdx +0 -0
  128. /package/docs/v7/{commands → _drafts/commands}/wait-for-image.mdx +0 -0
  129. /package/docs/v7/{commands → _drafts/commands}/wait-for-text.mdx +0 -0
  130. /package/docs/v7/{commands → _drafts/commands}/wait.mdx +0 -0
  131. /package/docs/v7/{getting-started → _drafts}/configuration.mdx +0 -0
  132. /package/docs/v7/{features → _drafts}/observable.mdx +0 -0
  133. /package/docs/v7/{platforms → _drafts/platforms}/linux.mdx +0 -0
  134. /package/docs/v7/{platforms → _drafts/platforms}/macos.mdx +0 -0
  135. /package/docs/v7/{platforms → _drafts/platforms}/windows.mdx +0 -0
  136. /package/docs/v7/{playwright.mdx → _drafts/playwright.mdx} +0 -0
  137. /package/docs/v7/{overview → _drafts}/readme.mdx +0 -0
  138. /package/docs/v7/{features → _drafts}/reports.mdx +0 -0
  139. /package/docs/v7/{api/client.mdx → client.mdx} +0 -0
  140. /package/docs/v7/{api/dashcam.mdx → dashcam.mdx} +0 -0
  141. /package/docs/v7/{api/elements.mdx → elements.mdx} +0 -0
  142. /package/docs/v7/{api/sandbox.mdx → sandbox.mdx} +0 -0
@@ -1,534 +0,0 @@
1
- ---
2
- title: "Writing Tests"
3
- description: "Learn how to write effective TestDriver tests with natural language"
4
- icon: "pencil"
5
- ---
6
-
7
- TestDriver makes writing tests intuitive by using natural language to describe interactions. This guide covers everything you need to know to write effective, maintainable tests.
8
-
9
- ## Basic Test Structure
10
-
11
- Every TestDriver test follows this simple pattern:
12
-
13
- ```javascript
14
- import { test } from 'vitest';
15
- import { TestDriver } from 'testdriverai/vitest/hooks';
16
-
17
- test('descriptive test name', async (context) => {
18
- // 1. Setup: Launch and navigate
19
- const testdriver = TestDriver(context, { headless: true });
20
- await testdriver.provision.chrome({ url: 'https://myapp.com' });
21
-
22
- // 2. Act: Interact with your application
23
- await testdriver.find('email input').type('user@example.com');
24
- await testdriver.find('submit button').click();
25
-
26
- // 3. Assert: Verify expected state
27
- await testdriver.assert('Welcome message is visible');
28
- });
29
- ```
30
-
31
- <Tip>
32
- The TestDriver hook handles all setup and cleanup automatically - no need for manual browser management!
33
- </Tip>
34
-
35
- ## Finding Elements
36
-
37
- Use natural language to describe elements:
38
-
39
- <Tabs>
40
- <Tab title="Good Descriptions">
41
- ```javascript
42
- // ✅ Specific and contextual
43
- await testdriver.find('submit button in the login form');
44
- await testdriver.find('email input field');
45
- await testdriver.find('delete button in the top right corner');
46
- await testdriver.find('first product card in the grid');
47
- await testdriver.find('dropdown menu labeled "Country"');
48
- ```
49
-
50
- These descriptions are:
51
- - Specific enough to locate the element
52
- - Include context (location, parent container)
53
- - Use natural human language
54
- </Tab>
55
-
56
- <Tab title="Avoid Vague">
57
- ```javascript
58
- // ❌ Too vague
59
- await testdriver.find('button');
60
- await testdriver.find('input');
61
- await testdriver.find('link');
62
- await testdriver.find('text');
63
-
64
- // ✅ Better
65
- await testdriver.find('submit button');
66
- await testdriver.find('email input');
67
- await testdriver.find('contact us link');
68
- await testdriver.find('welcome message text');
69
- ```
70
-
71
- Add specificity to help AI locate the exact element.
72
- </Tab>
73
- </Tabs>
74
-
75
- ## Chaining Actions
76
-
77
- TestDriver supports method chaining for cleaner code:
78
-
79
- ```javascript
80
- // Chain find() with actions
81
- await testdriver.find('Login button').click();
82
- await testdriver.find('email input').type('user@example.com');
83
- await testdriver.find('dropdown menu').hover();
84
- await testdriver.find('menu item').doubleClick();
85
- await testdriver.find('context option').rightClick();
86
-
87
- // Or save element reference
88
- const button = await testdriver.find('submit button');
89
- await button.click();
90
- ```
91
-
92
- ## Common Interactions
93
-
94
- <AccordionGroup>
95
- <Accordion title="Clicking Elements">
96
- ```javascript
97
- // Regular click
98
- await testdriver.find('button').click();
99
-
100
- // Double-click
101
- await testdriver.find('file item').doubleClick();
102
-
103
- // Right-click (context menu)
104
- await testdriver.find('text area').rightClick();
105
-
106
- // Click at specific coordinates
107
- await testdriver.click(500, 300);
108
- ```
109
- </Accordion>
110
-
111
- <Accordion title="Typing Text">
112
- ```javascript
113
- // Basic typing
114
- await testdriver.find('search input').type('query text');
115
-
116
- // Type sensitive data (won't be logged)
117
- await testdriver.find('password input').type('secret', { secret: true });
118
-
119
- // Type with delay between keystrokes
120
- await testdriver.find('input').type('slow typing', { delay: 500 });
121
-
122
- // Type numbers
123
- await testdriver.find('age input').type(25);
124
- ```
125
-
126
- <Warning>
127
- Always use `{ secret: true }` for passwords and sensitive data to prevent logging!
128
- </Warning>
129
- </Accordion>
130
-
131
- <Accordion title="Keyboard Shortcuts">
132
- ```javascript
133
- // Single keys
134
- await testdriver.pressKeys(['enter']);
135
- await testdriver.pressKeys(['tab']);
136
- await testdriver.pressKeys(['escape']);
137
-
138
- // Combinations
139
- await testdriver.pressKeys(['ctrl', 'c']); // Copy
140
- await testdriver.pressKeys(['ctrl', 'v']); // Paste
141
- await testdriver.pressKeys(['ctrl', 's']); // Save
142
-
143
- // macOS modifiers
144
- await testdriver.pressKeys(['cmd', 'c']); // macOS copy
145
- await testdriver.pressKeys(['cmd', 'shift', 'p']); // Command palette
146
- ```
147
- </Accordion>
148
-
149
- <Accordion title="Hovering">
150
- ```javascript
151
- // Hover over element to reveal dropdown
152
- await testdriver.find('Products menu').hover();
153
- await testdriver.find('Laptops submenu').click();
154
-
155
- // Hover at coordinates
156
- await testdriver.hover(400, 200);
157
- ```
158
- </Accordion>
159
-
160
- <Accordion title="Scrolling">
161
- ```javascript
162
- // Scroll down
163
- await testdriver.scroll('down', 500);
164
-
165
- // Scroll up
166
- await testdriver.scroll('up', 300);
167
-
168
- // Scroll until text appears
169
- await testdriver.scrollUntilText('Footer content');
170
-
171
- // Scroll until element is visible
172
- await testdriver.scroll('down', 1000);
173
- await testdriver.find('load more button').click();
174
- ```
175
- </Accordion>
176
- </AccordionGroup>
177
-
178
- ## Making Assertions
179
-
180
- Use AI-powered assertions to verify application state:
181
-
182
- ```javascript
183
- // Verify visibility
184
- await testdriver.assert('login page is displayed');
185
- await testdriver.assert('submit button is visible');
186
- await testdriver.assert('loading spinner is not visible');
187
-
188
- // Verify content
189
- await testdriver.assert('page title is "Welcome"');
190
- await testdriver.assert('success message says "Account created"');
191
- await testdriver.assert('error message contains "Invalid email"');
192
-
193
- // Verify state
194
- await testdriver.assert('checkbox is checked');
195
- await testdriver.assert('dropdown shows "United States"');
196
- await testdriver.assert('button is disabled');
197
-
198
- // Verify visual appearance
199
- await testdriver.assert('submit button is blue');
200
- await testdriver.assert('form has red border');
201
- ```
202
-
203
- <Tip>
204
- Assertions automatically wait for the condition to be true, making tests more stable.
205
- </Tip>
206
-
207
- ## Working with Multiple Elements
208
-
209
- Find and interact with multiple elements:
210
-
211
- ```javascript
212
- // Find all matching elements
213
- const products = await testdriver.findAll('product card');
214
- console.log(`Found ${products.length} products`);
215
-
216
- // Interact with each
217
- for (const product of products) {
218
- const title = await product.find('title text');
219
- console.log('Product:', title.text);
220
-
221
- await product.find('add to cart button').click();
222
- }
223
-
224
- // Or find specific element
225
- const firstProduct = products[0];
226
- await firstProduct.click();
227
- ```
228
-
229
- ## Handling Forms
230
-
231
- Complete form example:
232
-
233
- ```javascript
234
- test('fill out contact form', async (context) => {
235
- const { testdriver } = await chrome(context, {
236
- url: 'https://example.com/contact'
237
- });
238
-
239
- // Fill text inputs
240
- await testdriver.find('name input').type('John Doe');
241
- await testdriver.find('email input').type('john@example.com');
242
- await testdriver.find('phone input').type('555-1234');
243
-
244
- // Select from dropdown
245
- await testdriver.find('country dropdown').click();
246
- await testdriver.find('United States option').click();
247
-
248
- // Check checkbox
249
- await testdriver.find('newsletter checkbox').click();
250
-
251
- // Select radio button
252
- await testdriver.find('urgent priority radio button').click();
253
-
254
- // Fill textarea
255
- await testdriver.find('message textarea').type('This is my message.');
256
-
257
- // Submit
258
- await testdriver.find('send message button').click();
259
-
260
- // Verify success
261
- await testdriver.assert('thank you message is displayed');
262
- });
263
- ```
264
-
265
- ## Navigation Patterns
266
-
267
- <Tabs>
268
- <Tab title="Multi-Page Flow">
269
- ```javascript
270
- test('checkout flow', async (context) => {
271
- const { testdriver } = await chrome(context, {
272
- url: 'https://shop.example.com'
273
- });
274
-
275
- // Page 1: Browse products
276
- await testdriver.find('first product').click();
277
- await testdriver.find('add to cart button').click();
278
-
279
- // Page 2: Cart
280
- await testdriver.find('cart icon').click();
281
- await testdriver.find('checkout button').click();
282
-
283
- // Page 3: Shipping info
284
- await testdriver.find('address input').type('123 Main St');
285
- await testdriver.find('continue button').click();
286
-
287
- // Page 4: Payment
288
- await testdriver.find('card number').type('4242424242424242');
289
- await testdriver.find('place order').click();
290
-
291
- // Page 5: Confirmation
292
- await testdriver.assert('order confirmation is shown');
293
- });
294
- ```
295
- </Tab>
296
-
297
- <Tab title="Back Navigation">
298
- ```javascript
299
- // Navigate forward
300
- await testdriver.find('next page link').click();
301
- await testdriver.assert('page 2 is displayed');
302
-
303
- // Go back
304
- await testdriver.pressKeys(['alt', 'left']); // Browser back
305
- await testdriver.assert('page 1 is displayed');
306
- ```
307
- </Tab>
308
-
309
- <Tab title="Opening Links in New Tab">
310
- ```javascript
311
- // Open link in new tab (cmd+click / ctrl+click)
312
- const link = await testdriver.find('external link');
313
- await testdriver.pressKeys(['cmd']); // Hold cmd
314
- await link.click();
315
- // New tab opens
316
-
317
- // Switch between windows
318
- await testdriver.focusWindow(1); // Switch to second window
319
- ```
320
- </Tab>
321
- </Tabs>
322
-
323
- ## Best Practices
324
-
325
- <CardGroup cols={2}>
326
- <Card title="Write Descriptive Selectors" icon="text">
327
- ```javascript
328
- // ✅ Good
329
- await testdriver.find('blue submit button in the bottom right');
330
-
331
- // ❌ Too vague
332
- await testdriver.find('button');
333
- ```
334
- </Card>
335
-
336
- <Card title="Use secret: true for Passwords" icon="lock">
337
- ```javascript
338
- // ✅ Secure
339
- await testdriver.type('password', { secret: true });
340
-
341
- // ❌ Logged in dashcam
342
- await testdriver.type('password');
343
- ```
344
- </Card>
345
-
346
- <Card title="Test User Flows, Not Implementation" icon="route">
347
- ```javascript
348
- // ✅ User-focused
349
- test('user can purchase item', async (context) => {
350
- // Test the complete flow
351
- });
352
-
353
- // ❌ Implementation-focused
354
- test('click button #12345', async (context) => {
355
- // Too specific to implementation
356
- });
357
- ```
358
- </Card>
359
-
360
- <Card title="Use Meaningful Test Names" icon="tag">
361
- ```javascript
362
- // ✅ Clear intent
363
- test('user can reset password via email');
364
-
365
- // ❌ Vague
366
- test('test login');
367
- ```
368
- </Card>
369
- </CardGroup>
370
-
371
- ## Advanced Patterns
372
-
373
- <AccordionGroup>
374
- <Accordion title="Conditional Logic">
375
- ```javascript
376
- // Check if element exists
377
- try {
378
- await testdriver.find('cookie banner', { timeout: 5000 });
379
- // Banner found, dismiss it
380
- await testdriver.find('accept cookies button').click();
381
- } catch (error) {
382
- // Banner not found, continue
383
- console.log('No cookie banner');
384
- }
385
-
386
- // Conditional actions
387
- const loginButton = await testdriver.find('login button');
388
- if (loginButton) {
389
- await loginButton.click();
390
- }
391
- ```
392
- </Accordion>
393
-
394
- <Accordion title="Data-Driven Tests">
395
- ```javascript
396
- const testCases = [
397
- { email: 'valid@example.com', password: 'pass123', shouldPass: true },
398
- { email: 'invalid', password: 'pass123', shouldPass: false },
399
- { email: 'user@example.com', password: 'wrong', shouldPass: false },
400
- ];
401
-
402
- testCases.forEach(({ email, password, shouldPass }) => {
403
- test(`login with ${email}`, async (context) => {
404
- const { testdriver } = await chrome(context, { url });
405
-
406
- await testdriver.find('email').type(email);
407
- await testdriver.find('password').type(password, { secret: true });
408
- await testdriver.find('submit').click();
409
-
410
- if (shouldPass) {
411
- await testdriver.assert('dashboard is visible');
412
- } else {
413
- await testdriver.assert('error message is shown');
414
- }
415
- });
416
- });
417
- ```
418
- </Accordion>
419
-
420
- <Accordion title="Reusable Helpers">
421
- ```javascript
422
- // helpers.js
423
- export async function login(testdriver, email, password) {
424
- await testdriver.find('email input').type(email);
425
- await testdriver.find('password input').type(password, { secret: true });
426
- await testdriver.find('login button').click();
427
- await testdriver.assert('dashboard is visible');
428
- }
429
-
430
- // test.test.js
431
- import { login } from './helpers';
432
-
433
- test('user can view profile', async (context) => {
434
- const { testdriver } = await chrome(context, { url });
435
-
436
- await login(testdriver, 'user@example.com', 'password');
437
-
438
- await testdriver.find('profile link').click();
439
- await testdriver.assert('profile page is displayed');
440
- });
441
- ```
442
- </Accordion>
443
- </AccordionGroup>
444
-
445
- ## Common Patterns
446
-
447
- <Tabs>
448
- <Tab title="Login Flow">
449
- ```javascript
450
- test('user login', async (context) => {
451
- const { testdriver } = await chrome(context, {
452
- url: 'https://myapp.com/login'
453
- });
454
-
455
- await testdriver.find('email input').type('user@example.com');
456
- await testdriver.find('password input').type('secret', { secret: true });
457
- await testdriver.find('Login button').click();
458
-
459
- await testdriver.assert('Dashboard is visible');
460
- await testdriver.assert('Welcome message shows user name');
461
- });
462
- ```
463
- </Tab>
464
-
465
- <Tab title="Search">
466
- ```javascript
467
- test('search functionality', async (context) => {
468
- const { testdriver } = await chrome(context, { url });
469
-
470
- await testdriver.find('search input').type('laptop');
471
- await testdriver.pressKeys(['enter']);
472
-
473
- await testdriver.assert('search results are displayed');
474
- await testdriver.assert('results contain "laptop"');
475
-
476
- const results = await testdriver.findAll('result item');
477
- console.log(`Found ${results.length} results`);
478
- });
479
- ```
480
- </Tab>
481
-
482
- <Tab title="Shopping Cart">
483
- ```javascript
484
- test('add to cart', async (context) => {
485
- const { testdriver } = await chrome(context, { url });
486
-
487
- await testdriver.find('first product').click();
488
- await testdriver.find('add to cart button').click();
489
-
490
- await testdriver.assert('cart badge shows 1');
491
-
492
- await testdriver.find('cart icon').click();
493
- await testdriver.assert('product is in cart');
494
- await testdriver.assert('subtotal is correct');
495
- });
496
- ```
497
- </Tab>
498
- </Tabs>
499
-
500
- ## Next Steps
501
-
502
- <CardGroup cols={2}>
503
- <Card
504
- title="Generate Tests with AI"
505
- icon="wand-magic-sparkles"
506
- href="/v7/getting-started/generating-tests"
507
- >
508
- Use Claude to write tests automatically
509
- </Card>
510
-
511
- <Card
512
- title="Running & Debugging"
513
- icon="bug"
514
- href="/v7/getting-started/running-and-debugging"
515
- >
516
- Run tests and debug failures
517
- </Card>
518
-
519
- <Card
520
- title="API Reference"
521
- icon="book"
522
- href="/v7/api/client"
523
- >
524
- Complete API documentation
525
- </Card>
526
-
527
- <Card
528
- title="Examples"
529
- icon="code"
530
- href="/v7/presets/chrome"
531
- >
532
- View more examples
533
- </Card>
534
- </CardGroup>