testdriverai 7.2.9 → 7.2.11

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 (124) hide show
  1. package/.github/workflows/testdriver.yml +127 -0
  2. package/.testdriver/last-sandbox +7 -0
  3. package/agent/events.js +1 -0
  4. package/agent/index.js +71 -54
  5. package/agent/lib/sandbox.js +11 -1
  6. package/agents.md +393 -0
  7. package/debug/01-table-initial.png +0 -0
  8. package/debug/02-after-ai-explore.png +0 -0
  9. package/debug/02-after-scroll.png +0 -0
  10. package/docs/docs.json +87 -126
  11. package/docs/v7/_drafts/caching.mdx +2 -2
  12. package/docs/v7/{getting-started → _drafts}/installation.mdx +0 -66
  13. package/docs/v7/{features/coverage.mdx → _drafts/powerful.mdx} +1 -90
  14. package/docs/v7/{features → _drafts}/scalable.mdx +126 -4
  15. package/docs/v7/_drafts/screenshot.mdx +155 -0
  16. package/docs/v7/_drafts/writing-tests.mdx +25 -0
  17. package/docs/v7/{api/act.mdx → ai.mdx} +27 -27
  18. package/docs/v7/{api/assert.mdx → assert.mdx} +3 -3
  19. package/docs/v7/aws-setup.mdx +338 -0
  20. package/docs/v7/caching.mdx +128 -0
  21. package/docs/v7/ci-cd.mdx +605 -0
  22. package/docs/v7/{api/click.mdx → click.mdx} +4 -4
  23. package/docs/v7/cloud.mdx +120 -0
  24. package/docs/v7/customizing-devices.mdx +129 -0
  25. package/docs/v7/{api/dashcam.mdx → dashcam.mdx} +0 -78
  26. package/docs/v7/{api/doubleClick.mdx → double-click.mdx} +5 -5
  27. package/docs/v7/{api/elements.mdx → elements.mdx} +1 -54
  28. package/docs/v7/enterprise.mdx +116 -0
  29. package/docs/v7/examples.mdx +5 -0
  30. package/docs/v7/{api/exec.mdx → exec.mdx} +3 -3
  31. package/docs/v7/{api/find.mdx → find.mdx} +17 -21
  32. package/docs/v7/{api/focusApplication.mdx → focus-application.mdx} +3 -3
  33. package/docs/v7/generating-tests.mdx +36 -0
  34. package/docs/v7/{api/hover.mdx → hover.mdx} +3 -3
  35. package/docs/v7/locating-elements.mdx +71 -0
  36. package/docs/v7/making-assertions.mdx +32 -0
  37. package/docs/v7/{api/mouseDown.mdx → mouse-down.mdx} +7 -7
  38. package/docs/v7/{api/mouseUp.mdx → mouse-up.mdx} +8 -8
  39. package/docs/v7/performing-actions.mdx +51 -0
  40. package/docs/v7/{api/pressKeys.mdx → press-keys.mdx} +3 -3
  41. package/docs/v7/quickstart.mdx +162 -0
  42. package/docs/v7/reusable-code.mdx +240 -0
  43. package/docs/v7/{api/rightClick.mdx → right-click.mdx} +5 -5
  44. package/docs/v7/running-tests.mdx +181 -0
  45. package/docs/v7/{api/scroll.mdx → scroll.mdx} +3 -3
  46. package/docs/v7/secrets.mdx +115 -0
  47. package/docs/v7/self-hosted.mdx +66 -0
  48. package/docs/v7/{api/type.mdx → type.mdx} +3 -3
  49. package/docs/v7/variables.mdx +111 -0
  50. package/docs/v7/waiting-for-elements.mdx +66 -0
  51. package/docs/v7/what-is-testdriver.mdx +54 -0
  52. package/lib/vitest/hooks.mjs +80 -68
  53. package/package.json +1 -1
  54. package/sdk.d.ts +22 -9
  55. package/sdk.js +177 -44
  56. package/test/manual/reconnect-provision.test.mjs +49 -0
  57. package/test/manual/reconnect-signin.test.mjs +41 -0
  58. package/test/testdriver/ai.test.mjs +30 -0
  59. package/test/testdriver/setup/testHelpers.mjs +0 -1
  60. package/test/testdriver/windows-installer.test.mjs +61 -0
  61. package/tests/table-sort-enrollments.test.mjs +72 -0
  62. package/tests/table-sort-experiment.test.mjs +42 -0
  63. package/tests/table-sort-setup.test.mjs +59 -0
  64. package/vitest.config.mjs +1 -0
  65. package/docs/v7/api/assertions.mdx +0 -403
  66. package/docs/v7/api/sandbox.mdx +0 -404
  67. package/docs/v7/features/ai-native.mdx +0 -413
  68. package/docs/v7/features/application-logs.mdx +0 -353
  69. package/docs/v7/features/browser-logs.mdx +0 -414
  70. package/docs/v7/features/cache-management.mdx +0 -402
  71. package/docs/v7/features/continuous-testing.mdx +0 -346
  72. package/docs/v7/features/data-driven-testing.mdx +0 -441
  73. package/docs/v7/features/easy-to-write.mdx +0 -280
  74. package/docs/v7/features/enterprise.mdx +0 -656
  75. package/docs/v7/features/fast.mdx +0 -406
  76. package/docs/v7/features/managed-sandboxes.mdx +0 -384
  77. package/docs/v7/features/network-monitoring.mdx +0 -568
  78. package/docs/v7/features/parallel-execution.mdx +0 -381
  79. package/docs/v7/features/powerful.mdx +0 -531
  80. package/docs/v7/features/sandbox-customization.mdx +0 -229
  81. package/docs/v7/features/stable.mdx +0 -473
  82. package/docs/v7/features/system-performance.mdx +0 -616
  83. package/docs/v7/features/test-analytics.mdx +0 -373
  84. package/docs/v7/features/test-cases.mdx +0 -393
  85. package/docs/v7/features/test-replays.mdx +0 -408
  86. package/docs/v7/features/test-reports.mdx +0 -308
  87. package/docs/v7/getting-started/debugging-tests.mdx +0 -382
  88. package/docs/v7/getting-started/quickstart.mdx +0 -90
  89. package/docs/v7/getting-started/running-tests.mdx +0 -173
  90. package/docs/v7/getting-started/setting-up-in-ci.mdx +0 -612
  91. package/docs/v7/getting-started/writing-tests.mdx +0 -534
  92. package/docs/v7/overview/what-is-testdriver.mdx +0 -386
  93. package/docs/v7/presets/chrome-extension.mdx +0 -248
  94. package/docs/v7/presets/chrome.mdx +0 -300
  95. package/docs/v7/presets/electron.mdx +0 -460
  96. package/docs/v7/presets/vscode.mdx +0 -417
  97. package/docs/v7/presets/webapp.mdx +0 -393
  98. package/vitest.config.js +0 -18
  99. /package/docs/v7/{commands → _drafts/commands}/assert.mdx +0 -0
  100. /package/docs/v7/{commands → _drafts/commands}/exec.mdx +0 -0
  101. /package/docs/v7/{commands → _drafts/commands}/focus-application.mdx +0 -0
  102. /package/docs/v7/{commands → _drafts/commands}/hover-image.mdx +0 -0
  103. /package/docs/v7/{commands → _drafts/commands}/hover-text.mdx +0 -0
  104. /package/docs/v7/{commands → _drafts/commands}/if.mdx +0 -0
  105. /package/docs/v7/{commands → _drafts/commands}/match-image.mdx +0 -0
  106. /package/docs/v7/{commands → _drafts/commands}/press-keys.mdx +0 -0
  107. /package/docs/v7/{commands → _drafts/commands}/remember.mdx +0 -0
  108. /package/docs/v7/{commands → _drafts/commands}/run.mdx +0 -0
  109. /package/docs/v7/{commands → _drafts/commands}/scroll-until-image.mdx +0 -0
  110. /package/docs/v7/{commands → _drafts/commands}/scroll-until-text.mdx +0 -0
  111. /package/docs/v7/{commands → _drafts/commands}/scroll.mdx +0 -0
  112. /package/docs/v7/{commands → _drafts/commands}/type.mdx +0 -0
  113. /package/docs/v7/{commands → _drafts/commands}/wait-for-image.mdx +0 -0
  114. /package/docs/v7/{commands → _drafts/commands}/wait-for-text.mdx +0 -0
  115. /package/docs/v7/{commands → _drafts/commands}/wait.mdx +0 -0
  116. /package/docs/v7/{getting-started → _drafts}/configuration.mdx +0 -0
  117. /package/docs/v7/{features → _drafts}/observable.mdx +0 -0
  118. /package/docs/v7/{platforms → _drafts/platforms}/linux.mdx +0 -0
  119. /package/docs/v7/{platforms → _drafts/platforms}/macos.mdx +0 -0
  120. /package/docs/v7/{platforms → _drafts/platforms}/windows.mdx +0 -0
  121. /package/docs/v7/{playwright.mdx → _drafts/playwright.mdx} +0 -0
  122. /package/docs/v7/{overview → _drafts}/readme.mdx +0 -0
  123. /package/docs/v7/{features → _drafts}/reports.mdx +0 -0
  124. /package/docs/v7/{api/client.mdx → client.mdx} +0 -0
@@ -1,441 +0,0 @@
1
- ---
2
- title: "Data-Driven Testing"
3
- description: "Build maintainable test suites with reusable code and dynamic test data"
4
- icon: "table"
5
- ---
6
-
7
- Scale your test suite with reusable code patterns and dynamic data to reduce duplication and maintain consistency across thousands of tests.
8
-
9
- ## Code Snippets for Reusability
10
-
11
- Scale your test suite with reusable code snippets to reduce duplication and maintain consistency:
12
-
13
- <Tabs>
14
- <Tab title="Helper Functions">
15
- ```javascript test/helpers/auth.js
16
- // Reusable authentication helpers
17
- export async function login(testdriver, { email, password }) {
18
- await testdriver.find('email input').type(email);
19
- await testdriver.find('password input').type(password);
20
- await testdriver.find('login button').click();
21
- await testdriver.assert('logged in successfully');
22
- }
23
-
24
- export async function logout(testdriver) {
25
- await testdriver.find('user menu').click();
26
- await testdriver.find('logout button').click();
27
- }
28
- ```
29
-
30
- ```javascript test/checkout.test.js
31
- import { login } from './helpers/auth.js';
32
-
33
- test('checkout flow', async (context) => {
34
- const { testdriver } = await chrome(context, { url });
35
- await login(testdriver, {
36
- email: 'user@example.com',
37
- password: 'password123'
38
- });
39
- // Continue with checkout test
40
- });
41
- ```
42
- </Tab>
43
-
44
- <Tab title="Page Objects">
45
- ```javascript test/pages/LoginPage.js
46
- export class LoginPage {
47
- constructor(testdriver) {
48
- this.testdriver = testdriver;
49
- }
50
-
51
- async login(email, password) {
52
- await this.testdriver.find('email input').type(email);
53
- await this.testdriver.find('password input').type(password);
54
- await this.testdriver.find('submit button').click();
55
- }
56
-
57
- async assertError(message) {
58
- await this.testdriver.assert(`error message shows "${message}"`);
59
- }
60
- }
61
- ```
62
-
63
- ```javascript test/auth.test.js
64
- import { LoginPage } from './pages/LoginPage.js';
65
-
66
- test('invalid login shows error', async (context) => {
67
- const { testdriver } = await chrome(context, { url });
68
- const loginPage = new LoginPage(testdriver);
69
-
70
- await loginPage.login('invalid@test.com', 'wrong');
71
- await loginPage.assertError('Invalid credentials');
72
- });
73
- ```
74
- </Tab>
75
-
76
- <Tab title="Custom Commands">
77
- ```javascript test/commands/navigation.js
78
- export function addNavigationCommands(testdriver) {
79
- testdriver.navigateTo = async (section) => {
80
- await testdriver.find(`${section} nav link`).click();
81
- await testdriver.assert(`${section} page is loaded`);
82
- };
83
-
84
- testdriver.searchFor = async (query) => {
85
- await testdriver.find('search input').type(query);
86
- await testdriver.find('search button').click();
87
- await testdriver.assert('search results are displayed');
88
- };
89
-
90
- return testdriver;
91
- }
92
- ```
93
-
94
- ```javascript test/search.test.js
95
- import { addNavigationCommands } from './commands/navigation.js';
96
-
97
- test('search functionality', async (context) => {
98
- let { testdriver } = await chrome(context, { url });
99
- testdriver = addNavigationCommands(testdriver);
100
-
101
- await testdriver.searchFor('laptop');
102
- // Custom command used
103
- });
104
- ```
105
- </Tab>
106
- </Tabs>
107
-
108
- <Check>
109
- Reusable snippets reduce test maintenance time by up to 70% in large test suites.
110
- </Check>
111
-
112
- ## Dynamic Variables for Data-Driven Tests
113
-
114
- Scale your testing with dynamic data to cover more scenarios:
115
-
116
- <Tabs>
117
- <Tab title="Environment Variables">
118
- ```javascript
119
- import { test } from 'vitest';
120
- import { chrome } from 'testdriverai/presets';
121
-
122
- test('multi-environment testing', async (context) => {
123
- const env = process.env.TEST_ENV || 'staging';
124
- const urls = {
125
- dev: 'https://dev.myapp.com',
126
- staging: 'https://staging.myapp.com',
127
- production: 'https://myapp.com'
128
- };
129
-
130
- const { testdriver } = await chrome(context, {
131
- url: urls[env]
132
- });
133
-
134
- await testdriver.assert('app is running');
135
- });
136
- ```
137
-
138
- ```bash
139
- # Run against different environments
140
- TEST_ENV=dev npx vitest run
141
- TEST_ENV=staging npx vitest run
142
- TEST_ENV=production npx vitest run
143
- ```
144
- </Tab>
145
-
146
- <Tab title="Test Fixtures">
147
- ```javascript test/fixtures/users.js
148
- export const testUsers = [
149
- { email: 'admin@test.com', role: 'admin' },
150
- { email: 'user@test.com', role: 'user' },
151
- { email: 'guest@test.com', role: 'guest' }
152
- ];
153
-
154
- export const products = [
155
- { name: 'Laptop', price: 999 },
156
- { name: 'Mouse', price: 29 },
157
- { name: 'Keyboard', price: 89 }
158
- ];
159
- ```
160
-
161
- ```javascript test/permissions.test.js
162
- import { test } from 'vitest';
163
- import { chrome } from 'testdriverai/presets';
164
- import { testUsers } from './fixtures/users.js';
165
-
166
- test.each(testUsers)('$role can access dashboard', async ({ email, role }, context) => {
167
- const { testdriver } = await chrome(context, { url });
168
-
169
- await testdriver.find('email input').type(email);
170
- await testdriver.find('password input').type('password123');
171
- await testdriver.find('login button').click();
172
-
173
- if (role === 'admin') {
174
- await testdriver.assert('admin panel is visible');
175
- } else {
176
- await testdriver.assert('user dashboard is visible');
177
- }
178
- });
179
- ```
180
- </Tab>
181
-
182
- <Tab title="Dynamic Data Generation">
183
- ```javascript
184
- import { test } from 'vitest';
185
- import { chrome } from 'testdriverai/presets';
186
- import { faker } from '@faker-js/faker';
187
-
188
- test('user registration with dynamic data', async (context) => {
189
- const { testdriver } = await chrome(context, { url });
190
-
191
- // Generate unique test data for each run
192
- const userData = {
193
- firstName: faker.person.firstName(),
194
- lastName: faker.person.lastName(),
195
- email: faker.internet.email(),
196
- password: faker.internet.password({ length: 12 })
197
- };
198
-
199
- await testdriver.find('first name input').type(userData.firstName);
200
- await testdriver.find('last name input').type(userData.lastName);
201
- await testdriver.find('email input').type(userData.email);
202
- await testdriver.find('password input').type(userData.password);
203
- await testdriver.find('register button').click();
204
-
205
- await testdriver.assert('registration successful');
206
- console.log('Registered user:', userData.email);
207
- });
208
- ```
209
-
210
- ```bash
211
- npm install --save-dev @faker-js/faker
212
- ```
213
- </Tab>
214
- </Tabs>
215
-
216
- <Card title="Dynamic Variables Best Practices" icon="lightbulb">
217
- - **Environment configs:** Store URLs, credentials, and settings in env vars
218
- - **Test fixtures:** Maintain reusable test data in separate files
219
- - **Data generators:** Use libraries like Faker for unique test data
220
- - **Parameterization:** Test multiple scenarios with `test.each()`
221
- - **CI/CD integration:** Pass dynamic values via environment variables
222
- </Card>
223
-
224
- ## Secure Secrets Management
225
-
226
- Protect sensitive data in your tests with built-in secrets handling:
227
-
228
- <Tabs>
229
- <Tab title="Secret Type Option">
230
- ```javascript
231
- import { test } from 'vitest';
232
- import { chrome } from 'testdriverai/presets';
233
-
234
- test('login with secret password', async (context) => {
235
- const { testdriver } = await chrome(context, { url });
236
-
237
- await testdriver.find('email input').type('user@example.com');
238
-
239
- // Password is never logged or cached
240
- await testdriver.find('password input').type(process.env.TEST_PASSWORD, {
241
- secret: true
242
- });
243
-
244
- await testdriver.find('login button').click();
245
- await testdriver.assert('logged in successfully');
246
- });
247
- ```
248
-
249
- <Check>
250
- The `secret: true` option prevents sensitive data from appearing in logs, dashcam replays, or cache entries.
251
- </Check>
252
- </Tab>
253
-
254
- <Tab title="Environment Variables">
255
- ```javascript
256
- // .env.test
257
- TEST_PASSWORD=my-secret-password
258
- TEST_API_KEY=sk-1234567890abcdef
259
- TEST_CREDIT_CARD=4111111111111111
260
-
261
- // test/auth.test.js
262
- import { test } from 'vitest';
263
- import { chrome } from 'testdriverai/presets';
264
-
265
- test('secure authentication', async (context) => {
266
- const { testdriver } = await chrome(context, { url });
267
-
268
- // Load secrets from environment
269
- await testdriver.find('password input').type(
270
- process.env.TEST_PASSWORD,
271
- { secret: true }
272
- );
273
-
274
- await testdriver.find('api key input').type(
275
- process.env.TEST_API_KEY,
276
- { secret: true }
277
- );
278
- });
279
- ```
280
-
281
- ```bash
282
- # Install dotenv for local development
283
- npm install --save-dev dotenv
284
-
285
- # Load in test setup
286
- import 'dotenv/config';
287
- ```
288
- </Tab>
289
-
290
- <Tab title="CI/CD Secrets">
291
- ```yaml .github/workflows/test.yml
292
- name: E2E Tests
293
-
294
- on: [push, pull_request]
295
-
296
- jobs:
297
- test:
298
- runs-on: ubuntu-latest
299
- steps:
300
- - uses: actions/checkout@v3
301
- - uses: actions/setup-node@v3
302
- - run: npm install
303
- - run: npx vitest run
304
- env:
305
- TD_API_KEY: ${{ secrets.TD_API_KEY }}
306
- TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}
307
- TEST_API_KEY: ${{ secrets.TEST_API_KEY }}
308
- ```
309
-
310
- Configure secrets in your CI/CD platform:
311
- - **GitHub:** Settings → Secrets and variables → Actions
312
- - **GitLab:** Settings → CI/CD → Variables
313
- - **CircleCI:** Project Settings → Environment Variables
314
- </Tab>
315
-
316
- <Tab title="Helper Functions">
317
- ```javascript test/helpers/secrets.js
318
- // Centralized secret handling
319
- export function getSecret(key) {
320
- const value = process.env[key];
321
- if (!value) {
322
- throw new Error(`Secret ${key} not found in environment`);
323
- }
324
- return value;
325
- }
326
-
327
- export async function typeSecret(testdriver, selector, secretKey) {
328
- const value = getSecret(secretKey);
329
- await testdriver.find(selector).type(value, { secret: true });
330
- }
331
- ```
332
-
333
- ```javascript test/payment.test.js
334
- import { typeSecret } from './helpers/secrets.js';
335
-
336
- test('payment form', async (context) => {
337
- const { testdriver } = await chrome(context, { url });
338
-
339
- await typeSecret(testdriver, 'credit card input', 'TEST_CREDIT_CARD');
340
- await typeSecret(testdriver, 'cvv input', 'TEST_CVV');
341
-
342
- await testdriver.find('submit payment').click();
343
- });
344
- ```
345
- </Tab>
346
- </Tabs>
347
-
348
- <Warning>
349
- Never hardcode secrets in test files or commit them to version control. Always use environment variables or secure secret management systems.
350
- </Warning>
351
-
352
- ## Familiar Test Syntax
353
-
354
- TestDriver works with the test frameworks you already know:
355
-
356
- <Tabs>
357
- <Tab title="Vitest">
358
- ```javascript
359
- import { test, describe, beforeAll, afterAll } from 'vitest';
360
- import { chrome } from 'testdriverai/presets';
361
-
362
- describe('My Feature', () => {
363
- test('should work', async (context) => {
364
- const { testdriver } = await chrome(context, { url });
365
- await testdriver.find('button').click();
366
- });
367
- });
368
- ```
369
- </Tab>
370
-
371
- <Tab title="Jest">
372
- ```javascript
373
- import { chrome } from 'testdriverai/presets';
374
-
375
- describe('My Feature', () => {
376
- test('should work', async () => {
377
- const { testdriver } = await chrome({ url });
378
- await testdriver.find('button').click();
379
- });
380
- });
381
- ```
382
- </Tab>
383
-
384
- <Tab title="Mocha">
385
- ```javascript
386
- import { chrome } from 'testdriverai/presets';
387
-
388
- describe('My Feature', function() {
389
- it('should work', async function() {
390
- const { testdriver } = await chrome(this, { url });
391
- await testdriver.find('button').click();
392
- });
393
- });
394
- ```
395
- </Tab>
396
- </Tabs>
397
-
398
- ## Existing Systems Integration
399
-
400
- Drop TestDriver into your current workflow without disruption:
401
-
402
- ```javascript
403
- import { test, expect } from 'vitest';
404
- import { chrome } from 'testdriverai/presets';
405
-
406
- test('integrates with existing assertions', async (context) => {
407
- const { testdriver } = await chrome(context, { url });
408
-
409
- // Use TestDriver's AI assertions
410
- await testdriver.assert('welcome message is visible');
411
-
412
- // Or use traditional assertions
413
- const button = await testdriver.find('submit button');
414
- expect(button.coordinates).toBeDefined();
415
- expect(button.text).toContain('Submit');
416
-
417
- // Mix and match as needed
418
- const element = await testdriver.exec('js', 'document.title');
419
- expect(element).toBe('My App');
420
- });
421
- ```
422
-
423
- ## Learn More
424
-
425
- <CardGroup cols={2}>
426
- <Card
427
- title="Vitest Integration"
428
- icon="flask-vial"
429
- href="/v7/guides/vitest"
430
- >
431
- Complete Vitest guide
432
- </Card>
433
-
434
- <Card
435
- title="Continuous Testing"
436
- icon="arrows-spin"
437
- href="/v7/features/continuous-testing"
438
- >
439
- CI/CD integration and scaling
440
- </Card>
441
- </CardGroup>