testdriverai 6.2.2 → 7.1.0
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/acceptance-linux.yml +75 -0
- package/.github/workflows/acceptance-sdk-tests.yml +133 -0
- package/.vscode/settings.json +5 -1
- package/AGENTS.md +550 -0
- package/CODEOWNERS +0 -1
- package/README.md +126 -0
- package/{testdriver → _testdriver}/acceptance/drag-and-drop.yaml +2 -2
- package/{testdriver → _testdriver}/acceptance/snippets/login.yaml +1 -1
- package/_testdriver/examples/desktop/lifecycle/prerun.yaml +0 -0
- package/{testdriver → _testdriver}/examples/web/lifecycle/prerun.yaml +6 -1
- package/{testdriver → _testdriver}/lifecycle/postrun.yaml +3 -2
- package/_testdriver/lifecycle/prerun.yaml +15 -0
- package/{testdriver → _testdriver}/lifecycle/provision.yaml +7 -2
- package/agent/index.js +300 -85
- package/agent/interface.js +15 -0
- package/agent/lib/cache.js +142 -0
- package/agent/lib/commander.js +1 -39
- package/agent/lib/commands.js +910 -296
- package/agent/lib/redraw.js +129 -41
- package/agent/lib/sandbox.js +29 -6
- package/agent/lib/sdk.js +22 -0
- package/agent/lib/system.js +0 -3
- package/agent/lib/validation.js +1 -7
- package/debug-locate-response.js +82 -0
- package/debugger/index.html +15 -4
- package/docs/ARCHITECTURE.md +424 -0
- package/docs/AWESOME_LOGS_QUICK_REF.md +100 -0
- package/docs/MIGRATION.md +425 -0
- package/docs/PRESETS.md +210 -0
- package/docs/QUICK_START_TEST_RECORDING.md +215 -0
- package/docs/SDK_AWESOME_LOGS.md +468 -0
- package/docs/TEST_RECORDING.md +388 -0
- package/docs/docs.json +286 -152
- package/docs/guide/best-practices-polling.mdx +154 -0
- package/docs/sdk-browser-rendering.md +167 -0
- package/docs/v6/getting-started/self-hosting.mdx +407 -0
- package/docs/{guide → v6/guide}/dashcam.mdx +1 -1
- package/docs/{guide → v6/guide}/environment-variables.mdx +4 -5
- package/docs/{guide → v6/guide}/lifecycle.mdx +1 -1
- package/docs/v6/overview/comparison.mdx +101 -0
- package/docs/v7/README.md +135 -0
- package/docs/v7/api/ai.mdx +205 -0
- package/docs/v7/api/assert.mdx +285 -0
- package/docs/v7/api/assertions.mdx +403 -0
- package/docs/v7/api/click.mdx +287 -0
- package/docs/v7/api/client.mdx +322 -0
- package/docs/v7/api/dashcam.mdx +497 -0
- package/docs/v7/api/doubleClick.mdx +102 -0
- package/docs/v7/api/elements.mdx +479 -0
- package/docs/v7/api/exec.mdx +346 -0
- package/docs/v7/api/find.mdx +316 -0
- package/docs/v7/api/focusApplication.mdx +294 -0
- package/docs/v7/api/hover.mdx +279 -0
- package/docs/v7/api/mouseDown.mdx +161 -0
- package/docs/v7/api/mouseUp.mdx +164 -0
- package/docs/v7/api/pressKeys.mdx +349 -0
- package/docs/v7/api/rightClick.mdx +123 -0
- package/docs/v7/api/sandbox.mdx +404 -0
- package/docs/v7/api/scroll.mdx +300 -0
- package/docs/v7/api/type.mdx +314 -0
- package/docs/v7/commands/assert.mdx +45 -0
- package/docs/v7/commands/exec.mdx +282 -0
- package/docs/v7/commands/focus-application.mdx +44 -0
- package/docs/v7/commands/hover-image.mdx +69 -0
- package/docs/v7/commands/hover-text.mdx +47 -0
- package/docs/v7/commands/if.mdx +53 -0
- package/docs/v7/commands/match-image.mdx +67 -0
- package/docs/v7/commands/press-keys.mdx +87 -0
- package/docs/v7/commands/remember.mdx +49 -0
- package/docs/v7/commands/run.mdx +44 -0
- package/docs/v7/commands/scroll-until-image.mdx +66 -0
- package/docs/v7/commands/scroll-until-text.mdx +60 -0
- package/docs/v7/commands/scroll.mdx +69 -0
- package/docs/v7/commands/type.mdx +45 -0
- package/docs/v7/commands/wait-for-image.mdx +54 -0
- package/docs/v7/commands/wait-for-text.mdx +48 -0
- package/docs/v7/commands/wait.mdx +45 -0
- package/docs/v7/getting-started/configuration.mdx +380 -0
- package/docs/v7/getting-started/quickstart.mdx +332 -0
- package/docs/v7/guides/best-practices.mdx +486 -0
- package/docs/v7/guides/caching-ai.mdx +215 -0
- package/docs/v7/guides/caching-selectors.mdx +292 -0
- package/docs/v7/guides/caching.mdx +366 -0
- package/docs/v7/guides/ci-cd/azure.mdx +587 -0
- package/docs/v7/guides/ci-cd/circleci.mdx +523 -0
- package/docs/v7/guides/ci-cd/github-actions.mdx +457 -0
- package/docs/v7/guides/ci-cd/gitlab.mdx +498 -0
- package/docs/v7/guides/ci-cd/jenkins.mdx +664 -0
- package/docs/v7/guides/ci-cd/travis.mdx +438 -0
- package/docs/v7/guides/debugging.mdx +349 -0
- package/docs/v7/guides/faq.mdx +393 -0
- package/docs/v7/guides/migration.mdx +562 -0
- package/docs/v7/guides/performance.mdx +517 -0
- package/docs/{getting-started → v7/guides}/self-hosting.mdx +11 -12
- package/docs/v7/guides/troubleshooting.mdx +526 -0
- package/docs/v7/guides/vitest-plugin.mdx +477 -0
- package/docs/v7/guides/vitest.mdx +535 -0
- package/docs/v7/platforms/linux.mdx +308 -0
- package/docs/v7/platforms/macos.mdx +433 -0
- package/docs/v7/platforms/windows.mdx +430 -0
- package/docs/v7/playwright.mdx +342 -0
- package/docs/v7/presets/chrome-extension.mdx +223 -0
- package/docs/v7/presets/chrome.mdx +287 -0
- package/docs/v7/presets/electron.mdx +435 -0
- package/docs/v7/presets/vscode.mdx +398 -0
- package/docs/v7/presets/webapp.mdx +396 -0
- package/docs/v7/progressive-apis/CORE.md +459 -0
- package/docs/v7/progressive-apis/HOOKS.md +360 -0
- package/docs/v7/progressive-apis/PROGRESSIVE_DISCLOSURE.md +230 -0
- package/docs/v7/progressive-apis/PROVISION.md +266 -0
- package/eslint.config.js +19 -1
- package/interfaces/cli/lib/base.js +10 -4
- package/interfaces/logger.js +2 -1
- package/interfaces/shared-test-state.mjs +69 -0
- package/interfaces/vitest-plugin.mjs +830 -0
- package/package.json +29 -5
- package/schema.json +8 -29
- package/scripts/view-test-results.mjs +96 -0
- package/sdk-log-formatter.js +714 -0
- package/sdk.d.ts +1028 -0
- package/sdk.js +2567 -0
- package/{.github/workflows/self-hosted.yml → self-hosted.yml} +13 -4
- package/setup/aws/cloudformation.yaml +9 -2
- package/src/core/Dashcam.js +469 -0
- package/src/core/index.d.ts +150 -0
- package/src/core/index.js +12 -0
- package/src/presets/index.mjs +331 -0
- package/src/vitest/extended.mjs +108 -0
- package/src/vitest/hooks.d.ts +119 -0
- package/src/vitest/hooks.mjs +298 -0
- package/src/vitest/index.mjs +64 -0
- package/src/vitest/lifecycle.mjs +277 -0
- package/src/vitest/utils.mjs +150 -0
- package/test/dashcam.test.js +137 -0
- package/test/mcp-example-test.yaml +27 -0
- package/testdriver/acceptance-sdk/QUICK_REFERENCE.md +61 -0
- package/testdriver/acceptance-sdk/README.md +128 -0
- package/testdriver/acceptance-sdk/TEST_REPORTING.md +245 -0
- package/testdriver/acceptance-sdk/assert.test.mjs +26 -0
- package/testdriver/acceptance-sdk/auto-cache-key-demo.test.mjs +56 -0
- package/testdriver/acceptance-sdk/chrome-extension.test.mjs +89 -0
- package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +58 -0
- package/testdriver/acceptance-sdk/element-not-found.test.mjs +25 -0
- package/testdriver/acceptance-sdk/exec-js.test.mjs +43 -0
- package/testdriver/acceptance-sdk/exec-output.test.mjs +59 -0
- package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +57 -0
- package/testdriver/acceptance-sdk/focus-window.test.mjs +36 -0
- package/testdriver/acceptance-sdk/formatted-logging.test.mjs +26 -0
- package/testdriver/acceptance-sdk/hooks-example.test.mjs +38 -0
- package/testdriver/acceptance-sdk/hover-image.test.mjs +34 -0
- package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +38 -0
- package/testdriver/acceptance-sdk/hover-text.test.mjs +27 -0
- package/testdriver/acceptance-sdk/match-image.test.mjs +36 -0
- package/testdriver/acceptance-sdk/presets-example.test.mjs +87 -0
- package/testdriver/acceptance-sdk/press-keys.test.mjs +50 -0
- package/testdriver/acceptance-sdk/prompt.test.mjs +33 -0
- package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +38 -0
- package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +39 -0
- package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +28 -0
- package/testdriver/acceptance-sdk/scroll.test.mjs +41 -0
- package/testdriver/acceptance-sdk/setup/globalTeardown.mjs +11 -0
- package/testdriver/acceptance-sdk/setup/testHelpers.mjs +420 -0
- package/testdriver/acceptance-sdk/setup/vitestSetup.mjs +40 -0
- package/testdriver/acceptance-sdk/sully-ai.test.mjs +234 -0
- package/testdriver/acceptance-sdk/test-console-logs.test.mjs +42 -0
- package/testdriver/acceptance-sdk/type-checking-demo.js +49 -0
- package/testdriver/acceptance-sdk/type.test.mjs +45 -0
- package/verify-element-api.js +89 -0
- package/verify-types.js +0 -0
- package/vitest.config.example.js +19 -0
- package/vitest.config.mjs +66 -0
- package/vitest.config.mjs.bak +44 -0
- package/.github/workflows/acceptance-v6.yml +0 -169
- package/.vscode/mcp.json +0 -9
- package/docs/overview/comparison.mdx +0 -82
- package/testdriver/lifecycle/prerun.yaml +0 -17
- /package/{testdriver/examples/desktop/lifecycle/prerun.yaml → .env.example} +0 -0
- /package/{testdriver → _testdriver}/acceptance/assert.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/dashcam.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/embed.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/exec-js.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/exec-output.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/exec-shell.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/focus-window.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/hover-image.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/hover-text-with-description.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/hover-text.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/if-else.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/match-image.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/press-keys.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/prompt.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/remember.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/screenshots/cart.png +0 -0
- /package/{testdriver → _testdriver}/acceptance/scroll-keyboard.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/scroll-until-image.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/scroll-until-text.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/scroll.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/snippets/match-cart.yaml +0 -0
- /package/{testdriver → _testdriver}/acceptance/type.yaml +0 -0
- /package/{testdriver → _testdriver}/behavior/failure.yaml +0 -0
- /package/{testdriver → _testdriver}/behavior/hover-text.yaml +0 -0
- /package/{testdriver → _testdriver}/behavior/lifecycle/postrun.yaml +0 -0
- /package/{testdriver → _testdriver}/behavior/lifecycle/prerun.yaml +0 -0
- /package/{testdriver → _testdriver}/behavior/lifecycle/provision.yaml +0 -0
- /package/{testdriver → _testdriver}/behavior/secrets.yaml +0 -0
- /package/{testdriver → _testdriver}/edge-cases/dashcam-chrome.yaml +0 -0
- /package/{testdriver → _testdriver}/edge-cases/exec-pwsh-multiline.yaml +0 -0
- /package/{testdriver → _testdriver}/edge-cases/js-exception.yaml +0 -0
- /package/{testdriver → _testdriver}/edge-cases/js-promise.yaml +0 -0
- /package/{testdriver → _testdriver}/edge-cases/lifecycle/postrun.yaml +0 -0
- /package/{testdriver → _testdriver}/edge-cases/prompt-in-middle.yaml +0 -0
- /package/{testdriver → _testdriver}/edge-cases/prompt-nested.yaml +0 -0
- /package/{testdriver → _testdriver}/edge-cases/success-test.yaml +0 -0
- /package/{testdriver → _testdriver}/examples/android/example.yaml +0 -0
- /package/{testdriver → _testdriver}/examples/android/lifecycle/postrun.yaml +0 -0
- /package/{testdriver → _testdriver}/examples/android/lifecycle/provision.yaml +0 -0
- /package/{testdriver → _testdriver}/examples/android/readme.md +0 -0
- /package/{testdriver → _testdriver}/examples/chrome-extension/lifecycle/provision.yaml +0 -0
- /package/{testdriver → _testdriver}/examples/desktop/lifecycle/provision.yaml +0 -0
- /package/{testdriver → _testdriver}/examples/vscode-extension/lifecycle/provision.yaml +0 -0
- /package/{testdriver → _testdriver}/examples/web/lifecycle/postrun.yaml +0 -0
- /package/docs/{account → v6/account}/dashboard.mdx +0 -0
- /package/docs/{account → v6/account}/enterprise.mdx +0 -0
- /package/docs/{account → v6/account}/pricing.mdx +0 -0
- /package/docs/{account → v6/account}/projects.mdx +0 -0
- /package/docs/{account → v6/account}/team.mdx +0 -0
- /package/docs/{action → v6/action}/ami.mdx +0 -0
- /package/docs/{action → v6/action}/performance.mdx +0 -0
- /package/docs/{action → v6/action}/secrets.mdx +0 -0
- /package/docs/{apps → v6/apps}/chrome-extensions.mdx +0 -0
- /package/docs/{apps → v6/apps}/desktop-apps.mdx +0 -0
- /package/docs/{apps → v6/apps}/mobile-apps.mdx +0 -0
- /package/docs/{apps → v6/apps}/static-websites.mdx +0 -0
- /package/docs/{apps → v6/apps}/tauri-apps.mdx +0 -0
- /package/docs/{bugs → v6/bugs}/jira.mdx +0 -0
- /package/docs/{cli → v6/cli}/overview.mdx +0 -0
- /package/docs/{commands → v6/commands}/assert.mdx +0 -0
- /package/docs/{commands → v6/commands}/exec.mdx +0 -0
- /package/docs/{commands → v6/commands}/focus-application.mdx +0 -0
- /package/docs/{commands → v6/commands}/hover-image.mdx +0 -0
- /package/docs/{commands → v6/commands}/hover-text.mdx +0 -0
- /package/docs/{commands → v6/commands}/if.mdx +0 -0
- /package/docs/{commands → v6/commands}/match-image.mdx +0 -0
- /package/docs/{commands → v6/commands}/press-keys.mdx +0 -0
- /package/docs/{commands → v6/commands}/remember.mdx +0 -0
- /package/docs/{commands → v6/commands}/run.mdx +0 -0
- /package/docs/{commands → v6/commands}/scroll-until-image.mdx +0 -0
- /package/docs/{commands → v6/commands}/scroll-until-text.mdx +0 -0
- /package/docs/{commands → v6/commands}/scroll.mdx +0 -0
- /package/docs/{commands → v6/commands}/type.mdx +0 -0
- /package/docs/{commands → v6/commands}/wait-for-image.mdx +0 -0
- /package/docs/{commands → v6/commands}/wait-for-text.mdx +0 -0
- /package/docs/{commands → v6/commands}/wait.mdx +0 -0
- /package/docs/{exporting → v6/exporting}/junit.mdx +0 -0
- /package/docs/{exporting → v6/exporting}/playwright.mdx +0 -0
- /package/docs/{features → v6/features}/auto-healing.mdx +0 -0
- /package/docs/{features → v6/features}/generation.mdx +0 -0
- /package/docs/{features → v6/features}/parallel-testing.mdx +0 -0
- /package/docs/{features → v6/features}/reusable-snippets.mdx +0 -0
- /package/docs/{features → v6/features}/selectorless.mdx +0 -0
- /package/docs/{features → v6/features}/visual-assertions.mdx +0 -0
- /package/docs/{getting-started → v6/getting-started}/ci.mdx +0 -0
- /package/docs/{getting-started → v6/getting-started}/cli.mdx +0 -0
- /package/docs/{getting-started → v6/getting-started}/editing.mdx +0 -0
- /package/docs/{getting-started → v6/getting-started}/playwright.mdx +0 -0
- /package/docs/{getting-started → v6/getting-started}/running.mdx +0 -0
- /package/docs/{getting-started → v6/getting-started}/vscode.mdx +0 -0
- /package/docs/{guide → v6/guide}/assertions.mdx +0 -0
- /package/docs/{guide → v6/guide}/authentication.mdx +0 -0
- /package/docs/{guide → v6/guide}/code.mdx +0 -0
- /package/docs/{guide → v6/guide}/locating.mdx +0 -0
- /package/docs/{guide → v6/guide}/protips.mdx +0 -0
- /package/docs/{guide → v6/guide}/variables.mdx +0 -0
- /package/docs/{guide → v6/guide}/waiting.mdx +0 -0
- /package/docs/{importing → v6/importing}/csv.mdx +0 -0
- /package/docs/{importing → v6/importing}/gherkin.mdx +0 -0
- /package/docs/{importing → v6/importing}/jira.mdx +0 -0
- /package/docs/{importing → v6/importing}/testrail.mdx +0 -0
- /package/docs/{integrations → v6/integrations}/electron.mdx +0 -0
- /package/docs/{integrations → v6/integrations}/netlify.mdx +0 -0
- /package/docs/{integrations → v6/integrations}/vercel.mdx +0 -0
- /package/docs/{interactive → v6/interactive}/explore.mdx +0 -0
- /package/docs/{interactive → v6/interactive}/run.mdx +0 -0
- /package/docs/{interactive → v6/interactive}/save.mdx +0 -0
- /package/docs/{overview → v6/overview}/faq.mdx +0 -0
- /package/docs/{overview → v6/overview}/performance.mdx +0 -0
- /package/docs/{overview → v6/overview}/quickstart.mdx +0 -0
- /package/docs/{overview → v6/overview}/what-is-testdriver.mdx +0 -0
- /package/docs/{scenarios → v6/scenarios}/ai-chatbot.mdx +0 -0
- /package/docs/{scenarios → v6/scenarios}/cookie-banner.mdx +0 -0
- /package/docs/{scenarios → v6/scenarios}/file-upload.mdx +0 -0
- /package/docs/{scenarios → v6/scenarios}/form-filling.mdx +0 -0
- /package/docs/{scenarios → v6/scenarios}/log-in.mdx +0 -0
- /package/docs/{scenarios → v6/scenarios}/pdf-generation.mdx +0 -0
- /package/docs/{scenarios → v6/scenarios}/spell-check.mdx +0 -0
- /package/docs/{security → v6/security}/action.mdx +0 -0
- /package/docs/{security → v6/security}/agent.mdx +0 -0
- /package/docs/{security → v6/security}/platform.mdx +0 -0
- /package/docs/{tutorials → v6/tutorials}/advanced-test.mdx +0 -0
- /package/docs/{tutorials → v6/tutorials}/basic-test.mdx +0 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Using TestDriver with Vitest"
|
|
3
|
+
sidebarTitle: "Vitest Integration"
|
|
4
|
+
description: "Complete guide to integrating TestDriver with Vitest"
|
|
5
|
+
icon: "flask-vial"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
TestDriver integrates seamlessly with Vitest, providing three levels of API complexity to match your needs. From simple preset functions to full manual control, choose the approach that works best for your project.
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
### 1. Install TestDriver
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install --save-dev testdriverai
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. Create Vitest Config
|
|
21
|
+
|
|
22
|
+
```javascript vitest.config.mjs
|
|
23
|
+
import { defineConfig } from 'vitest/config';
|
|
24
|
+
|
|
25
|
+
export default defineConfig({
|
|
26
|
+
test: {
|
|
27
|
+
// Optional: Configure test timeout
|
|
28
|
+
testTimeout: 120000,
|
|
29
|
+
hookTimeout: 120000,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 3. Write Your First Test
|
|
35
|
+
|
|
36
|
+
```javascript example.test.js
|
|
37
|
+
import { test } from 'vitest';
|
|
38
|
+
import { chrome } from 'testdriverai/presets';
|
|
39
|
+
|
|
40
|
+
test('my first test', async (context) => {
|
|
41
|
+
const { testdriver } = await chrome(context, {
|
|
42
|
+
url: 'https://example.com'
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
await testdriver.find('More information link').click();
|
|
46
|
+
await testdriver.assert('IANA information page is visible');
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 4. Run Your Tests
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx vitest
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
That's it! TestDriver automatically handles all setup and teardown.
|
|
57
|
+
|
|
58
|
+
## Three Levels of Integration
|
|
59
|
+
|
|
60
|
+
<CardGroup cols={3}>
|
|
61
|
+
<Card title="Provision API" icon="rocket" href="/v7/progressive-apis/PROVISION">
|
|
62
|
+
**Easiest** - One-line setup
|
|
63
|
+
```javascript
|
|
64
|
+
const { testdriver } = await provision('chrome', { url }, context);
|
|
65
|
+
```
|
|
66
|
+
</Card>
|
|
67
|
+
|
|
68
|
+
<Card title="Hooks API" icon="link" href="/v7/progressive-apis/HOOKS">
|
|
69
|
+
**Flexible** - More control
|
|
70
|
+
```javascript
|
|
71
|
+
const client = useTestDriver(context);
|
|
72
|
+
const dashcam = useDashcam(context, client);
|
|
73
|
+
```
|
|
74
|
+
</Card>
|
|
75
|
+
|
|
76
|
+
<Card title="Core Classes" icon="code" href="/v7/progressive-apis/CORE">
|
|
77
|
+
**Full Control** - Manual everything
|
|
78
|
+
```javascript
|
|
79
|
+
const client = new TestDriver(apiKey);
|
|
80
|
+
await client.connect();
|
|
81
|
+
```
|
|
82
|
+
</Card>
|
|
83
|
+
</CardGroup>
|
|
84
|
+
|
|
85
|
+
## Complete Examples
|
|
86
|
+
|
|
87
|
+
### Web Application Testing
|
|
88
|
+
|
|
89
|
+
```javascript login.test.js
|
|
90
|
+
import { describe, test, expect } from 'vitest';
|
|
91
|
+
import { chrome } from 'testdriverai/presets';
|
|
92
|
+
|
|
93
|
+
describe('User Login', () => {
|
|
94
|
+
test('successful login flow', async (context) => {
|
|
95
|
+
const { testdriver, dashcam } = await chrome(context, {
|
|
96
|
+
url: 'https://myapp.com/login',
|
|
97
|
+
maximized: true
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Fill login form
|
|
101
|
+
await testdriver.find('email input').type('user@example.com');
|
|
102
|
+
await testdriver.find('password input').type('password123');
|
|
103
|
+
await testdriver.find('Login button').click();
|
|
104
|
+
|
|
105
|
+
// Verify dashboard loads
|
|
106
|
+
const result = await testdriver.assert('Welcome message is visible');
|
|
107
|
+
expect(result).toBeTruthy();
|
|
108
|
+
|
|
109
|
+
// Dashcam automatically saves replay URL
|
|
110
|
+
console.log('Replay:', dashcam.url);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('invalid credentials error', async (context) => {
|
|
114
|
+
const { testdriver } = await chrome(context, {
|
|
115
|
+
url: 'https://myapp.com/login'
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
await testdriver.find('email input').type('wrong@example.com');
|
|
119
|
+
await testdriver.find('password input').type('wrongpass');
|
|
120
|
+
await testdriver.find('Login button').click();
|
|
121
|
+
|
|
122
|
+
await testdriver.assert('Invalid credentials error appears');
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### VS Code Extension Testing
|
|
128
|
+
|
|
129
|
+
```javascript extension.test.js
|
|
130
|
+
import { test } from 'vitest';
|
|
131
|
+
import { vscode } from 'testdriverai/presets';
|
|
132
|
+
|
|
133
|
+
test('create new python file', async (context) => {
|
|
134
|
+
const { vscode } = await vscode(context, {
|
|
135
|
+
workspace: '/tmp/test-project',
|
|
136
|
+
extensions: ['ms-python.python']
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Open command palette
|
|
140
|
+
await vscode.pressKeys(['cmd', 'shift', 'p']);
|
|
141
|
+
|
|
142
|
+
// Create new Python file
|
|
143
|
+
await vscode.type('Python: Create New File');
|
|
144
|
+
await vscode.pressKeys(['enter']);
|
|
145
|
+
|
|
146
|
+
// Verify file created
|
|
147
|
+
await vscode.assert('Untitled Python file is open');
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Electron App Testing
|
|
152
|
+
|
|
153
|
+
```javascript electron-app.test.js
|
|
154
|
+
import { test } from 'vitest';
|
|
155
|
+
import { electron } from 'testdriverai/presets';
|
|
156
|
+
|
|
157
|
+
test('file menu operations', async (context) => {
|
|
158
|
+
const { app } = await electron(context, {
|
|
159
|
+
appPath: './dist/my-app',
|
|
160
|
+
args: ['--enable-logging']
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
await app.find('File menu').click();
|
|
164
|
+
await app.find('New Document').click();
|
|
165
|
+
|
|
166
|
+
await app.assert('New document window opens');
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Using Multiple Presets
|
|
171
|
+
|
|
172
|
+
```javascript multi-app.test.js
|
|
173
|
+
import { test } from 'vitest';
|
|
174
|
+
import { chrome, vscode } from 'testdriverai/presets';
|
|
175
|
+
|
|
176
|
+
test('test chrome and vscode together', async (context) => {
|
|
177
|
+
// Both share the same Vitest context for cleanup
|
|
178
|
+
const browser = await chrome(context, {
|
|
179
|
+
url: 'https://example.com'
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const editor = await vscode(context, {
|
|
183
|
+
workspace: '/tmp/project'
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Use both in the same test
|
|
187
|
+
await browser.testdriver.find('link').click();
|
|
188
|
+
await editor.vscode.find('File').click();
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Test Lifecycle
|
|
193
|
+
|
|
194
|
+
TestDriver automatically manages the entire test lifecycle:
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
test('lifecycle example', async (context) => {
|
|
198
|
+
// 1. Setup happens automatically when you call preset
|
|
199
|
+
const { testdriver, dashcam } = await chrome(context, { url });
|
|
200
|
+
|
|
201
|
+
// 2. Your test code runs
|
|
202
|
+
await testdriver.find('button').click();
|
|
203
|
+
|
|
204
|
+
// 3. Teardown happens automatically after test completes
|
|
205
|
+
// - Dashcam stops and saves replay URL
|
|
206
|
+
// - TestDriver disconnects from sandbox
|
|
207
|
+
// - All resources are cleaned up
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Automatic Cleanup
|
|
212
|
+
|
|
213
|
+
Even if your test fails or throws an error, cleanup still happens:
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
test('error handling', async (context) => {
|
|
217
|
+
const { testdriver } = await chrome(context, { url });
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
await testdriver.find('non-existent element').click();
|
|
221
|
+
} catch (error) {
|
|
222
|
+
// Cleanup STILL happens automatically via Vitest hooks
|
|
223
|
+
console.error('Test failed:', error);
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
// No need for finally block or manual cleanup
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Configuration
|
|
231
|
+
|
|
232
|
+
### Environment Variables
|
|
233
|
+
|
|
234
|
+
Create a `.env` file in your project root:
|
|
235
|
+
|
|
236
|
+
```bash .env
|
|
237
|
+
TD_API_KEY=your-api-key-here
|
|
238
|
+
TD_API_ROOT=https://testdriver-api.onrender.com
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
TestDriver automatically reads these when initializing.
|
|
242
|
+
|
|
243
|
+
### Vitest Config Options
|
|
244
|
+
|
|
245
|
+
```javascript vitest.config.mjs
|
|
246
|
+
import { defineConfig } from 'vitest/config';
|
|
247
|
+
|
|
248
|
+
export default defineConfig({
|
|
249
|
+
test: {
|
|
250
|
+
// Recommended: Increase timeouts for UI testing
|
|
251
|
+
testTimeout: 120000, // 2 minutes per test
|
|
252
|
+
hookTimeout: 120000, // 2 minutes for setup/teardown
|
|
253
|
+
|
|
254
|
+
// Optional: Run tests sequentially for resource-intensive tests
|
|
255
|
+
threads: false,
|
|
256
|
+
|
|
257
|
+
// Optional: Limit concurrent tests
|
|
258
|
+
maxConcurrency: 3,
|
|
259
|
+
|
|
260
|
+
// Optional: Enable file watching
|
|
261
|
+
watch: false,
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Per-Test Configuration
|
|
267
|
+
|
|
268
|
+
Override defaults for specific tests:
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
test('long running test', async (context) => {
|
|
272
|
+
const { testdriver } = await chrome(context, {
|
|
273
|
+
url: 'https://slow-app.com',
|
|
274
|
+
dashcam: false, // Disable recording for faster execution
|
|
275
|
+
maximized: false,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Your test code
|
|
279
|
+
}, { timeout: 180000 }); // 3-minute timeout for this test only
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Running Tests
|
|
283
|
+
|
|
284
|
+
### Basic Commands
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# Run all tests
|
|
288
|
+
npx vitest
|
|
289
|
+
|
|
290
|
+
# Run specific file
|
|
291
|
+
npx vitest login.test.js
|
|
292
|
+
|
|
293
|
+
# Run in watch mode
|
|
294
|
+
npx vitest --watch
|
|
295
|
+
|
|
296
|
+
# Run with coverage
|
|
297
|
+
npx vitest --coverage
|
|
298
|
+
|
|
299
|
+
# Run tests matching pattern
|
|
300
|
+
npx vitest --grep "login"
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### CI/CD Integration
|
|
304
|
+
|
|
305
|
+
```yaml .github/workflows/test.yml
|
|
306
|
+
name: TestDriver Tests
|
|
307
|
+
|
|
308
|
+
on: [push, pull_request]
|
|
309
|
+
|
|
310
|
+
jobs:
|
|
311
|
+
test:
|
|
312
|
+
runs-on: ubuntu-latest
|
|
313
|
+
steps:
|
|
314
|
+
- uses: actions/checkout@v3
|
|
315
|
+
|
|
316
|
+
- name: Setup Node.js
|
|
317
|
+
uses: actions/setup-node@v3
|
|
318
|
+
with:
|
|
319
|
+
node-version: '18'
|
|
320
|
+
|
|
321
|
+
- name: Install dependencies
|
|
322
|
+
run: npm install
|
|
323
|
+
|
|
324
|
+
- name: Run tests
|
|
325
|
+
env:
|
|
326
|
+
TD_API_KEY: ${{ secrets.TD_API_KEY }}
|
|
327
|
+
run: npx vitest --run
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Advanced Patterns
|
|
331
|
+
|
|
332
|
+
### Shared Setup with beforeEach
|
|
333
|
+
|
|
334
|
+
```javascript
|
|
335
|
+
import { describe, test, beforeEach } from 'vitest';
|
|
336
|
+
import { chrome } from 'testdriverai/presets';
|
|
337
|
+
|
|
338
|
+
describe('Dashboard Tests', () => {
|
|
339
|
+
let testdriver;
|
|
340
|
+
|
|
341
|
+
beforeEach(async (context) => {
|
|
342
|
+
// Setup runs before each test
|
|
343
|
+
const result = await chrome(context, {
|
|
344
|
+
url: 'https://myapp.com'
|
|
345
|
+
});
|
|
346
|
+
testdriver = result.testdriver;
|
|
347
|
+
|
|
348
|
+
// Shared login
|
|
349
|
+
await testdriver.find('email').type('user@example.com');
|
|
350
|
+
await testdriver.find('password').type('password');
|
|
351
|
+
await testdriver.find('Login').click();
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test('view profile', async () => {
|
|
355
|
+
await testdriver.find('Profile link').click();
|
|
356
|
+
await testdriver.assert('Profile page loads');
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
test('view settings', async () => {
|
|
360
|
+
await testdriver.find('Settings link').click();
|
|
361
|
+
await testdriver.assert('Settings page loads');
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Parameterized Tests
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
import { test } from 'vitest';
|
|
370
|
+
import { chrome } from 'testdriverai/presets';
|
|
371
|
+
|
|
372
|
+
const testCases = [
|
|
373
|
+
{ browser: 'chrome', os: 'linux' },
|
|
374
|
+
{ browser: 'chrome', os: 'windows' },
|
|
375
|
+
{ browser: 'chrome', os: 'mac' },
|
|
376
|
+
];
|
|
377
|
+
|
|
378
|
+
testCases.forEach(({ browser, os }) => {
|
|
379
|
+
test(`login on ${os}`, async (context) => {
|
|
380
|
+
const { testdriver } = await chrome(context, {
|
|
381
|
+
url: 'https://myapp.com',
|
|
382
|
+
os
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
await testdriver.find('Login').click();
|
|
386
|
+
await testdriver.assert('Login successful');
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Custom Helpers
|
|
392
|
+
|
|
393
|
+
```javascript helpers.js
|
|
394
|
+
import { chrome } from 'testdriverai/presets';
|
|
395
|
+
|
|
396
|
+
export async function loginAsUser(context, email, password) {
|
|
397
|
+
const { testdriver } = await chrome(context, {
|
|
398
|
+
url: 'https://myapp.com/login'
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
await testdriver.find('email input').type(email);
|
|
402
|
+
await testdriver.find('password input').type(password);
|
|
403
|
+
await testdriver.find('Login button').click();
|
|
404
|
+
|
|
405
|
+
return testdriver;
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
```javascript test.js
|
|
410
|
+
import { test } from 'vitest';
|
|
411
|
+
import { loginAsUser } from './helpers.js';
|
|
412
|
+
|
|
413
|
+
test('logged in user can view dashboard', async (context) => {
|
|
414
|
+
const testdriver = await loginAsUser(context, 'user@example.com', 'pass123');
|
|
415
|
+
|
|
416
|
+
await testdriver.find('Dashboard link').click();
|
|
417
|
+
await testdriver.assert('Dashboard is visible');
|
|
418
|
+
});
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## Best Practices
|
|
422
|
+
|
|
423
|
+
### 1. Use Descriptive Test Names
|
|
424
|
+
|
|
425
|
+
```javascript
|
|
426
|
+
// ✅ Good
|
|
427
|
+
test('user can login with valid credentials and view dashboard', async (context) => {
|
|
428
|
+
|
|
429
|
+
// ❌ Bad
|
|
430
|
+
test('test1', async (context) => {
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### 2. Enable Dashcam for Debugging
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
test('complex interaction', async (context) => {
|
|
437
|
+
const { testdriver, dashcam } = await chrome(context, {
|
|
438
|
+
url: 'https://myapp.com',
|
|
439
|
+
dashcam: true // Always enable for debugging
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// If test fails, check dashcam.url for replay
|
|
443
|
+
});
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 3. Use Assertions Liberally
|
|
447
|
+
|
|
448
|
+
```javascript
|
|
449
|
+
test('multi-step flow', async (context) => {
|
|
450
|
+
const { testdriver } = await chrome(context, { url });
|
|
451
|
+
|
|
452
|
+
await testdriver.find('Step 1').click();
|
|
453
|
+
await testdriver.assert('Step 1 completed'); // Verify each step
|
|
454
|
+
|
|
455
|
+
await testdriver.find('Step 2').click();
|
|
456
|
+
await testdriver.assert('Step 2 completed');
|
|
457
|
+
});
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### 4. Keep Tests Focused
|
|
461
|
+
|
|
462
|
+
```javascript
|
|
463
|
+
// ✅ Good - One test per scenario
|
|
464
|
+
test('user can login', async (context) => { /* ... */ });
|
|
465
|
+
test('user can logout', async (context) => { /* ... */ });
|
|
466
|
+
|
|
467
|
+
// ❌ Bad - Testing too many things
|
|
468
|
+
test('user can login and logout and change settings and...', async (context) => { /* ... */ });
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### 5. Use Environment Variables for Secrets
|
|
472
|
+
|
|
473
|
+
```javascript
|
|
474
|
+
// ✅ Good
|
|
475
|
+
await testdriver.find('password').type(process.env.TEST_PASSWORD);
|
|
476
|
+
|
|
477
|
+
// ❌ Bad
|
|
478
|
+
await testdriver.find('password').type('hardcoded-password');
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
## Troubleshooting
|
|
482
|
+
|
|
483
|
+
### Tests Timeout
|
|
484
|
+
|
|
485
|
+
Increase timeout in vitest.config.mjs:
|
|
486
|
+
|
|
487
|
+
```javascript
|
|
488
|
+
export default defineConfig({
|
|
489
|
+
test: {
|
|
490
|
+
testTimeout: 180000, // 3 minutes
|
|
491
|
+
},
|
|
492
|
+
});
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### Cleanup Not Working
|
|
496
|
+
|
|
497
|
+
Make sure you're passing the `context` parameter:
|
|
498
|
+
|
|
499
|
+
```javascript
|
|
500
|
+
// ✅ Correct
|
|
501
|
+
test('my test', async (context) => {
|
|
502
|
+
await chrome(context, { url });
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// ❌ Wrong - cleanup won't work
|
|
506
|
+
test('my test', async () => {
|
|
507
|
+
await chrome({}, { url });
|
|
508
|
+
});
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### Dashcam URL Not Available
|
|
512
|
+
|
|
513
|
+
Ensure Dashcam is enabled and check for errors:
|
|
514
|
+
|
|
515
|
+
```javascript
|
|
516
|
+
const { testdriver, dashcam } = await chrome(context, {
|
|
517
|
+
url: 'https://example.com',
|
|
518
|
+
dashcam: true
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
if (dashcam) {
|
|
522
|
+
console.log('Replay URL:', dashcam.url);
|
|
523
|
+
} else {
|
|
524
|
+
console.error('Dashcam not initialized');
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
## See Also
|
|
529
|
+
|
|
530
|
+
- [Provision API](/v7/progressive-apis/PROVISION) - One-line setup for common apps
|
|
531
|
+
- [Hooks API](/v7/progressive-apis/HOOKS) - Flexible lifecycle control
|
|
532
|
+
- [Chrome Preset](/v7/presets/chrome) - Browser testing
|
|
533
|
+
- [VS Code Preset](/v7/presets/vscode) - Extension testing
|
|
534
|
+
- [Electron Preset](/v7/presets/electron) - Desktop app testing
|
|
535
|
+
- [Vitest Plugin](/v7/guides/vitest-plugin) - Test recording and reporting
|