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,287 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "click()"
|
|
3
|
+
sidebarTitle: "click"
|
|
4
|
+
description: "Click at specific coordinates or on elements"
|
|
5
|
+
icon: "mouse-pointer"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Element Click
|
|
9
|
+
|
|
10
|
+
When called on an Element object, clicks on the located element.
|
|
11
|
+
|
|
12
|
+
### Syntax
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
await element.click(action)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Parameters
|
|
19
|
+
|
|
20
|
+
<ParamField path="action" type="string" default="click">
|
|
21
|
+
Type of click action: `'click'`, `'double-click'`, `'right-click'`, `'hover'`, `'mouseDown'`, `'mouseUp'`
|
|
22
|
+
</ParamField>
|
|
23
|
+
|
|
24
|
+
### Returns
|
|
25
|
+
|
|
26
|
+
`Promise<void>`
|
|
27
|
+
|
|
28
|
+
### Examples
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
// Regular click
|
|
32
|
+
const button = await testdriver.find('submit button');
|
|
33
|
+
await button.click();
|
|
34
|
+
|
|
35
|
+
// Double-click
|
|
36
|
+
const file = await testdriver.find('README.txt file');
|
|
37
|
+
await file.click('double-click');
|
|
38
|
+
|
|
39
|
+
// Right-click
|
|
40
|
+
const item = await testdriver.find('menu item');
|
|
41
|
+
await item.click('right-click');
|
|
42
|
+
|
|
43
|
+
// Hover (same as element.hover())
|
|
44
|
+
const tooltip = await testdriver.find('info icon');
|
|
45
|
+
await button.click('hover');
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Coordinate Click
|
|
49
|
+
|
|
50
|
+
Click at specific screen coordinates.
|
|
51
|
+
|
|
52
|
+
### Syntax
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
await testdriver.click(x, y, action)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Parameters
|
|
59
|
+
|
|
60
|
+
<ParamField path="x" type="number" required>
|
|
61
|
+
X coordinate
|
|
62
|
+
</ParamField>
|
|
63
|
+
|
|
64
|
+
<ParamField path="y" type="number" required>
|
|
65
|
+
Y coordinate
|
|
66
|
+
</ParamField>
|
|
67
|
+
|
|
68
|
+
<ParamField path="action" type="string" default="click">
|
|
69
|
+
Type of click: `'click'`, `'double-click'`, `'right-click'`, `'mouseDown'`, `'mouseUp'`
|
|
70
|
+
</ParamField>
|
|
71
|
+
|
|
72
|
+
### Returns
|
|
73
|
+
|
|
74
|
+
`Promise<void>`
|
|
75
|
+
|
|
76
|
+
### Examples
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
// Click at coordinates
|
|
80
|
+
await testdriver.click(500, 300);
|
|
81
|
+
|
|
82
|
+
// Double-click at coordinates
|
|
83
|
+
await testdriver.click(500, 300, 'double-click');
|
|
84
|
+
|
|
85
|
+
// Right-click at coordinates
|
|
86
|
+
await testdriver.click(500, 300, 'right-click');
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Click Actions
|
|
90
|
+
|
|
91
|
+
### Regular Click
|
|
92
|
+
|
|
93
|
+
Single left-click action.
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
const button = await testdriver.find('Login button');
|
|
97
|
+
await button.click();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Double Click
|
|
101
|
+
|
|
102
|
+
Double-click action, commonly used to open files or select text.
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
const file = await testdriver.find('document.pdf');
|
|
106
|
+
await file.click('double-click');
|
|
107
|
+
|
|
108
|
+
// Or use the dedicated method
|
|
109
|
+
await file.doubleClick();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Right Click
|
|
113
|
+
|
|
114
|
+
Right-click to open context menus.
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
const folder = await testdriver.find('Documents folder');
|
|
118
|
+
await folder.click('right-click');
|
|
119
|
+
|
|
120
|
+
// Or use the dedicated method
|
|
121
|
+
await folder.rightClick();
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Mouse Down / Mouse Up
|
|
125
|
+
|
|
126
|
+
For drag operations or custom click behavior.
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
const draggable = await testdriver.find('draggable item');
|
|
130
|
+
await draggable.click('mouseDown');
|
|
131
|
+
|
|
132
|
+
// Move to target
|
|
133
|
+
const dropZone = await testdriver.find('drop zone');
|
|
134
|
+
await dropZone.hover();
|
|
135
|
+
await dropZone.click('mouseUp');
|
|
136
|
+
|
|
137
|
+
// Or use dedicated methods
|
|
138
|
+
await draggable.mouseDown();
|
|
139
|
+
await dropZone.mouseUp();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Best Practices
|
|
143
|
+
|
|
144
|
+
<Check>
|
|
145
|
+
**Prefer element clicks over coordinate clicks**
|
|
146
|
+
|
|
147
|
+
Element-based clicking is more reliable and resolution-independent:
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
// ✅ Preferred
|
|
151
|
+
const button = await testdriver.find('submit button');
|
|
152
|
+
await button.click();
|
|
153
|
+
|
|
154
|
+
// ❌ Avoid (fragile)
|
|
155
|
+
await testdriver.click(500, 300);
|
|
156
|
+
```
|
|
157
|
+
</Check>
|
|
158
|
+
|
|
159
|
+
<Check>
|
|
160
|
+
**Verify element was found**
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
const element = await testdriver.find('button');
|
|
164
|
+
if (!element.found()) {
|
|
165
|
+
throw new Error('Element not found');
|
|
166
|
+
}
|
|
167
|
+
await element.click();
|
|
168
|
+
```
|
|
169
|
+
</Check>
|
|
170
|
+
|
|
171
|
+
<Warning>
|
|
172
|
+
**Element must be found before clicking**
|
|
173
|
+
|
|
174
|
+
The `find()` method automatically locates elements, but clicking an element that wasn't found will throw an error:
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
const element = await testdriver.find('button');
|
|
178
|
+
// This will throw if element wasn't found
|
|
179
|
+
await element.click();
|
|
180
|
+
```
|
|
181
|
+
</Warning>
|
|
182
|
+
|
|
183
|
+
## Use Cases
|
|
184
|
+
|
|
185
|
+
<AccordionGroup>
|
|
186
|
+
<Accordion title="Button Clicks">
|
|
187
|
+
```javascript
|
|
188
|
+
const submitBtn = await testdriver.find('submit button');
|
|
189
|
+
await submitBtn.click();
|
|
190
|
+
|
|
191
|
+
const cancelBtn = await testdriver.find('cancel button');
|
|
192
|
+
await cancelBtn.click();
|
|
193
|
+
```
|
|
194
|
+
</Accordion>
|
|
195
|
+
|
|
196
|
+
<Accordion title="Opening Files">
|
|
197
|
+
```javascript
|
|
198
|
+
const file = await testdriver.find('report.pdf file icon');
|
|
199
|
+
await file.doubleClick();
|
|
200
|
+
```
|
|
201
|
+
</Accordion>
|
|
202
|
+
|
|
203
|
+
<Accordion title="Context Menus">
|
|
204
|
+
```javascript
|
|
205
|
+
const item = await testdriver.find('file item');
|
|
206
|
+
await item.rightClick();
|
|
207
|
+
|
|
208
|
+
// Select menu option
|
|
209
|
+
const deleteOption = await testdriver.find('Delete option');
|
|
210
|
+
await deleteOption.click();
|
|
211
|
+
```
|
|
212
|
+
</Accordion>
|
|
213
|
+
|
|
214
|
+
<Accordion title="Drag and Drop">
|
|
215
|
+
```javascript
|
|
216
|
+
const source = await testdriver.find('source item');
|
|
217
|
+
await source.mouseDown();
|
|
218
|
+
|
|
219
|
+
const target = await testdriver.find('target zone');
|
|
220
|
+
await target.hover();
|
|
221
|
+
await target.mouseUp();
|
|
222
|
+
```
|
|
223
|
+
</Accordion>
|
|
224
|
+
</AccordionGroup>
|
|
225
|
+
|
|
226
|
+
## Complete Example
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
import { beforeAll, afterAll, describe, it } from 'vitest';
|
|
230
|
+
import TestDriver from 'testdriverai';
|
|
231
|
+
|
|
232
|
+
describe('Click Interactions', () => {
|
|
233
|
+
let testdriver;
|
|
234
|
+
|
|
235
|
+
beforeAll(async () => {
|
|
236
|
+
client = new TestDriver(process.env.TD_API_KEY);
|
|
237
|
+
await testdriver.auth();
|
|
238
|
+
await testdriver.connect({ newSandbox: true });
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
afterAll(async () => {
|
|
242
|
+
await testdriver.disconnect();
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('should perform various click actions', async () => {
|
|
246
|
+
await testdriver.focusApplication('Google Chrome');
|
|
247
|
+
|
|
248
|
+
// Regular click
|
|
249
|
+
const loginBtn = await testdriver.find('login button');
|
|
250
|
+
await loginBtn.click();
|
|
251
|
+
|
|
252
|
+
// Right-click for context menu
|
|
253
|
+
const profileIcon = await testdriver.find('profile icon');
|
|
254
|
+
await profileIcon.rightClick();
|
|
255
|
+
|
|
256
|
+
const settingsOption = await testdriver.find('Settings menu option');
|
|
257
|
+
await settingsOption.click();
|
|
258
|
+
|
|
259
|
+
// Double-click to edit
|
|
260
|
+
const nameField = await testdriver.find('name display field');
|
|
261
|
+
await nameField.doubleClick();
|
|
262
|
+
|
|
263
|
+
// Verify state
|
|
264
|
+
await testdriver.assert('name field is now editable');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should perform drag and drop', async () => {
|
|
268
|
+
const item = await testdriver.find('draggable item');
|
|
269
|
+
await item.mouseDown();
|
|
270
|
+
|
|
271
|
+
// Drag to new location
|
|
272
|
+
const dropTarget = await testdriver.find('drop area');
|
|
273
|
+
await dropTarget.hover();
|
|
274
|
+
await dropTarget.mouseUp();
|
|
275
|
+
|
|
276
|
+
// Verify
|
|
277
|
+
await testdriver.assert('item is in the drop area');
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Related Methods
|
|
283
|
+
|
|
284
|
+
- [`find()`](/v7/api/find) - Locate elements to click
|
|
285
|
+
- [`hover()`](/v7/api/hover) - Hover without clicking
|
|
286
|
+
- [`doubleClick()`](/v7/api/doubleClick) - Dedicated double-click method
|
|
287
|
+
- [`rightClick()`](/v7/api/rightClick) - Dedicated right-click method
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "TestDriver Client"
|
|
3
|
+
sidebarTitle: "Client"
|
|
4
|
+
description: "Initialize and configure the TestDriver SDK client"
|
|
5
|
+
icon: "plug"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
The `TestDriver` client is the main entry point for the SDK. It handles authentication, sandbox connection, and provides access to all testing methods.
|
|
11
|
+
|
|
12
|
+
## Constructor
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
const testdriver = new TestDriver(apiKey, options)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Parameters
|
|
19
|
+
|
|
20
|
+
<ParamField path="apiKey" type="string" required>
|
|
21
|
+
Your TestDriver API key from the [dashboard](https://app.testdriver.ai/team)
|
|
22
|
+
</ParamField>
|
|
23
|
+
|
|
24
|
+
<ParamField path="options" type="object">
|
|
25
|
+
Configuration options for the client
|
|
26
|
+
|
|
27
|
+
<Expandable title="properties">
|
|
28
|
+
<ParamField path="os" type="string" default="windows">
|
|
29
|
+
Operating system for the sandbox: `'windows'` or `'linux'`
|
|
30
|
+
</ParamField>
|
|
31
|
+
|
|
32
|
+
<ParamField path="resolution" type="string" default="1366x768">
|
|
33
|
+
Screen resolution for the sandbox (e.g., `'1920x1080'`, `'1366x768'`)
|
|
34
|
+
</ParamField>
|
|
35
|
+
|
|
36
|
+
<ParamField path="apiRoot" type="string" default="https://testdriver-api.onrender.com">
|
|
37
|
+
API endpoint URL (typically only changed for self-hosted deployments)
|
|
38
|
+
</ParamField>
|
|
39
|
+
|
|
40
|
+
<ParamField path="analytics" type="boolean" default="true">
|
|
41
|
+
Enable or disable usage analytics
|
|
42
|
+
</ParamField>
|
|
43
|
+
|
|
44
|
+
<ParamField path="logging" type="boolean" default="true">
|
|
45
|
+
Enable or disable console logging
|
|
46
|
+
</ParamField>
|
|
47
|
+
|
|
48
|
+
<ParamField path="environment" type="object">
|
|
49
|
+
Additional environment variables to pass to the sandbox
|
|
50
|
+
</ParamField>
|
|
51
|
+
</Expandable>
|
|
52
|
+
</ParamField>
|
|
53
|
+
|
|
54
|
+
### Example
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import TestDriver from 'testdriverai';
|
|
58
|
+
|
|
59
|
+
const testdriver = new TestDriver(process.env.TD_API_KEY, {
|
|
60
|
+
os: 'windows',
|
|
61
|
+
resolution: '1920x1080',
|
|
62
|
+
logging: true,
|
|
63
|
+
analytics: true
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Authentication
|
|
68
|
+
|
|
69
|
+
### auth()
|
|
70
|
+
|
|
71
|
+
Authenticate with the TestDriver API.
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
await testdriver.auth()
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Returns:** `Promise<string>` - Authentication token
|
|
78
|
+
|
|
79
|
+
**Example:**
|
|
80
|
+
```javascript
|
|
81
|
+
await testdriver.auth();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
<Note>
|
|
85
|
+
You must call `auth()` before `connect()`. Most examples call both sequentially.
|
|
86
|
+
</Note>
|
|
87
|
+
|
|
88
|
+
## Connection Management
|
|
89
|
+
|
|
90
|
+
### connect()
|
|
91
|
+
|
|
92
|
+
Connect to a sandbox environment. This creates or reconnects to a virtual machine where your tests will run.
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
await testdriver.connect(options)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Parameters
|
|
99
|
+
|
|
100
|
+
<ParamField path="options" type="object">
|
|
101
|
+
Connection options
|
|
102
|
+
|
|
103
|
+
<Expandable title="properties">
|
|
104
|
+
<ParamField path="newSandbox" type="boolean" default="false">
|
|
105
|
+
Force creation of a new sandbox instead of reusing an existing one
|
|
106
|
+
</ParamField>
|
|
107
|
+
|
|
108
|
+
<ParamField path="sandboxId" type="string">
|
|
109
|
+
Existing sandbox ID to reconnect to
|
|
110
|
+
</ParamField>
|
|
111
|
+
|
|
112
|
+
<ParamField path="ip" type="string">
|
|
113
|
+
Direct IP address to connect to (for self-hosted sandboxes)
|
|
114
|
+
</ParamField>
|
|
115
|
+
|
|
116
|
+
<ParamField path="sandboxAmi" type="string">
|
|
117
|
+
AMI to use for the sandbox (AWS deployments)
|
|
118
|
+
</ParamField>
|
|
119
|
+
|
|
120
|
+
<ParamField path="sandboxInstance" type="string">
|
|
121
|
+
Instance type for the sandbox (AWS deployments)
|
|
122
|
+
</ParamField>
|
|
123
|
+
|
|
124
|
+
<ParamField path="headless" type="boolean" default="false">
|
|
125
|
+
Run in headless mode without opening the debugger
|
|
126
|
+
</ParamField>
|
|
127
|
+
</Expandable>
|
|
128
|
+
</ParamField>
|
|
129
|
+
|
|
130
|
+
**Returns:** `Promise<Object>` - Sandbox instance details including `instanceId`, `ip`, `vncPort`, etc.
|
|
131
|
+
|
|
132
|
+
#### Examples
|
|
133
|
+
|
|
134
|
+
**Basic connection:**
|
|
135
|
+
```javascript
|
|
136
|
+
await testdriver.connect({ newSandbox: true });
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Reconnect to existing sandbox:**
|
|
140
|
+
```javascript
|
|
141
|
+
const instance = await testdriver.connect({
|
|
142
|
+
sandboxId: 'existing-sandbox-id-123'
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Self-hosted sandbox:**
|
|
147
|
+
```javascript
|
|
148
|
+
await testdriver.connect({
|
|
149
|
+
ip: '192.168.1.100'
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### disconnect()
|
|
154
|
+
|
|
155
|
+
Disconnect from the sandbox and clean up resources.
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
await testdriver.disconnect()
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Returns:** `Promise<void>`
|
|
162
|
+
|
|
163
|
+
**Example:**
|
|
164
|
+
```javascript
|
|
165
|
+
afterAll(async () => {
|
|
166
|
+
await testdriver.disconnect();
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Instance Information
|
|
171
|
+
|
|
172
|
+
### getInstance()
|
|
173
|
+
|
|
174
|
+
Get the current sandbox instance details.
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
const instance = testdriver.getInstance()
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Returns:** `Object | null` - Sandbox instance information
|
|
181
|
+
|
|
182
|
+
**Example:**
|
|
183
|
+
```javascript
|
|
184
|
+
const instance = testdriver.getInstance();
|
|
185
|
+
console.log('Instance ID:', instance.instanceId);
|
|
186
|
+
console.log('IP Address:', instance.ip);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### getSessionId()
|
|
190
|
+
|
|
191
|
+
Get the current session ID for tracking and debugging.
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const sessionId = testdriver.getSessionId()
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Returns:** `string | null` - Session ID
|
|
198
|
+
|
|
199
|
+
**Example:**
|
|
200
|
+
```javascript
|
|
201
|
+
const sessionId = testdriver.getSessionId();
|
|
202
|
+
console.log('Session:', sessionId);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Logging & Events
|
|
206
|
+
|
|
207
|
+
### setLogging()
|
|
208
|
+
|
|
209
|
+
Enable or disable console logging at runtime.
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
testdriver.setLogging(enabled)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Parameters:**
|
|
216
|
+
- `enabled` (boolean) - Whether to enable logging
|
|
217
|
+
|
|
218
|
+
**Example:**
|
|
219
|
+
```javascript
|
|
220
|
+
// Disable logging for cleanup operations
|
|
221
|
+
testdriver.setLogging(false);
|
|
222
|
+
await testdriver.disconnect();
|
|
223
|
+
testdriver.setLogging(true);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### getEmitter()
|
|
227
|
+
|
|
228
|
+
Get the event emitter for custom event handling.
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
const emitter = testdriver.getEmitter()
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Returns:** `EventEmitter2` - Event emitter instance
|
|
235
|
+
|
|
236
|
+
**Example:**
|
|
237
|
+
```javascript
|
|
238
|
+
const emitter = testdriver.getEmitter();
|
|
239
|
+
|
|
240
|
+
emitter.on('command:start', (data) => {
|
|
241
|
+
console.log('Command started:', data);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
emitter.on('command:success', (data) => {
|
|
245
|
+
console.log('Command succeeded:', data);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
emitter.on('command:error', (error) => {
|
|
249
|
+
console.error('Command failed:', error);
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Complete Example
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
import { beforeAll, afterAll, describe, it } from 'vitest';
|
|
257
|
+
import TestDriver from 'testdriverai';
|
|
258
|
+
|
|
259
|
+
describe('My Test Suite', () => {
|
|
260
|
+
let testdriver;
|
|
261
|
+
|
|
262
|
+
beforeAll(async () => {
|
|
263
|
+
// Initialize client
|
|
264
|
+
client = new TestDriver(process.env.TD_API_KEY, {
|
|
265
|
+
os: 'windows',
|
|
266
|
+
resolution: '1366x768',
|
|
267
|
+
logging: true
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Set up event listeners
|
|
271
|
+
const emitter = testdriver.getEmitter();
|
|
272
|
+
emitter.on('log:info', (msg) => console.log('[INFO]', msg));
|
|
273
|
+
|
|
274
|
+
// Authenticate and connect
|
|
275
|
+
await testdriver.auth();
|
|
276
|
+
const instance = await testdriver.connect({ newSandbox: true });
|
|
277
|
+
|
|
278
|
+
console.log('Connected to sandbox:', instance.instanceId);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
afterAll(async () => {
|
|
282
|
+
await testdriver.disconnect();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('runs a test', async () => {
|
|
286
|
+
// Your test code here
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Best Practices
|
|
292
|
+
|
|
293
|
+
<AccordionGroup>
|
|
294
|
+
<Accordion title="Reuse sandboxes across tests">
|
|
295
|
+
Use `beforeAll`/`afterAll` to create one sandbox per test suite rather than per test. This significantly reduces execution time.
|
|
296
|
+
</Accordion>
|
|
297
|
+
|
|
298
|
+
<Accordion title="Handle connection errors gracefully">
|
|
299
|
+
Wrap `connect()` in a try-catch block to handle network issues or quota limits:
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
try {
|
|
303
|
+
await testdriver.connect({ newSandbox: true });
|
|
304
|
+
} catch (error) {
|
|
305
|
+
console.error('Failed to connect:', error.message);
|
|
306
|
+
throw error;
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
</Accordion>
|
|
310
|
+
|
|
311
|
+
<Accordion title="Always disconnect">
|
|
312
|
+
Use `afterAll` or try-finally blocks to ensure `disconnect()` is called even if tests fail. This prevents orphaned sandboxes.
|
|
313
|
+
</Accordion>
|
|
314
|
+
|
|
315
|
+
<Accordion title="Use environment variables for API keys">
|
|
316
|
+
Never hardcode API keys. Use environment variables:
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
const testdriver = new TestDriver(process.env.TD_API_KEY);
|
|
320
|
+
```
|
|
321
|
+
</Accordion>
|
|
322
|
+
</AccordionGroup>
|