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.
- package/.github/workflows/testdriver.yml +127 -0
- package/.testdriver/last-sandbox +7 -0
- package/agent/events.js +1 -0
- package/agent/index.js +71 -54
- package/agent/lib/sandbox.js +11 -1
- package/agents.md +393 -0
- package/debug/01-table-initial.png +0 -0
- package/debug/02-after-ai-explore.png +0 -0
- package/debug/02-after-scroll.png +0 -0
- package/docs/docs.json +87 -126
- package/docs/v7/_drafts/caching.mdx +2 -2
- package/docs/v7/{getting-started → _drafts}/installation.mdx +0 -66
- package/docs/v7/{features/coverage.mdx → _drafts/powerful.mdx} +1 -90
- package/docs/v7/{features → _drafts}/scalable.mdx +126 -4
- package/docs/v7/_drafts/screenshot.mdx +155 -0
- package/docs/v7/_drafts/writing-tests.mdx +25 -0
- package/docs/v7/{api/act.mdx → ai.mdx} +27 -27
- package/docs/v7/{api/assert.mdx → assert.mdx} +3 -3
- package/docs/v7/aws-setup.mdx +338 -0
- package/docs/v7/caching.mdx +128 -0
- package/docs/v7/ci-cd.mdx +605 -0
- package/docs/v7/{api/click.mdx → click.mdx} +4 -4
- package/docs/v7/cloud.mdx +120 -0
- package/docs/v7/customizing-devices.mdx +129 -0
- package/docs/v7/{api/dashcam.mdx → dashcam.mdx} +0 -78
- package/docs/v7/{api/doubleClick.mdx → double-click.mdx} +5 -5
- package/docs/v7/{api/elements.mdx → elements.mdx} +1 -54
- package/docs/v7/enterprise.mdx +116 -0
- package/docs/v7/examples.mdx +5 -0
- package/docs/v7/{api/exec.mdx → exec.mdx} +3 -3
- package/docs/v7/{api/find.mdx → find.mdx} +17 -21
- package/docs/v7/{api/focusApplication.mdx → focus-application.mdx} +3 -3
- package/docs/v7/generating-tests.mdx +36 -0
- package/docs/v7/{api/hover.mdx → hover.mdx} +3 -3
- package/docs/v7/locating-elements.mdx +71 -0
- package/docs/v7/making-assertions.mdx +32 -0
- package/docs/v7/{api/mouseDown.mdx → mouse-down.mdx} +7 -7
- package/docs/v7/{api/mouseUp.mdx → mouse-up.mdx} +8 -8
- package/docs/v7/performing-actions.mdx +51 -0
- package/docs/v7/{api/pressKeys.mdx → press-keys.mdx} +3 -3
- package/docs/v7/quickstart.mdx +162 -0
- package/docs/v7/reusable-code.mdx +240 -0
- package/docs/v7/{api/rightClick.mdx → right-click.mdx} +5 -5
- package/docs/v7/running-tests.mdx +181 -0
- package/docs/v7/{api/scroll.mdx → scroll.mdx} +3 -3
- package/docs/v7/secrets.mdx +115 -0
- package/docs/v7/self-hosted.mdx +66 -0
- package/docs/v7/{api/type.mdx → type.mdx} +3 -3
- package/docs/v7/variables.mdx +111 -0
- package/docs/v7/waiting-for-elements.mdx +66 -0
- package/docs/v7/what-is-testdriver.mdx +54 -0
- package/lib/vitest/hooks.mjs +80 -68
- package/package.json +1 -1
- package/sdk.d.ts +22 -9
- package/sdk.js +177 -44
- package/test/manual/reconnect-provision.test.mjs +49 -0
- package/test/manual/reconnect-signin.test.mjs +41 -0
- package/test/testdriver/ai.test.mjs +30 -0
- package/test/testdriver/setup/testHelpers.mjs +0 -1
- package/test/testdriver/windows-installer.test.mjs +61 -0
- package/tests/table-sort-enrollments.test.mjs +72 -0
- package/tests/table-sort-experiment.test.mjs +42 -0
- package/tests/table-sort-setup.test.mjs +59 -0
- package/vitest.config.mjs +1 -0
- package/docs/v7/api/assertions.mdx +0 -403
- package/docs/v7/api/sandbox.mdx +0 -404
- package/docs/v7/features/ai-native.mdx +0 -413
- package/docs/v7/features/application-logs.mdx +0 -353
- package/docs/v7/features/browser-logs.mdx +0 -414
- package/docs/v7/features/cache-management.mdx +0 -402
- package/docs/v7/features/continuous-testing.mdx +0 -346
- package/docs/v7/features/data-driven-testing.mdx +0 -441
- package/docs/v7/features/easy-to-write.mdx +0 -280
- package/docs/v7/features/enterprise.mdx +0 -656
- package/docs/v7/features/fast.mdx +0 -406
- package/docs/v7/features/managed-sandboxes.mdx +0 -384
- package/docs/v7/features/network-monitoring.mdx +0 -568
- package/docs/v7/features/parallel-execution.mdx +0 -381
- package/docs/v7/features/powerful.mdx +0 -531
- package/docs/v7/features/sandbox-customization.mdx +0 -229
- package/docs/v7/features/stable.mdx +0 -473
- package/docs/v7/features/system-performance.mdx +0 -616
- package/docs/v7/features/test-analytics.mdx +0 -373
- package/docs/v7/features/test-cases.mdx +0 -393
- package/docs/v7/features/test-replays.mdx +0 -408
- package/docs/v7/features/test-reports.mdx +0 -308
- package/docs/v7/getting-started/debugging-tests.mdx +0 -382
- package/docs/v7/getting-started/quickstart.mdx +0 -90
- package/docs/v7/getting-started/running-tests.mdx +0 -173
- package/docs/v7/getting-started/setting-up-in-ci.mdx +0 -612
- package/docs/v7/getting-started/writing-tests.mdx +0 -534
- package/docs/v7/overview/what-is-testdriver.mdx +0 -386
- package/docs/v7/presets/chrome-extension.mdx +0 -248
- package/docs/v7/presets/chrome.mdx +0 -300
- package/docs/v7/presets/electron.mdx +0 -460
- package/docs/v7/presets/vscode.mdx +0 -417
- package/docs/v7/presets/webapp.mdx +0 -393
- package/vitest.config.js +0 -18
- /package/docs/v7/{commands → _drafts/commands}/assert.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/exec.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/focus-application.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/hover-image.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/hover-text.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/if.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/match-image.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/press-keys.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/remember.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/run.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/scroll-until-image.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/scroll-until-text.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/scroll.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/type.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/wait-for-image.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/wait-for-text.mdx +0 -0
- /package/docs/v7/{commands → _drafts/commands}/wait.mdx +0 -0
- /package/docs/v7/{getting-started → _drafts}/configuration.mdx +0 -0
- /package/docs/v7/{features → _drafts}/observable.mdx +0 -0
- /package/docs/v7/{platforms → _drafts/platforms}/linux.mdx +0 -0
- /package/docs/v7/{platforms → _drafts/platforms}/macos.mdx +0 -0
- /package/docs/v7/{platforms → _drafts/platforms}/windows.mdx +0 -0
- /package/docs/v7/{playwright.mdx → _drafts/playwright.mdx} +0 -0
- /package/docs/v7/{overview → _drafts}/readme.mdx +0 -0
- /package/docs/v7/{features → _drafts}/reports.mdx +0 -0
- /package/docs/v7/{api/client.mdx → client.mdx} +0 -0
|
@@ -1,100 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "Common Patterns"
|
|
3
3
|
description: "Test everything from desktop apps to chatbots to video content"
|
|
4
4
|
icon: "radar"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
TestDriver provides unmatched testing coverage across platforms, applications, and content types. From desktop applications to AI chatbots, from PDFs to videos, TestDriver can test it all.
|
|
8
8
|
|
|
9
|
-
## Application Types
|
|
10
|
-
|
|
11
|
-
### Desktop Applications
|
|
12
|
-
|
|
13
|
-
Test native desktop applications on Windows, macOS, and Linux with the same simple API:
|
|
14
|
-
|
|
15
|
-
```javascript
|
|
16
|
-
import { test } from 'vitest';
|
|
17
|
-
import { desktop } from 'testdriverai/presets';
|
|
18
|
-
|
|
19
|
-
test('desktop app with file operations', async (context) => {
|
|
20
|
-
const { testdriver } = await desktop(context, {
|
|
21
|
-
appPath: '/Applications/MyApp.app',
|
|
22
|
-
os: 'mac'
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
await testdriver.find('File menu').click();
|
|
26
|
-
await testdriver.find('Open').click();
|
|
27
|
-
await testdriver.find('Documents folder').doubleClick();
|
|
28
|
-
await testdriver.find('test.txt').click();
|
|
29
|
-
await testdriver.find('Open button').click();
|
|
30
|
-
await testdriver.assert('test.txt is displayed in the editor');
|
|
31
|
-
});
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
<Card title="Desktop Preset" icon="desktop" href="/v7/presets/desktop">
|
|
35
|
-
Complete guide to testing desktop applications
|
|
36
|
-
</Card>
|
|
37
|
-
|
|
38
|
-
### VS Code Extensions
|
|
39
|
-
|
|
40
|
-
Test IDE extensions with full access to the VS Code environment:
|
|
41
|
-
|
|
42
|
-
```javascript
|
|
43
|
-
import { test } from 'vitest';
|
|
44
|
-
import { vscode } from 'testdriverai/presets';
|
|
45
|
-
|
|
46
|
-
test('vscode extension with settings', async (context) => {
|
|
47
|
-
const { testdriver } = await vscode(context, {
|
|
48
|
-
workspace: '/tmp/test-project',
|
|
49
|
-
extensions: ['your-extension-id']
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// Open settings
|
|
53
|
-
await testdriver.pressKeys(['cmd', ',']);
|
|
54
|
-
await testdriver.find('search settings input').type('your.extension.setting');
|
|
55
|
-
await testdriver.find('Enable feature checkbox').click();
|
|
56
|
-
|
|
57
|
-
// Verify extension behavior
|
|
58
|
-
await testdriver.pressKeys(['cmd', 'shift', 'p']);
|
|
59
|
-
await testdriver.type('Your Extension Command');
|
|
60
|
-
await testdriver.pressKeys(['enter']);
|
|
61
|
-
await testdriver.assert('Extension panel is visible');
|
|
62
|
-
});
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
<Card title="VS Code Preset" icon="code" href="/v7/presets/vscode">
|
|
66
|
-
Complete guide to testing VS Code extensions
|
|
67
|
-
</Card>
|
|
68
|
-
|
|
69
|
-
### Chrome Extensions
|
|
70
|
-
|
|
71
|
-
Test browser extensions in their natural environment with access to popups, content scripts, and background pages:
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
import { test } from 'vitest';
|
|
75
|
-
import { chromeExtension } from 'testdriverai/presets';
|
|
76
|
-
|
|
77
|
-
test('chrome extension functionality', async (context) => {
|
|
78
|
-
const { testdriver } = await chromeExtension(context, {
|
|
79
|
-
extensionPath: './my-extension',
|
|
80
|
-
url: 'https://example.com'
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Test extension popup
|
|
84
|
-
await testdriver.find('extension icon').click();
|
|
85
|
-
await testdriver.find('Enable feature toggle').click();
|
|
86
|
-
await testdriver.assert('Feature enabled message appears');
|
|
87
|
-
|
|
88
|
-
// Test content script injection
|
|
89
|
-
await testdriver.assert('Extension content is visible on page');
|
|
90
|
-
});
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
<Card title="Chrome Extension Preset" icon="puzzle-piece" href="/v7/presets/chrome-extension">
|
|
94
|
-
Complete guide to testing Chrome extensions
|
|
95
|
-
</Card>
|
|
96
|
-
|
|
97
|
-
## Advanced Use Cases
|
|
98
9
|
|
|
99
10
|
### AI Chatbots
|
|
100
11
|
|
|
@@ -344,13 +344,35 @@ TestDriver integrates seamlessly with all major CI/CD platforms:
|
|
|
344
344
|
|
|
345
345
|
## JUnit Reports
|
|
346
346
|
|
|
347
|
-
Generate JUnit XML reports for test result aggregation
|
|
347
|
+
Generate JUnit XML reports for test result aggregation and CI/CD integration.
|
|
348
|
+
|
|
349
|
+
### Basic Setup
|
|
350
|
+
|
|
351
|
+
Configure Vitest to output JUnit reports by adding a reporter to your config:
|
|
352
|
+
|
|
353
|
+
```javascript vitest.config.mjs
|
|
354
|
+
import { defineConfig } from 'vitest/config';
|
|
355
|
+
|
|
356
|
+
export default defineConfig({
|
|
357
|
+
test: {
|
|
358
|
+
testTimeout: 120000,
|
|
359
|
+
hookTimeout: 120000,
|
|
360
|
+
reporters: ['default', 'junit'],
|
|
361
|
+
outputFile: {
|
|
362
|
+
junit: 'test-report.junit.xml'
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Or run from the command line:
|
|
348
369
|
|
|
349
370
|
```bash
|
|
350
|
-
# Generate JUnit report
|
|
351
371
|
npx vitest run --reporter=junit --outputFile=test-results.xml
|
|
352
372
|
```
|
|
353
373
|
|
|
374
|
+
This generates a standard JUnit XML report:
|
|
375
|
+
|
|
354
376
|
```xml test-results.xml
|
|
355
377
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
356
378
|
<testsuites name="vitest tests" tests="12" failures="0" errors="0" time="125.3">
|
|
@@ -359,12 +381,112 @@ npx vitest run --reporter=junit --outputFile=test-results.xml
|
|
|
359
381
|
<testcase name="invalid credentials show error" time="9.8" />
|
|
360
382
|
<testcase name="password reset works" time="9.0" />
|
|
361
383
|
</testsuite>
|
|
362
|
-
<!-- More test suites -->
|
|
363
384
|
</testsuites>
|
|
364
385
|
```
|
|
365
386
|
|
|
387
|
+
### GitHub Actions PR Comments
|
|
388
|
+
|
|
389
|
+
Use JUnit reports to automatically post test results as comments on pull requests. This provides immediate visibility into test failures without leaving GitHub.
|
|
390
|
+
|
|
391
|
+
```yaml .github/workflows/test.yml
|
|
392
|
+
name: E2E Tests
|
|
393
|
+
|
|
394
|
+
on:
|
|
395
|
+
pull_request:
|
|
396
|
+
branches: [main]
|
|
397
|
+
|
|
398
|
+
permissions:
|
|
399
|
+
contents: read
|
|
400
|
+
pull-requests: write
|
|
401
|
+
checks: write
|
|
402
|
+
|
|
403
|
+
jobs:
|
|
404
|
+
test:
|
|
405
|
+
runs-on: ubuntu-latest
|
|
406
|
+
|
|
407
|
+
steps:
|
|
408
|
+
- uses: actions/checkout@v4
|
|
409
|
+
|
|
410
|
+
- name: Setup Node.js
|
|
411
|
+
uses: actions/setup-node@v4
|
|
412
|
+
with:
|
|
413
|
+
node-version: '20'
|
|
414
|
+
cache: 'npm'
|
|
415
|
+
|
|
416
|
+
- name: Install dependencies
|
|
417
|
+
run: npm ci
|
|
418
|
+
|
|
419
|
+
- name: Run tests
|
|
420
|
+
run: npx vitest run
|
|
421
|
+
env:
|
|
422
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
423
|
+
|
|
424
|
+
- name: Publish Test Results
|
|
425
|
+
uses: EnricoMi/publish-unit-test-result-action@v2
|
|
426
|
+
if: always()
|
|
427
|
+
with:
|
|
428
|
+
files: test-report.junit.xml
|
|
429
|
+
comment_mode: always
|
|
430
|
+
check_name: Test Results
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
<Note>
|
|
434
|
+
The `if: always()` ensures test results are published even when tests fail, so you always see what went wrong.
|
|
435
|
+
</Note>
|
|
436
|
+
|
|
437
|
+
The [publish-unit-test-result-action](https://github.com/EnricoMi/publish-unit-test-result-action) creates:
|
|
438
|
+
|
|
439
|
+
- **PR comments** with a summary table of passed/failed tests
|
|
440
|
+
- **Check runs** visible in the GitHub PR checks tab
|
|
441
|
+
- **Annotations** highlighting failed tests in the diff view
|
|
442
|
+
|
|
443
|
+
### Multi-Platform Testing with JUnit
|
|
444
|
+
|
|
445
|
+
When testing across multiple platforms, use separate check names to distinguish results:
|
|
446
|
+
|
|
447
|
+
```yaml .github/workflows/test.yml
|
|
448
|
+
jobs:
|
|
449
|
+
test-linux:
|
|
450
|
+
runs-on: ubuntu-latest
|
|
451
|
+
steps:
|
|
452
|
+
# ... setup steps ...
|
|
453
|
+
|
|
454
|
+
- name: Run Linux tests
|
|
455
|
+
run: npx vitest run
|
|
456
|
+
env:
|
|
457
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
458
|
+
TD_OS: linux
|
|
459
|
+
|
|
460
|
+
- name: Publish Test Results
|
|
461
|
+
uses: EnricoMi/publish-unit-test-result-action@v2
|
|
462
|
+
if: always()
|
|
463
|
+
with:
|
|
464
|
+
files: test-report.junit.xml
|
|
465
|
+
comment_mode: always
|
|
466
|
+
check_name: Test Results (Linux)
|
|
467
|
+
|
|
468
|
+
test-windows:
|
|
469
|
+
runs-on: ubuntu-latest
|
|
470
|
+
steps:
|
|
471
|
+
# ... setup steps ...
|
|
472
|
+
|
|
473
|
+
- name: Run Windows tests
|
|
474
|
+
run: npx vitest run
|
|
475
|
+
env:
|
|
476
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
477
|
+
TD_OS: windows
|
|
478
|
+
|
|
479
|
+
- name: Publish Test Results
|
|
480
|
+
uses: EnricoMi/publish-unit-test-result-action@v2
|
|
481
|
+
if: always()
|
|
482
|
+
with:
|
|
483
|
+
files: test-report.junit.xml
|
|
484
|
+
comment_mode: always
|
|
485
|
+
check_name: Test Results (Windows)
|
|
486
|
+
```
|
|
487
|
+
|
|
366
488
|
<Check>
|
|
367
|
-
JUnit reports integrate with Jenkins, Azure DevOps, TeamCity, and other CI platforms for test result visualization.
|
|
489
|
+
JUnit reports integrate with Jenkins, Azure DevOps, TeamCity, GitLab, and other CI platforms for test result visualization.
|
|
368
490
|
</Check>
|
|
369
491
|
|
|
370
492
|
## Familiar Test Syntax
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "screenshot()"
|
|
3
|
+
sidebarTitle: "screenshot"
|
|
4
|
+
description: "Capture a screenshot of the current screen"
|
|
5
|
+
icon: "camera"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Capture a screenshot of the current sandbox screen. Returns a base64 encoded PNG, or saves directly to a file and returns the filepath.
|
|
11
|
+
|
|
12
|
+
## Syntax
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
// Options object (recommended)
|
|
16
|
+
await testdriver.screenshot(options)
|
|
17
|
+
|
|
18
|
+
// Legacy positional arguments
|
|
19
|
+
await testdriver.screenshot(scale, silent, mouse)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Parameters
|
|
23
|
+
|
|
24
|
+
<ParamField path="options" type="object">
|
|
25
|
+
Options object for screenshot capture
|
|
26
|
+
</ParamField>
|
|
27
|
+
|
|
28
|
+
<ParamField path="options.scale" type="number" default="1">
|
|
29
|
+
Scale factor for the screenshot (1 = original size, 0.5 = half size, etc.)
|
|
30
|
+
</ParamField>
|
|
31
|
+
|
|
32
|
+
<ParamField path="options.silent" type="boolean" default="false">
|
|
33
|
+
Whether to suppress logging output
|
|
34
|
+
</ParamField>
|
|
35
|
+
|
|
36
|
+
<ParamField path="options.mouse" type="boolean" default="false">
|
|
37
|
+
Whether to include the mouse cursor in the screenshot
|
|
38
|
+
</ParamField>
|
|
39
|
+
|
|
40
|
+
<ParamField path="options.path" type="string">
|
|
41
|
+
File path to save the screenshot. If provided, the screenshot is saved to this file and the filepath is returned instead of base64 data. Directories are created automatically if they don't exist.
|
|
42
|
+
</ParamField>
|
|
43
|
+
|
|
44
|
+
## Returns
|
|
45
|
+
|
|
46
|
+
`Promise<string>` - Base64 encoded PNG screenshot, or the filepath if `options.path` was provided.
|
|
47
|
+
|
|
48
|
+
## Examples
|
|
49
|
+
|
|
50
|
+
### Basic Screenshot (Base64)
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// Capture a screenshot and get base64 data
|
|
54
|
+
const screenshot = await testdriver.screenshot();
|
|
55
|
+
|
|
56
|
+
// Write to file manually
|
|
57
|
+
import fs from 'fs';
|
|
58
|
+
fs.writeFileSync('screenshot.png', Buffer.from(screenshot, 'base64'));
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Save Directly to File
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// Save screenshot directly to a file (returns filepath)
|
|
65
|
+
const filepath = await testdriver.screenshot({ path: './screenshots/test.png' });
|
|
66
|
+
console.log(`Screenshot saved to: ${filepath}`);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### With Mouse Cursor
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
// Include mouse cursor in screenshot
|
|
73
|
+
const screenshot = await testdriver.screenshot({ mouse: true });
|
|
74
|
+
|
|
75
|
+
// Or save to file with mouse cursor
|
|
76
|
+
const filepath = await testdriver.screenshot({
|
|
77
|
+
path: './debug/with-cursor.png',
|
|
78
|
+
mouse: true
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Scaled Screenshot
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
// Capture at half size (useful for reducing file size)
|
|
86
|
+
const screenshot = await testdriver.screenshot({ scale: 0.5 });
|
|
87
|
+
|
|
88
|
+
// Capture at double size
|
|
89
|
+
const filepath = await testdriver.screenshot({
|
|
90
|
+
path: './hires.png',
|
|
91
|
+
scale: 2
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Silent Mode
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
// Capture without logging output
|
|
99
|
+
const screenshot = await testdriver.screenshot({ silent: true });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Legacy Usage
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
// Legacy positional arguments still work
|
|
106
|
+
const screenshot = await testdriver.screenshot(1, false, true);
|
|
107
|
+
// Equivalent to: screenshot({ scale: 1, silent: false, mouse: true })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Use Cases
|
|
111
|
+
|
|
112
|
+
### Debugging Test Failures
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
it('should complete checkout', async (context) => {
|
|
116
|
+
const testdriver = TestDriver(context, { newSandbox: true });
|
|
117
|
+
await testdriver.provision.chrome({ url: 'https://shop.example.com' });
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
await testdriver.find('Checkout button').click();
|
|
121
|
+
await testdriver.assert('Order confirmation is visible');
|
|
122
|
+
} catch (error) {
|
|
123
|
+
// Save screenshot on failure for debugging
|
|
124
|
+
await testdriver.screenshot({ path: './failures/checkout-failed.png' });
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Visual Documentation
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
// Capture screenshots at each step for documentation
|
|
134
|
+
await testdriver.screenshot({ path: './docs/step1-login.png' });
|
|
135
|
+
await testdriver.find('Login button').click();
|
|
136
|
+
await testdriver.screenshot({ path: './docs/step2-dashboard.png' });
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Comparing States
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// Capture before and after states
|
|
143
|
+
const before = await testdriver.screenshot();
|
|
144
|
+
await testdriver.find('Toggle dark mode').click();
|
|
145
|
+
const after = await testdriver.screenshot();
|
|
146
|
+
|
|
147
|
+
// Both are base64 - can be compared or stored
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Notes
|
|
151
|
+
|
|
152
|
+
- Screenshots are captured from the sandbox's virtual display
|
|
153
|
+
- The base64 string does not include a data URI prefix (raw base64)
|
|
154
|
+
- When using `path`, directories are created automatically if they don't exist
|
|
155
|
+
- File format is always PNG regardless of the file extension used
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Writing Tests"
|
|
3
|
+
description: "Learn how to write effective TestDriver tests with natural language"
|
|
4
|
+
icon: "pencil"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Learn how to write effective TestDriver tests. This section covers everything from generating tests with AI to making assertions.
|
|
8
|
+
|
|
9
|
+
<CardGroup cols={2}>
|
|
10
|
+
<Card title="Generating Tests" icon="wand-magic-sparkles" href="./generating-tests">
|
|
11
|
+
Use AI coding agents and exploration mode to generate tests
|
|
12
|
+
</Card>
|
|
13
|
+
<Card title="Locating Elements" icon="crosshairs" href="./locating-elements">
|
|
14
|
+
Find UI elements using natural language descriptions
|
|
15
|
+
</Card>
|
|
16
|
+
<Card title="Waiting for Elements" icon="clock" href="./waiting-for-elements">
|
|
17
|
+
Handle async operations and prevent flaky tests
|
|
18
|
+
</Card>
|
|
19
|
+
<Card title="Performing Actions" icon="computer-mouse" href="./performing-actions">
|
|
20
|
+
Click, type, hover, scroll and more
|
|
21
|
+
</Card>
|
|
22
|
+
<Card title="Making Assertions" icon="check-double" href="./making-assertions">
|
|
23
|
+
Verify application state with AI-powered assertions
|
|
24
|
+
</Card>
|
|
25
|
+
</CardGroup>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
sidebarTitle: "
|
|
2
|
+
title: "ai()"
|
|
3
|
+
sidebarTitle: "ai"
|
|
4
4
|
description: "Execute natural language tasks using AI"
|
|
5
5
|
icon: "wand-magic-sparkles"
|
|
6
6
|
tag: beta
|
|
@@ -8,12 +8,12 @@ tag: beta
|
|
|
8
8
|
|
|
9
9
|
## Overview
|
|
10
10
|
|
|
11
|
-
The `
|
|
11
|
+
The `ai()` method allows you to execute complex tasks using natural language descriptions. TestDriver's AI will figure out the steps needed to accomplish the task.
|
|
12
12
|
|
|
13
13
|
## Syntax
|
|
14
14
|
|
|
15
15
|
```javascript
|
|
16
|
-
await testdriver.
|
|
16
|
+
await testdriver.ai(task, options)
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Parameters
|
|
@@ -42,20 +42,20 @@ await testdriver.act(task, options)
|
|
|
42
42
|
|
|
43
43
|
```javascript
|
|
44
44
|
// Simple task execution
|
|
45
|
-
await testdriver.
|
|
45
|
+
await testdriver.ai('Click the submit button');
|
|
46
46
|
|
|
47
47
|
// Complex multi-step task
|
|
48
|
-
await testdriver.
|
|
48
|
+
await testdriver.ai('Fill out the contact form and submit it');
|
|
49
49
|
|
|
50
50
|
// Navigation task
|
|
51
|
-
await testdriver.
|
|
51
|
+
await testdriver.ai('Go to the settings page and enable notifications');
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
### With Validation
|
|
55
55
|
|
|
56
56
|
```javascript
|
|
57
57
|
// AI will verify the task completed successfully
|
|
58
|
-
const result = await testdriver.
|
|
58
|
+
const result = await testdriver.ai('Complete the checkout process', {
|
|
59
59
|
validateAndLoop: true
|
|
60
60
|
});
|
|
61
61
|
|
|
@@ -66,10 +66,10 @@ console.log('Task result:', result);
|
|
|
66
66
|
|
|
67
67
|
```javascript
|
|
68
68
|
// The AI will break down complex tasks
|
|
69
|
-
await testdriver.
|
|
69
|
+
await testdriver.ai('Search for "laptop", add the first result to cart, and proceed to checkout');
|
|
70
70
|
|
|
71
71
|
// UI exploration
|
|
72
|
-
await testdriver.
|
|
72
|
+
await testdriver.ai('Find and click all menu items to explore the application');
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
## Use Cases
|
|
@@ -79,8 +79,8 @@ await testdriver.act('Find and click all menu items to explore the application')
|
|
|
79
79
|
Use AI to explore unfamiliar applications:
|
|
80
80
|
|
|
81
81
|
```javascript
|
|
82
|
-
await testdriver.
|
|
83
|
-
await testdriver.
|
|
82
|
+
await testdriver.ai('Explore the main navigation menu');
|
|
83
|
+
await testdriver.ai('Try to find the user profile settings');
|
|
84
84
|
```
|
|
85
85
|
</Accordion>
|
|
86
86
|
|
|
@@ -88,8 +88,8 @@ await testdriver.act('Find and click all menu items to explore the application')
|
|
|
88
88
|
Let AI handle multi-step processes:
|
|
89
89
|
|
|
90
90
|
```javascript
|
|
91
|
-
await testdriver.
|
|
92
|
-
await testdriver.
|
|
91
|
+
await testdriver.ai('Complete the multi-step registration form');
|
|
92
|
+
await testdriver.ai('Configure all the advanced settings to default values');
|
|
93
93
|
```
|
|
94
94
|
</Accordion>
|
|
95
95
|
|
|
@@ -97,8 +97,8 @@ await testdriver.act('Find and click all menu items to explore the application')
|
|
|
97
97
|
When exact element locations aren't critical:
|
|
98
98
|
|
|
99
99
|
```javascript
|
|
100
|
-
await testdriver.
|
|
101
|
-
await testdriver.
|
|
100
|
+
await testdriver.ai('Close any popup dialogs');
|
|
101
|
+
await testdriver.ai('Accept the cookie consent if it appears');
|
|
102
102
|
```
|
|
103
103
|
</Accordion>
|
|
104
104
|
</AccordionGroup>
|
|
@@ -110,13 +110,13 @@ await testdriver.act('Find and click all menu items to explore the application')
|
|
|
110
110
|
|
|
111
111
|
```javascript
|
|
112
112
|
// ✅ Good
|
|
113
|
-
await testdriver.
|
|
113
|
+
await testdriver.ai('Add the first product to the shopping cart');
|
|
114
114
|
|
|
115
115
|
// ❌ Too vague
|
|
116
|
-
await testdriver.
|
|
116
|
+
await testdriver.ai('do something');
|
|
117
117
|
|
|
118
118
|
// ❌ Too specific (defeats the purpose)
|
|
119
|
-
await testdriver.
|
|
119
|
+
await testdriver.ai('click at coordinates 500, 300');
|
|
120
120
|
```
|
|
121
121
|
</Check>
|
|
122
122
|
|
|
@@ -125,7 +125,7 @@ await testdriver.act('Find and click all menu items to explore the application')
|
|
|
125
125
|
|
|
126
126
|
```javascript
|
|
127
127
|
// Use AI for setup
|
|
128
|
-
await testdriver.
|
|
128
|
+
await testdriver.ai('Navigate to the login page');
|
|
129
129
|
|
|
130
130
|
// Use explicit methods for critical steps
|
|
131
131
|
const usernameField = await testdriver.find('username input');
|
|
@@ -142,7 +142,7 @@ await testdriver.act('Find and click all menu items to explore the application')
|
|
|
142
142
|
|
|
143
143
|
## When to Use AI vs Explicit Methods
|
|
144
144
|
|
|
145
|
-
### Use `
|
|
145
|
+
### Use `ai()` when:
|
|
146
146
|
- Exploring unfamiliar applications
|
|
147
147
|
- Handling optional UI elements (popups, cookies, etc.)
|
|
148
148
|
- Prototyping tests quickly
|
|
@@ -178,8 +178,8 @@ describe('E-commerce Flow with AI', () => {
|
|
|
178
178
|
await testdriver.focusApplication('Google Chrome');
|
|
179
179
|
|
|
180
180
|
// Use AI for navigation and exploration
|
|
181
|
-
await testdriver.
|
|
182
|
-
await testdriver.
|
|
181
|
+
await testdriver.ai('Browse to the electronics section');
|
|
182
|
+
await testdriver.ai('Find and add a laptop to the cart');
|
|
183
183
|
|
|
184
184
|
// Use explicit methods for critical steps
|
|
185
185
|
const cartIcon = await testdriver.find('shopping cart icon');
|
|
@@ -189,7 +189,7 @@ describe('E-commerce Flow with AI', () => {
|
|
|
189
189
|
console.log('Cart total:', total);
|
|
190
190
|
|
|
191
191
|
// Use AI for checkout flow
|
|
192
|
-
await testdriver.
|
|
192
|
+
await testdriver.ai('Proceed to checkout and fill in shipping details', {
|
|
193
193
|
validateAndLoop: true
|
|
194
194
|
});
|
|
195
195
|
|
|
@@ -201,6 +201,6 @@ describe('E-commerce Flow with AI', () => {
|
|
|
201
201
|
|
|
202
202
|
## Related Methods
|
|
203
203
|
|
|
204
|
-
- [`find()`](/v7/
|
|
205
|
-
- [`assert()`](/v7/
|
|
206
|
-
- [`extract()`](/v7/
|
|
204
|
+
- [`find()`](/v7/find) - Locate specific elements
|
|
205
|
+
- [`assert()`](/v7/assert) - Make assertions
|
|
206
|
+
- [`extract()`](/v7/extract) - Extract information
|
|
@@ -280,6 +280,6 @@ describe('Assertions', () => {
|
|
|
280
280
|
|
|
281
281
|
## Related Methods
|
|
282
282
|
|
|
283
|
-
- [`extract()`](/v7/
|
|
284
|
-
- [`find()`](/v7/
|
|
285
|
-
- [`ai()`](/v7/
|
|
283
|
+
- [`extract()`](/v7/extract) - Extract information for detailed assertions
|
|
284
|
+
- [`find()`](/v7/find) - Locate elements to verify
|
|
285
|
+
- [`ai()`](/v7/ai) - Complex AI-driven tasks
|