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.
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 +93 -125
  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/doubleClick.mdx → double-click.mdx} +5 -5
  26. package/docs/v7/enterprise.mdx +135 -0
  27. package/docs/v7/examples.mdx +5 -0
  28. package/docs/v7/{api/exec.mdx → exec.mdx} +3 -3
  29. package/docs/v7/{api/find.mdx → find.mdx} +17 -21
  30. package/docs/v7/{api/focusApplication.mdx → focus-application.mdx} +3 -3
  31. package/docs/v7/generating-tests.mdx +32 -0
  32. package/docs/v7/{api/hover.mdx → hover.mdx} +3 -3
  33. package/docs/v7/locating-elements.mdx +71 -0
  34. package/docs/v7/making-assertions.mdx +32 -0
  35. package/docs/v7/{api/mouseDown.mdx → mouse-down.mdx} +7 -7
  36. package/docs/v7/{api/mouseUp.mdx → mouse-up.mdx} +8 -8
  37. package/docs/v7/performing-actions.mdx +51 -0
  38. package/docs/v7/{api/pressKeys.mdx → press-keys.mdx} +3 -3
  39. package/docs/v7/quickstart.mdx +162 -0
  40. package/docs/v7/reusable-code.mdx +240 -0
  41. package/docs/v7/{api/rightClick.mdx → right-click.mdx} +5 -5
  42. package/docs/v7/running-tests.mdx +181 -0
  43. package/docs/v7/{api/scroll.mdx → scroll.mdx} +3 -3
  44. package/docs/v7/secrets.mdx +115 -0
  45. package/docs/v7/self-hosted.mdx +66 -0
  46. package/docs/v7/{api/type.mdx → type.mdx} +3 -3
  47. package/docs/v7/variables.mdx +111 -0
  48. package/docs/v7/waiting-for-elements.mdx +66 -0
  49. package/docs/v7/what-is-testdriver.mdx +54 -0
  50. package/lib/vitest/hooks.mjs +80 -68
  51. package/package.json +1 -1
  52. package/sdk.d.ts +22 -9
  53. package/sdk.js +177 -44
  54. package/test/manual/reconnect-provision.test.mjs +49 -0
  55. package/test/manual/reconnect-signin.test.mjs +41 -0
  56. package/test/testdriver/ai.test.mjs +30 -0
  57. package/test/testdriver/setup/testHelpers.mjs +0 -1
  58. package/test/testdriver/windows-installer.test.mjs +61 -0
  59. package/tests/table-sort-enrollments.test.mjs +72 -0
  60. package/tests/table-sort-experiment.test.mjs +42 -0
  61. package/tests/table-sort-setup.test.mjs +59 -0
  62. package/vitest.config.mjs +1 -0
  63. package/docs/v7/api/assertions.mdx +0 -403
  64. package/docs/v7/features/ai-native.mdx +0 -413
  65. package/docs/v7/features/application-logs.mdx +0 -353
  66. package/docs/v7/features/browser-logs.mdx +0 -414
  67. package/docs/v7/features/cache-management.mdx +0 -402
  68. package/docs/v7/features/continuous-testing.mdx +0 -346
  69. package/docs/v7/features/data-driven-testing.mdx +0 -441
  70. package/docs/v7/features/easy-to-write.mdx +0 -280
  71. package/docs/v7/features/enterprise.mdx +0 -656
  72. package/docs/v7/features/fast.mdx +0 -406
  73. package/docs/v7/features/managed-sandboxes.mdx +0 -384
  74. package/docs/v7/features/network-monitoring.mdx +0 -568
  75. package/docs/v7/features/parallel-execution.mdx +0 -381
  76. package/docs/v7/features/powerful.mdx +0 -531
  77. package/docs/v7/features/sandbox-customization.mdx +0 -229
  78. package/docs/v7/features/stable.mdx +0 -473
  79. package/docs/v7/features/system-performance.mdx +0 -616
  80. package/docs/v7/features/test-analytics.mdx +0 -373
  81. package/docs/v7/features/test-cases.mdx +0 -393
  82. package/docs/v7/features/test-replays.mdx +0 -408
  83. package/docs/v7/features/test-reports.mdx +0 -308
  84. package/docs/v7/getting-started/debugging-tests.mdx +0 -382
  85. package/docs/v7/getting-started/quickstart.mdx +0 -90
  86. package/docs/v7/getting-started/running-tests.mdx +0 -173
  87. package/docs/v7/getting-started/setting-up-in-ci.mdx +0 -612
  88. package/docs/v7/getting-started/writing-tests.mdx +0 -534
  89. package/docs/v7/overview/what-is-testdriver.mdx +0 -386
  90. package/docs/v7/presets/chrome-extension.mdx +0 -248
  91. package/docs/v7/presets/chrome.mdx +0 -300
  92. package/docs/v7/presets/electron.mdx +0 -460
  93. package/docs/v7/presets/vscode.mdx +0 -417
  94. package/docs/v7/presets/webapp.mdx +0 -393
  95. package/vitest.config.js +0 -18
  96. /package/docs/v7/{commands → _drafts/commands}/assert.mdx +0 -0
  97. /package/docs/v7/{commands → _drafts/commands}/exec.mdx +0 -0
  98. /package/docs/v7/{commands → _drafts/commands}/focus-application.mdx +0 -0
  99. /package/docs/v7/{commands → _drafts/commands}/hover-image.mdx +0 -0
  100. /package/docs/v7/{commands → _drafts/commands}/hover-text.mdx +0 -0
  101. /package/docs/v7/{commands → _drafts/commands}/if.mdx +0 -0
  102. /package/docs/v7/{commands → _drafts/commands}/match-image.mdx +0 -0
  103. /package/docs/v7/{commands → _drafts/commands}/press-keys.mdx +0 -0
  104. /package/docs/v7/{commands → _drafts/commands}/remember.mdx +0 -0
  105. /package/docs/v7/{commands → _drafts/commands}/run.mdx +0 -0
  106. /package/docs/v7/{commands → _drafts/commands}/scroll-until-image.mdx +0 -0
  107. /package/docs/v7/{commands → _drafts/commands}/scroll-until-text.mdx +0 -0
  108. /package/docs/v7/{commands → _drafts/commands}/scroll.mdx +0 -0
  109. /package/docs/v7/{commands → _drafts/commands}/type.mdx +0 -0
  110. /package/docs/v7/{commands → _drafts/commands}/wait-for-image.mdx +0 -0
  111. /package/docs/v7/{commands → _drafts/commands}/wait-for-text.mdx +0 -0
  112. /package/docs/v7/{commands → _drafts/commands}/wait.mdx +0 -0
  113. /package/docs/v7/{getting-started → _drafts}/configuration.mdx +0 -0
  114. /package/docs/v7/{features → _drafts}/observable.mdx +0 -0
  115. /package/docs/v7/{platforms → _drafts/platforms}/linux.mdx +0 -0
  116. /package/docs/v7/{platforms → _drafts/platforms}/macos.mdx +0 -0
  117. /package/docs/v7/{platforms → _drafts/platforms}/windows.mdx +0 -0
  118. /package/docs/v7/{playwright.mdx → _drafts/playwright.mdx} +0 -0
  119. /package/docs/v7/{overview → _drafts}/readme.mdx +0 -0
  120. /package/docs/v7/{features → _drafts}/reports.mdx +0 -0
  121. /package/docs/v7/{api/client.mdx → client.mdx} +0 -0
  122. /package/docs/v7/{api/dashcam.mdx → dashcam.mdx} +0 -0
  123. /package/docs/v7/{api/elements.mdx → elements.mdx} +0 -0
  124. /package/docs/v7/{api/sandbox.mdx → sandbox.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>