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,425 @@
|
|
|
1
|
+
# Migration Guide: v6 → v7
|
|
2
|
+
|
|
3
|
+
This guide helps you migrate from the old TestDriver API (v6) to the new SDK architecture (v7).
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
v7 introduces a **progressive disclosure** pattern with three API levels:
|
|
8
|
+
|
|
9
|
+
1. **Presets** (Beginner) - Zero config, instant setup
|
|
10
|
+
2. **Hooks** (Intermediate) - Flexible lifecycle management
|
|
11
|
+
3. **Core Classes** (Advanced) - Full manual control
|
|
12
|
+
|
|
13
|
+
You can mix and match these patterns based on your needs.
|
|
14
|
+
|
|
15
|
+
## Quick Migration Examples
|
|
16
|
+
|
|
17
|
+
### Before (v6) - Legacy Helpers
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
import { test } from 'vitest';
|
|
21
|
+
import { authDashcam, startDashcam, stopDashcam } from 'testdriverai';
|
|
22
|
+
|
|
23
|
+
test('my test', async ({ client }) => {
|
|
24
|
+
await authDashcam(client);
|
|
25
|
+
await startDashcam(client);
|
|
26
|
+
|
|
27
|
+
await client.find('Login button').click();
|
|
28
|
+
|
|
29
|
+
const url = await stopDashcam(client);
|
|
30
|
+
console.log('Replay:', url);
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### After (v7) - Using Presets
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
import { test } from 'vitest';
|
|
38
|
+
import { chromePreset } from 'testdriverai/presets';
|
|
39
|
+
|
|
40
|
+
test('my test', async (context) => {
|
|
41
|
+
const { client } = await chromePreset(context, {
|
|
42
|
+
url: 'https://myapp.com'
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Dashcam already running, auto-stops at test end
|
|
46
|
+
await client.find('Login button').click();
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### After (v7) - Using Hooks
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
import { test } from 'vitest';
|
|
54
|
+
import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
|
|
55
|
+
|
|
56
|
+
test('my test', async (context) => {
|
|
57
|
+
const client = useTestDriver(context, { os: 'linux' });
|
|
58
|
+
const dashcam = useDashcam(context, client, {
|
|
59
|
+
autoAuth: true,
|
|
60
|
+
autoStart: true,
|
|
61
|
+
autoStop: true
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await client.find('Login button').click();
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### After (v7) - Using Core Classes
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
import { test } from 'vitest';
|
|
72
|
+
import { TestDriver, Dashcam } from 'testdriverai/core';
|
|
73
|
+
|
|
74
|
+
test('my test', async (context) => {
|
|
75
|
+
const client = new TestDriver(process.env.TD_API_KEY, { os: 'linux' });
|
|
76
|
+
const dashcam = new Dashcam(client);
|
|
77
|
+
|
|
78
|
+
await client.auth();
|
|
79
|
+
await client.connect();
|
|
80
|
+
|
|
81
|
+
await dashcam.auth();
|
|
82
|
+
await dashcam.start();
|
|
83
|
+
|
|
84
|
+
await client.find('Login button').click();
|
|
85
|
+
|
|
86
|
+
const url = await dashcam.stop();
|
|
87
|
+
await client.disconnect();
|
|
88
|
+
|
|
89
|
+
console.log('Replay:', url);
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Package Exports
|
|
94
|
+
|
|
95
|
+
v7 introduces multiple entry points for different use cases:
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
// Main SDK (unchanged)
|
|
99
|
+
import TestDriver from 'testdriverai';
|
|
100
|
+
|
|
101
|
+
// Core classes
|
|
102
|
+
import { TestDriver, Dashcam } from 'testdriverai/core';
|
|
103
|
+
|
|
104
|
+
// Vitest hooks
|
|
105
|
+
import { useTestDriver, useDashcam } from 'testdriverai/vitest/hooks';
|
|
106
|
+
|
|
107
|
+
// Presets
|
|
108
|
+
import { chromePreset, vscodePreset } from 'testdriverai/presets';
|
|
109
|
+
|
|
110
|
+
// Vitest plugin (unchanged)
|
|
111
|
+
import testDriver from 'testdriverai/vitest';
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## API Changes
|
|
115
|
+
|
|
116
|
+
### Dashcam Lifecycle Helpers (DEPRECATED)
|
|
117
|
+
|
|
118
|
+
The following functions are **deprecated** but still work for backward compatibility:
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
// ❌ OLD (still works, but deprecated)
|
|
122
|
+
import {
|
|
123
|
+
authDashcam,
|
|
124
|
+
addDashcamLog,
|
|
125
|
+
startDashcam,
|
|
126
|
+
stopDashcam
|
|
127
|
+
} from 'testdriverai';
|
|
128
|
+
|
|
129
|
+
authDashcam(client);
|
|
130
|
+
startDashcam(client);
|
|
131
|
+
stopDashcam(client);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Migrate to:**
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// ✅ NEW - Direct class usage
|
|
138
|
+
import { Dashcam } from 'testdriverai/core';
|
|
139
|
+
|
|
140
|
+
const dashcam = new Dashcam(client);
|
|
141
|
+
await dashcam.auth();
|
|
142
|
+
await dashcam.start();
|
|
143
|
+
const url = await dashcam.stop();
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Or even better:
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
// ✅ NEW - Using hooks
|
|
150
|
+
import { useDashcam } from 'testdriverai/vitest/hooks';
|
|
151
|
+
|
|
152
|
+
const dashcam = useDashcam(context, client, {
|
|
153
|
+
autoAuth: true,
|
|
154
|
+
autoStart: true,
|
|
155
|
+
autoStop: true
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### TestDriver Client Creation
|
|
160
|
+
|
|
161
|
+
**No changes needed** - the main SDK API remains the same:
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
// Still works exactly the same
|
|
165
|
+
import TestDriver from 'testdriverai';
|
|
166
|
+
const client = new TestDriver(apiKey, { os: 'linux' });
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
But you now have cleaner alternatives:
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
// Using hooks (auto-cleanup)
|
|
173
|
+
import { useTestDriver } from 'testdriverai/vitest/hooks';
|
|
174
|
+
const client = useTestDriver(context, { os: 'linux' });
|
|
175
|
+
|
|
176
|
+
// Using presets (zero config)
|
|
177
|
+
import { chromePreset } from 'testdriverai/presets';
|
|
178
|
+
const { browser } = await chromePreset(context, { url: 'https://example.com' });
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Migration Strategies
|
|
182
|
+
|
|
183
|
+
### Strategy 1: Gradual Migration
|
|
184
|
+
|
|
185
|
+
Keep existing tests working, adopt new APIs for new tests:
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
// old-test.js - Leave as-is
|
|
189
|
+
import { authDashcam, startDashcam } from 'testdriverai';
|
|
190
|
+
|
|
191
|
+
// new-test.js - Use new APIs
|
|
192
|
+
import { chromePreset } from 'testdriverai/presets';
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The old helpers will continue to work indefinitely.
|
|
196
|
+
|
|
197
|
+
### Strategy 2: Convert to Hooks
|
|
198
|
+
|
|
199
|
+
Replace lifecycle helpers with hooks for better lifecycle management:
|
|
200
|
+
|
|
201
|
+
**Before:**
|
|
202
|
+
```javascript
|
|
203
|
+
import { authDashcam, startDashcam, stopDashcam } from 'testdriverai';
|
|
204
|
+
|
|
205
|
+
test('my test', async ({ client }) => {
|
|
206
|
+
await authDashcam(client);
|
|
207
|
+
await startDashcam(client);
|
|
208
|
+
// test code
|
|
209
|
+
await stopDashcam(client);
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**After:**
|
|
214
|
+
```javascript
|
|
215
|
+
import { useDashcam } from 'testdriverai/vitest/hooks';
|
|
216
|
+
|
|
217
|
+
test('my test', async (context) => {
|
|
218
|
+
// Assuming client is already available via plugin or another hook
|
|
219
|
+
const dashcam = useDashcam(context, client, {
|
|
220
|
+
autoAuth: true,
|
|
221
|
+
autoStart: true,
|
|
222
|
+
autoStop: true
|
|
223
|
+
});
|
|
224
|
+
// test code
|
|
225
|
+
// Auto-stops at test end
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Strategy 3: Adopt Presets
|
|
230
|
+
|
|
231
|
+
For common scenarios (Chrome, VS Code, Electron), use presets:
|
|
232
|
+
|
|
233
|
+
**Before:**
|
|
234
|
+
```javascript
|
|
235
|
+
test('chrome test', async ({ client }) => {
|
|
236
|
+
await authDashcam(client);
|
|
237
|
+
await startDashcam(client);
|
|
238
|
+
|
|
239
|
+
await client.exec('sh', 'google-chrome "https://example.com" &', 30000);
|
|
240
|
+
await client.focusApplication('Google Chrome');
|
|
241
|
+
|
|
242
|
+
await client.find('button').click();
|
|
243
|
+
|
|
244
|
+
await stopDashcam(client);
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**After:**
|
|
249
|
+
```javascript
|
|
250
|
+
test('chrome test', async (context) => {
|
|
251
|
+
const { browser } = await chromePreset(context, {
|
|
252
|
+
url: 'https://example.com'
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
await browser.find('button').click();
|
|
256
|
+
// Dashcam auto-stops, cleanup automatic
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Benefits of Migration
|
|
261
|
+
|
|
262
|
+
### Before Migration
|
|
263
|
+
|
|
264
|
+
- ❌ Manual lifecycle management (easy to forget cleanup)
|
|
265
|
+
- ❌ Lots of boilerplate for common scenarios
|
|
266
|
+
- ❌ No TypeScript support
|
|
267
|
+
- ❌ Helper functions scattered across codebase
|
|
268
|
+
- ❌ Tight coupling to plugin
|
|
269
|
+
|
|
270
|
+
### After Migration
|
|
271
|
+
|
|
272
|
+
- ✅ Automatic lifecycle management (hooks)
|
|
273
|
+
- ✅ Zero boilerplate (presets)
|
|
274
|
+
- ✅ Full TypeScript definitions
|
|
275
|
+
- ✅ Organized, composable APIs
|
|
276
|
+
- ✅ Works with or without plugin
|
|
277
|
+
|
|
278
|
+
## Common Patterns
|
|
279
|
+
|
|
280
|
+
### Pattern 1: Chrome Testing
|
|
281
|
+
|
|
282
|
+
```javascript
|
|
283
|
+
// OLD
|
|
284
|
+
test('chrome test', async ({ client }) => {
|
|
285
|
+
await client.exec('sh', 'google-chrome "https://example.com" &', 30000);
|
|
286
|
+
await client.focusApplication('Google Chrome');
|
|
287
|
+
await authDashcam(client);
|
|
288
|
+
await startDashcam(client);
|
|
289
|
+
// ... test code
|
|
290
|
+
await stopDashcam(client);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// NEW
|
|
294
|
+
import { chromePreset } from 'testdriverai/presets';
|
|
295
|
+
|
|
296
|
+
test('chrome test', async (context) => {
|
|
297
|
+
const { client } = await chromePreset(context, {
|
|
298
|
+
url: 'https://example.com'
|
|
299
|
+
});
|
|
300
|
+
// ... test code
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Lines of code:** 7 → 2 (71% reduction)
|
|
305
|
+
|
|
306
|
+
### Pattern 2: Manual Dashcam Control
|
|
307
|
+
|
|
308
|
+
```javascript
|
|
309
|
+
// OLD
|
|
310
|
+
test('dashcam test', async ({ client }) => {
|
|
311
|
+
await authDashcam(client);
|
|
312
|
+
await startDashcam(client);
|
|
313
|
+
// ... test code
|
|
314
|
+
const url = await stopDashcam(client);
|
|
315
|
+
console.log(url);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// NEW
|
|
319
|
+
import { Dashcam } from 'testdriverai/core';
|
|
320
|
+
|
|
321
|
+
test('dashcam test', async (context) => {
|
|
322
|
+
const dashcam = new Dashcam(client);
|
|
323
|
+
await dashcam.auth();
|
|
324
|
+
await dashcam.start();
|
|
325
|
+
// ... test code
|
|
326
|
+
const url = await dashcam.stop();
|
|
327
|
+
console.log(url);
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Pattern 3: Custom Application Setup
|
|
332
|
+
|
|
333
|
+
```javascript
|
|
334
|
+
// OLD
|
|
335
|
+
test('custom app', async ({ client }) => {
|
|
336
|
+
await authDashcam(client);
|
|
337
|
+
await startDashcam(client);
|
|
338
|
+
await client.exec('sh', 'myapp --arg1 --arg2 &', 30000);
|
|
339
|
+
await client.focusApplication('MyApp');
|
|
340
|
+
// ... test code
|
|
341
|
+
await stopDashcam(client);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// NEW - Create custom preset
|
|
345
|
+
import { createPreset } from 'testdriverai/presets';
|
|
346
|
+
|
|
347
|
+
const myAppPreset = createPreset({
|
|
348
|
+
name: 'My App',
|
|
349
|
+
defaults: { args: [] },
|
|
350
|
+
async setup(context, client, dashcam, options) {
|
|
351
|
+
const { args = [] } = options;
|
|
352
|
+
const argsStr = args.join(' ');
|
|
353
|
+
await client.exec('sh', `myapp ${argsStr} &`, 30000);
|
|
354
|
+
await client.focusApplication('MyApp');
|
|
355
|
+
return {}; // client is returned automatically
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
test('custom app', async (context) => {
|
|
360
|
+
const { client } = await myAppPreset(context, {
|
|
361
|
+
args: ['--arg1', '--arg2']
|
|
362
|
+
});
|
|
363
|
+
// ... test code
|
|
364
|
+
// Auto-cleanup
|
|
365
|
+
});
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Reusable** - Use `myAppPreset` in all your tests!
|
|
369
|
+
|
|
370
|
+
## TypeScript Support
|
|
371
|
+
|
|
372
|
+
v7 includes full TypeScript definitions:
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { test } from 'vitest';
|
|
376
|
+
import { chromePreset, ChromePresetOptions } from 'testdriverai/presets';
|
|
377
|
+
import { useTestDriver, UseDashcamOptions } from 'testdriverai/vitest/hooks';
|
|
378
|
+
import { Dashcam, DashcamOptions } from 'testdriverai/core';
|
|
379
|
+
|
|
380
|
+
// Full autocomplete and type checking!
|
|
381
|
+
test('typed test', async (context) => {
|
|
382
|
+
const { client } = await chromePreset(context, {
|
|
383
|
+
url: 'https://example.com',
|
|
384
|
+
maximized: true,
|
|
385
|
+
os: 'linux' // Type-safe: only 'linux' | 'mac' | 'windows'
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
await client.find('button').click();
|
|
389
|
+
});
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Breaking Changes
|
|
393
|
+
|
|
394
|
+
### None! 🎉
|
|
395
|
+
|
|
396
|
+
v7 is **100% backward compatible**. All existing code continues to work.
|
|
397
|
+
|
|
398
|
+
The old lifecycle helpers (`authDashcam`, `startDashcam`, `stopDashcam`) are marked as deprecated but fully functional.
|
|
399
|
+
|
|
400
|
+
## Deprecation Timeline
|
|
401
|
+
|
|
402
|
+
- **v7.0** - New APIs introduced, old helpers work (with deprecation warnings)
|
|
403
|
+
- **v7.x** - Old helpers continue to work
|
|
404
|
+
- **v8.0** - Old helpers removed (TBD, at least 6 months notice)
|
|
405
|
+
|
|
406
|
+
## Getting Help
|
|
407
|
+
|
|
408
|
+
- 📖 **Hooks Documentation**: See `/docs/HOOKS.md`
|
|
409
|
+
- 📖 **Presets Documentation**: See `/docs/PRESETS.md`
|
|
410
|
+
- 💬 **Examples**: See `/testdriver/acceptance-sdk/*-example.test.mjs`
|
|
411
|
+
- 🐛 **Issues**: GitHub Issues
|
|
412
|
+
|
|
413
|
+
## Summary
|
|
414
|
+
|
|
415
|
+
**Choose your level:**
|
|
416
|
+
|
|
417
|
+
| Level | Best For | Example |
|
|
418
|
+
|-------|----------|---------|
|
|
419
|
+
| **Presets** | Common apps (Chrome, VS Code) | `chromePreset(context, { url })` |
|
|
420
|
+
| **Hooks** | Custom lifecycle, power users | `useTestDriver(context, options)` |
|
|
421
|
+
| **Core** | Advanced control, debugging | `new Dashcam(client)` |
|
|
422
|
+
|
|
423
|
+
**Recommendation:** Start with presets for common scenarios, use hooks for custom needs, drop to core classes only when necessary.
|
|
424
|
+
|
|
425
|
+
Migration is **optional** - your existing code continues to work!
|
package/docs/PRESETS.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# TestDriver Presets
|
|
2
|
+
|
|
3
|
+
Presets provide pre-configured setups for common applications, reducing boilerplate and making your tests easier to write.
|
|
4
|
+
|
|
5
|
+
## Available Presets
|
|
6
|
+
|
|
7
|
+
### chromePreset
|
|
8
|
+
|
|
9
|
+
Automatically sets up Chrome browser with TestDriver and Dashcam.
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
import { test } from 'vitest';
|
|
13
|
+
import { chromePreset } from 'testdriverai/presets';
|
|
14
|
+
|
|
15
|
+
test('my test', async (context) => {
|
|
16
|
+
const { client } = await chromePreset(context, {
|
|
17
|
+
url: 'https://myapp.com/login'
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await client.find('email input').type('user@example.com');
|
|
21
|
+
await client.find('Login button').click();
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Options:**
|
|
26
|
+
- `url` - URL to navigate to (default: 'http://testdriver-sandbox.vercel.app/')
|
|
27
|
+
- `os` - Target OS: 'linux', 'mac', 'windows' (default: 'linux')
|
|
28
|
+
- `dashcam` - Enable Dashcam recording (default: true)
|
|
29
|
+
- `maximized` - Start maximized (default: true)
|
|
30
|
+
- `guest` - Use guest mode (default: true)
|
|
31
|
+
|
|
32
|
+
**Returns:**
|
|
33
|
+
- `client` - TestDriver instance
|
|
34
|
+
- `dashcam` - Dashcam instance (if enabled)
|
|
35
|
+
|
|
36
|
+
### vscodePreset
|
|
37
|
+
|
|
38
|
+
Automatically sets up VS Code with TestDriver and Dashcam.
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
import { vscodePreset } from 'testdriverai/presets';
|
|
42
|
+
|
|
43
|
+
test('extension test', async (context) => {
|
|
44
|
+
const { vscode } = await vscodePreset(context, {
|
|
45
|
+
workspace: '/tmp/test-project',
|
|
46
|
+
extensions: ['ms-python.python']
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await vscode.find('File menu').click();
|
|
50
|
+
await vscode.find('New File').click();
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Options:**
|
|
55
|
+
- `workspace` - Workspace/folder to open
|
|
56
|
+
- `os` - Target OS (default: 'linux')
|
|
57
|
+
- `dashcam` - Enable Dashcam recording (default: true)
|
|
58
|
+
- `extensions` - Array of extension IDs to install
|
|
59
|
+
|
|
60
|
+
**Returns:**
|
|
61
|
+
- `client` - TestDriver instance
|
|
62
|
+
- `vscode` - Alias for client
|
|
63
|
+
- `dashcam` - Dashcam instance (if enabled)
|
|
64
|
+
|
|
65
|
+
### electronPreset
|
|
66
|
+
|
|
67
|
+
Automatically sets up an Electron application.
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
import { electronPreset } from 'testdriverai/presets';
|
|
71
|
+
|
|
72
|
+
test('electron app test', async (context) => {
|
|
73
|
+
const { app } = await electronPreset(context, {
|
|
74
|
+
appPath: '/path/to/electron/app',
|
|
75
|
+
args: ['--enable-logging']
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await app.find('main window').click();
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Options:**
|
|
83
|
+
- `appPath` - Path to Electron app (required)
|
|
84
|
+
- `os` - Target OS (default: 'linux')
|
|
85
|
+
- `dashcam` - Enable Dashcam recording (default: true)
|
|
86
|
+
- `args` - Additional electron arguments
|
|
87
|
+
|
|
88
|
+
**Returns:**
|
|
89
|
+
- `client` - TestDriver instance
|
|
90
|
+
- `app` - Alias for client
|
|
91
|
+
- `dashcam` - Dashcam instance (if enabled)
|
|
92
|
+
|
|
93
|
+
### webAppPreset
|
|
94
|
+
|
|
95
|
+
Generic web application preset (currently uses Chrome).
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
import { webAppPreset } from 'testdriverai/presets';
|
|
99
|
+
|
|
100
|
+
test('web app test', async (context) => {
|
|
101
|
+
const { client } = await webAppPreset(context, {
|
|
102
|
+
url: 'https://example.com',
|
|
103
|
+
browser: 'chrome' // Only Chrome supported currently
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
await client.find('login form').click();
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Creating Custom Presets
|
|
111
|
+
|
|
112
|
+
Use `createPreset` to build your own presets:
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
import { createPreset } from 'testdriverai/presets';
|
|
116
|
+
|
|
117
|
+
const firefoxPreset = createPreset({
|
|
118
|
+
name: 'Firefox Browser',
|
|
119
|
+
defaults: { os: 'linux', dashcam: true },
|
|
120
|
+
async setup(context, client, dashcam, options) {
|
|
121
|
+
const { url } = options;
|
|
122
|
+
|
|
123
|
+
// Launch Firefox
|
|
124
|
+
await client.exec('sh', `firefox "${url}" >/dev/null 2>&1 &`, 30000);
|
|
125
|
+
await client.focusApplication('Firefox');
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
// client is already included automatically
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Use your custom preset
|
|
134
|
+
test('my test', async (context) => {
|
|
135
|
+
const { client } = await firefoxPreset(context, {
|
|
136
|
+
url: 'https://example.com',
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
await client.find('page content').click();
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### createPreset API
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
createPreset({
|
|
147
|
+
name: string, // Preset name (for errors)
|
|
148
|
+
defaults: object, // Default options
|
|
149
|
+
setup: async function // Setup function
|
|
150
|
+
})
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The `setup` function receives:
|
|
154
|
+
- `context` - Vitest test context
|
|
155
|
+
- `client` - TestDriver instance (already connected)
|
|
156
|
+
- `dashcam` - Dashcam instance (if enabled)
|
|
157
|
+
- `options` - Merged defaults + user options
|
|
158
|
+
|
|
159
|
+
The `setup` function should return an object with any custom properties. The returned object will automatically include `client` and `dashcam`.
|
|
160
|
+
|
|
161
|
+
## How Presets Work
|
|
162
|
+
|
|
163
|
+
Presets automatically:
|
|
164
|
+
|
|
165
|
+
1. **Create TestDriver client** - Uses `useTestDriver` hook
|
|
166
|
+
2. **Connect to sandbox** - Authenticates and connects
|
|
167
|
+
3. **Set up Dashcam** - If enabled (default: true)
|
|
168
|
+
4. **Configure application** - Launch and focus the app
|
|
169
|
+
5. **Handle cleanup** - Automatic disconnect and dashcam stop
|
|
170
|
+
|
|
171
|
+
All lifecycle is managed automatically via Vitest hooks.
|
|
172
|
+
|
|
173
|
+
## Progressive Disclosure
|
|
174
|
+
|
|
175
|
+
Presets fit into the progressive disclosure pattern:
|
|
176
|
+
|
|
177
|
+
### Beginner (Presets)
|
|
178
|
+
```javascript
|
|
179
|
+
const { client } = await chromePreset(context, { url: 'https://example.com' });
|
|
180
|
+
```
|
|
181
|
+
Everything automatic - just pass URL and start testing.
|
|
182
|
+
|
|
183
|
+
### Intermediate (Hooks)
|
|
184
|
+
```javascript
|
|
185
|
+
const client = useTestDriver(context, { os: 'linux' });
|
|
186
|
+
const dashcam = useDashcam(context, client, { autoStart: true });
|
|
187
|
+
// Custom setup code
|
|
188
|
+
```
|
|
189
|
+
More control over lifecycle, still automatic cleanup.
|
|
190
|
+
|
|
191
|
+
### Advanced (Direct)
|
|
192
|
+
```javascript
|
|
193
|
+
const client = new TestDriver(apiKey, { os: 'linux' });
|
|
194
|
+
await client.auth();
|
|
195
|
+
await client.connect();
|
|
196
|
+
// Full manual control
|
|
197
|
+
```
|
|
198
|
+
Complete control, manual everything.
|
|
199
|
+
|
|
200
|
+
## Best Practices
|
|
201
|
+
|
|
202
|
+
1. **Use presets for common scenarios** - Chrome, VS Code, Electron
|
|
203
|
+
2. **Create custom presets for your apps** - Encapsulate setup logic
|
|
204
|
+
3. **Enable dashcam by default** - Great for debugging failures
|
|
205
|
+
4. **Keep presets focused** - One app/scenario per preset
|
|
206
|
+
5. **Use descriptive variable names** - `client`, `vscode`, `app` based on what you're testing
|
|
207
|
+
|
|
208
|
+
## Examples
|
|
209
|
+
|
|
210
|
+
See `testdriver/acceptance-sdk/presets-example.test.mjs` for working examples.
|