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,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "rightClick"
|
|
3
|
+
description: "Perform a right-click action to open context menus"
|
|
4
|
+
icon: "bars"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The `rightClick()` method performs a right-click action on an element, typically used to open context menus. You can either call it on an [`Element`](/v7/core-concepts/elements) instance or use it directly with a selector.
|
|
10
|
+
|
|
11
|
+
## Syntax
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
// Right-click on an element
|
|
15
|
+
await element.rightClick();
|
|
16
|
+
|
|
17
|
+
// Right-click using a selector
|
|
18
|
+
await ai.rightClick('selector');
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Parameters
|
|
22
|
+
|
|
23
|
+
When called on an `Element`, no parameters are required.
|
|
24
|
+
|
|
25
|
+
When called directly on the AI client:
|
|
26
|
+
|
|
27
|
+
| Parameter | Type | Description |
|
|
28
|
+
|-----------|------|-------------|
|
|
29
|
+
| `selector` | `string` | The selector describing the element to right-click |
|
|
30
|
+
|
|
31
|
+
## Returns
|
|
32
|
+
|
|
33
|
+
Returns a `Promise<void>` that resolves when the right-click action completes.
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
### Right-Click to Open Context Menu
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
const fileItem = await ai.find('README.md file');
|
|
41
|
+
await fileItem.rightClick();
|
|
42
|
+
|
|
43
|
+
// Select menu option
|
|
44
|
+
await ai.click('Delete from context menu');
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Direct Right-Click with Selector
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
await ai.rightClick('image in the gallery');
|
|
51
|
+
await ai.click('Save image as');
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### VS Code Context Menu
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import { test } from 'vitest';
|
|
58
|
+
import { vscode } from '@testdriver/sdk';
|
|
59
|
+
|
|
60
|
+
test('renames a file via context menu', async () => {
|
|
61
|
+
const { ai } = await vscode();
|
|
62
|
+
|
|
63
|
+
// Right-click on a file
|
|
64
|
+
await ai.rightClick('test.js in the file explorer');
|
|
65
|
+
|
|
66
|
+
// Click rename option
|
|
67
|
+
await ai.click('Rename');
|
|
68
|
+
|
|
69
|
+
// Type new name
|
|
70
|
+
await ai.type('test.spec.js');
|
|
71
|
+
await ai.pressKeys('Enter');
|
|
72
|
+
|
|
73
|
+
// Verify rename
|
|
74
|
+
const renamedFile = await ai.find('test.spec.js in the file explorer');
|
|
75
|
+
expect(renamedFile).toBeTruthy();
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Browser Context Menu
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { test } from 'vitest';
|
|
83
|
+
import { chrome } from '@testdriver/sdk';
|
|
84
|
+
|
|
85
|
+
test('opens link in new tab', async () => {
|
|
86
|
+
const { ai } = await chrome('https://example.com');
|
|
87
|
+
|
|
88
|
+
// Right-click on a link
|
|
89
|
+
await ai.rightClick('Documentation link');
|
|
90
|
+
|
|
91
|
+
// Select "Open in new tab"
|
|
92
|
+
await ai.click('Open link in new tab');
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Custom Context Menu in Web App
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
test('uses custom context menu', async () => {
|
|
100
|
+
const { ai } = await chrome('https://app.example.com');
|
|
101
|
+
|
|
102
|
+
// Right-click on custom element
|
|
103
|
+
await ai.rightClick('project item in the list');
|
|
104
|
+
|
|
105
|
+
// Wait for custom menu to appear
|
|
106
|
+
await ai.find('custom context menu');
|
|
107
|
+
|
|
108
|
+
// Click menu option
|
|
109
|
+
await ai.click('Duplicate project');
|
|
110
|
+
|
|
111
|
+
// Verify duplication
|
|
112
|
+
const duplicatedProject = await ai.find('project item (copy)');
|
|
113
|
+
expect(duplicatedProject).toBeTruthy();
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Related Methods
|
|
118
|
+
|
|
119
|
+
- [`click()`](/v7/api/click) - Single click on an element
|
|
120
|
+
- [`doubleClick()`](/v7/api/doubleClick) - Double-click on an element
|
|
121
|
+
- [`mouseDown()`](/v7/api/mouseDown) - Press mouse button without releasing
|
|
122
|
+
- [`mouseUp()`](/v7/api/mouseUp) - Release mouse button
|
|
123
|
+
- [`hover()`](/v7/api/hover) - Move mouse over element without clicking
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Sandbox Management"
|
|
3
|
+
sidebarTitle: "Sandbox"
|
|
4
|
+
description: "Execute scripts and manage the sandbox environment"
|
|
5
|
+
icon: "server"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
The sandbox is a virtual machine where your tests run. You can execute shell commands, JavaScript, and manage applications within the sandbox environment.
|
|
11
|
+
|
|
12
|
+
## Code Execution
|
|
13
|
+
|
|
14
|
+
### exec()
|
|
15
|
+
|
|
16
|
+
Execute code or shell commands in the sandbox.
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
await testdriver.exec(language, code, timeout, silent)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Parameters:**
|
|
23
|
+
- `language` (string) - Language to execute: `'js'` (JavaScript) or `'pwsh'` (PowerShell)
|
|
24
|
+
- `code` (string) - Code or command to execute
|
|
25
|
+
- `timeout` (number) - Timeout in milliseconds
|
|
26
|
+
- `silent` (boolean, optional) - Suppress output if `true`
|
|
27
|
+
|
|
28
|
+
**Returns:** `Promise<string>` - Command output
|
|
29
|
+
|
|
30
|
+
### JavaScript Execution
|
|
31
|
+
|
|
32
|
+
Execute JavaScript code in the browser context (Windows sandbox only).
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
// Execute JavaScript in the browser
|
|
36
|
+
const result = await testdriver.exec('js', 'document.title', 5000);
|
|
37
|
+
console.log('Page title:', result);
|
|
38
|
+
|
|
39
|
+
// Manipulate the DOM
|
|
40
|
+
await testdriver.exec('js', `
|
|
41
|
+
document.querySelector('#username').value = 'testuser';
|
|
42
|
+
`, 5000);
|
|
43
|
+
|
|
44
|
+
// Return data from the page
|
|
45
|
+
const elementText = await testdriver.exec('js', `
|
|
46
|
+
document.querySelector('.message').textContent
|
|
47
|
+
`, 5000);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### PowerShell Execution
|
|
51
|
+
|
|
52
|
+
Execute PowerShell commands in the Windows sandbox.
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
// Run a simple command
|
|
56
|
+
const output = await testdriver.exec('pwsh', 'Get-Process chrome', 5000);
|
|
57
|
+
console.log('Chrome processes:', output);
|
|
58
|
+
|
|
59
|
+
// Install software
|
|
60
|
+
await testdriver.exec('pwsh', 'npm install -g dashcam@beta', 10000);
|
|
61
|
+
|
|
62
|
+
// Start an application
|
|
63
|
+
await testdriver.exec('pwsh', `
|
|
64
|
+
Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "https://example.com"
|
|
65
|
+
`, 10000);
|
|
66
|
+
|
|
67
|
+
// File operations
|
|
68
|
+
await testdriver.exec('pwsh', 'New-Item -Path "C:\\test.txt" -ItemType File', 5000);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Silent Execution
|
|
72
|
+
|
|
73
|
+
Use the `silent` parameter to suppress output for background operations:
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
// Silent installation
|
|
77
|
+
await testdriver.exec('pwsh', 'npm install -g some-package', 10000, true);
|
|
78
|
+
|
|
79
|
+
// Start background process
|
|
80
|
+
await testdriver.exec('pwsh', 'Start-Process notepad', 5000, true);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Application Management
|
|
84
|
+
|
|
85
|
+
### focusApplication()
|
|
86
|
+
|
|
87
|
+
Bring an application window to the foreground.
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
await testdriver.focusApplication(name)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Parameters:**
|
|
94
|
+
- `name` (string) - Application name (e.g., `'Google Chrome'`, `'Microsoft Edge'`, `'Notepad'`)
|
|
95
|
+
|
|
96
|
+
**Returns:** `Promise<string>` - Result message
|
|
97
|
+
|
|
98
|
+
**Example:**
|
|
99
|
+
```javascript
|
|
100
|
+
// Focus Chrome browser
|
|
101
|
+
await testdriver.focusApplication('Google Chrome');
|
|
102
|
+
|
|
103
|
+
// Focus Edge
|
|
104
|
+
await testdriver.focusApplication('Microsoft Edge');
|
|
105
|
+
|
|
106
|
+
// Focus Notepad
|
|
107
|
+
await testdriver.focusApplication('Notepad');
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
<Tip>
|
|
111
|
+
Call `focusApplication()` before interacting with UI elements to ensure the correct window is active.
|
|
112
|
+
</Tip>
|
|
113
|
+
|
|
114
|
+
## Common Sandbox Operations
|
|
115
|
+
|
|
116
|
+
### Installing Software
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
// Install npm package globally
|
|
120
|
+
await testdriver.exec('pwsh', 'npm install -g package-name', 30000);
|
|
121
|
+
|
|
122
|
+
// Install via Chocolatey (if available)
|
|
123
|
+
await testdriver.exec('pwsh', 'choco install firefox -y', 60000);
|
|
124
|
+
|
|
125
|
+
// Download and install
|
|
126
|
+
await testdriver.exec('pwsh', `
|
|
127
|
+
Invoke-WebRequest -Uri "https://example.com/installer.exe" -OutFile "C:\\installer.exe"
|
|
128
|
+
Start-Process -FilePath "C:\\installer.exe" -ArgumentList "/S" -Wait
|
|
129
|
+
`, 120000);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### File Operations
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
// Create a file
|
|
136
|
+
await testdriver.exec('pwsh', `
|
|
137
|
+
Set-Content -Path "C:\\test.txt" -Value "Hello World"
|
|
138
|
+
`, 5000);
|
|
139
|
+
|
|
140
|
+
// Read a file
|
|
141
|
+
const content = await testdriver.exec('pwsh', 'Get-Content -Path "C:\\test.txt"', 5000);
|
|
142
|
+
|
|
143
|
+
// Copy files
|
|
144
|
+
await testdriver.exec('pwsh', 'Copy-Item -Path "C:\\source.txt" -Destination "C:\\dest.txt"', 5000);
|
|
145
|
+
|
|
146
|
+
// Delete files
|
|
147
|
+
await testdriver.exec('pwsh', 'Remove-Item -Path "C:\\test.txt"', 5000);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Environment Variables
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
// Set environment variable
|
|
154
|
+
await testdriver.exec('pwsh', '$env:MY_VAR = "value"', 5000);
|
|
155
|
+
|
|
156
|
+
// Get environment variable
|
|
157
|
+
const value = await testdriver.exec('pwsh', '$env:MY_VAR', 5000);
|
|
158
|
+
|
|
159
|
+
// Set persistent environment variable
|
|
160
|
+
await testdriver.exec('pwsh', '[Environment]::SetEnvironmentVariable("MY_VAR", "value", "User")', 5000);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Network Operations
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
// Test connectivity
|
|
167
|
+
const pingResult = await testdriver.exec('pwsh', 'Test-NetConnection google.com', 10000);
|
|
168
|
+
|
|
169
|
+
// Download file
|
|
170
|
+
await testdriver.exec('pwsh', `
|
|
171
|
+
Invoke-WebRequest -Uri "https://example.com/file.zip" -OutFile "C:\\Downloads\\file.zip"
|
|
172
|
+
`, 30000);
|
|
173
|
+
|
|
174
|
+
// Check if port is open
|
|
175
|
+
const portCheck = await testdriver.exec('pwsh', 'Test-NetConnection -ComputerName localhost -Port 3000', 5000);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Process Management
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
// List running processes
|
|
182
|
+
const processes = await testdriver.exec('pwsh', 'Get-Process', 5000);
|
|
183
|
+
|
|
184
|
+
// Kill a process
|
|
185
|
+
await testdriver.exec('pwsh', 'Stop-Process -Name "chrome" -Force', 5000);
|
|
186
|
+
|
|
187
|
+
// Start a process and wait for it
|
|
188
|
+
await testdriver.exec('pwsh', 'Start-Process notepad -Wait', 30000);
|
|
189
|
+
|
|
190
|
+
// Start process with arguments
|
|
191
|
+
await testdriver.exec('pwsh', `
|
|
192
|
+
Start-Process "chrome.exe" -ArgumentList "--incognito", "https://example.com"
|
|
193
|
+
`, 5000);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Browser Automation with JavaScript
|
|
197
|
+
|
|
198
|
+
### DOM Manipulation
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
// Click an element
|
|
202
|
+
await testdriver.exec('js', `
|
|
203
|
+
document.querySelector('#submit-button').click();
|
|
204
|
+
`, 5000);
|
|
205
|
+
|
|
206
|
+
// Fill a form
|
|
207
|
+
await testdriver.exec('js', `
|
|
208
|
+
document.querySelector('#username').value = 'user@example.com';
|
|
209
|
+
document.querySelector('#password').value = 'secret';
|
|
210
|
+
document.querySelector('#login-form').submit();
|
|
211
|
+
`, 5000);
|
|
212
|
+
|
|
213
|
+
// Scroll to element
|
|
214
|
+
await testdriver.exec('js', `
|
|
215
|
+
document.querySelector('#footer').scrollIntoView();
|
|
216
|
+
`, 5000);
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Reading Page Data
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
// Get page title
|
|
223
|
+
const title = await testdriver.exec('js', 'document.title', 5000);
|
|
224
|
+
|
|
225
|
+
// Get all links
|
|
226
|
+
const links = await testdriver.exec('js', `
|
|
227
|
+
Array.from(document.querySelectorAll('a')).map(a => a.href).join('\\n')
|
|
228
|
+
`, 5000);
|
|
229
|
+
|
|
230
|
+
// Check if element exists
|
|
231
|
+
const exists = await testdriver.exec('js', `
|
|
232
|
+
document.querySelector('.error-message') !== null
|
|
233
|
+
`, 5000);
|
|
234
|
+
|
|
235
|
+
// Get element text
|
|
236
|
+
const text = await testdriver.exec('js', `
|
|
237
|
+
document.querySelector('.notification').textContent
|
|
238
|
+
`, 5000);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Waiting for Conditions
|
|
242
|
+
|
|
243
|
+
```javascript
|
|
244
|
+
// Wait for element to appear (using polling)
|
|
245
|
+
await testdriver.exec('js', `
|
|
246
|
+
await new Promise((resolve) => {
|
|
247
|
+
const interval = setInterval(() => {
|
|
248
|
+
if (document.querySelector('.loaded')) {
|
|
249
|
+
clearInterval(interval);
|
|
250
|
+
resolve();
|
|
251
|
+
}
|
|
252
|
+
}, 100);
|
|
253
|
+
});
|
|
254
|
+
`, 30000);
|
|
255
|
+
|
|
256
|
+
// Wait for page load
|
|
257
|
+
await testdriver.exec('js', `
|
|
258
|
+
if (document.readyState !== 'complete') {
|
|
259
|
+
await new Promise(resolve => window.addEventListener('load', resolve));
|
|
260
|
+
}
|
|
261
|
+
`, 10000);
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Complete Example
|
|
265
|
+
|
|
266
|
+
```javascript
|
|
267
|
+
import { beforeAll, afterAll, describe, it } from 'vitest';
|
|
268
|
+
import TestDriver from 'testdriverai';
|
|
269
|
+
|
|
270
|
+
describe('Sandbox Operations', () => {
|
|
271
|
+
let testdriver;
|
|
272
|
+
|
|
273
|
+
beforeAll(async () => {
|
|
274
|
+
client = new TestDriver(process.env.TD_API_KEY, {
|
|
275
|
+
os: 'windows',
|
|
276
|
+
resolution: '1366x768'
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await testdriver.auth();
|
|
280
|
+
await testdriver.connect({ newSandbox: true });
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
afterAll(async () => {
|
|
284
|
+
await testdriver.disconnect();
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('should install and use a tool', async () => {
|
|
288
|
+
// Install a tool
|
|
289
|
+
await testdriver.exec('pwsh', 'npm install -g http-server', 30000, true);
|
|
290
|
+
|
|
291
|
+
// Create a simple HTML file
|
|
292
|
+
await testdriver.exec('pwsh', `
|
|
293
|
+
Set-Content -Path "C:\\index.html" -Value "<h1>Hello World</h1>"
|
|
294
|
+
`, 5000);
|
|
295
|
+
|
|
296
|
+
// Start HTTP server (background process)
|
|
297
|
+
await testdriver.exec('pwsh', `
|
|
298
|
+
Start-Process pwsh -ArgumentList "-Command", "http-server C:\\ -p 8080"
|
|
299
|
+
`, 5000, true);
|
|
300
|
+
|
|
301
|
+
// Wait for server to start
|
|
302
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
303
|
+
|
|
304
|
+
// Launch browser to view the page
|
|
305
|
+
await testdriver.exec('pwsh', `
|
|
306
|
+
Start-Process chrome -ArgumentList "http://localhost:8080"
|
|
307
|
+
`, 5000);
|
|
308
|
+
|
|
309
|
+
// Focus the browser
|
|
310
|
+
await testdriver.focusApplication('Google Chrome');
|
|
311
|
+
|
|
312
|
+
// Verify the page loaded
|
|
313
|
+
const pageText = await testdriver.exec('js', 'document.body.textContent', 5000);
|
|
314
|
+
expect(pageText).toContain('Hello World');
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('should manage files and processes', async () => {
|
|
318
|
+
// Create test file
|
|
319
|
+
await testdriver.exec('pwsh', `
|
|
320
|
+
"Test content" | Out-File -FilePath "C:\\test.txt"
|
|
321
|
+
`, 5000);
|
|
322
|
+
|
|
323
|
+
// Open file in notepad
|
|
324
|
+
await testdriver.exec('pwsh', 'Start-Process notepad C:\\test.txt', 5000);
|
|
325
|
+
|
|
326
|
+
// Focus notepad
|
|
327
|
+
await testdriver.focusApplication('Notepad');
|
|
328
|
+
|
|
329
|
+
// Wait a moment
|
|
330
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
331
|
+
|
|
332
|
+
// Close notepad
|
|
333
|
+
await testdriver.exec('pwsh', 'Stop-Process -Name notepad -Force', 5000);
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Best Practices
|
|
339
|
+
|
|
340
|
+
<AccordionGroup>
|
|
341
|
+
<Accordion title="Use appropriate timeouts">
|
|
342
|
+
Set realistic timeouts based on the operation:
|
|
343
|
+
|
|
344
|
+
```javascript
|
|
345
|
+
// Quick operations: 5000ms
|
|
346
|
+
await testdriver.exec('js', 'document.title', 5000);
|
|
347
|
+
|
|
348
|
+
// Installations: 30000-60000ms
|
|
349
|
+
await testdriver.exec('pwsh', 'npm install -g package', 30000);
|
|
350
|
+
|
|
351
|
+
// Downloads or complex operations: 60000-120000ms
|
|
352
|
+
await testdriver.exec('pwsh', 'Install-Module Something', 120000);
|
|
353
|
+
```
|
|
354
|
+
</Accordion>
|
|
355
|
+
|
|
356
|
+
<Accordion title="Handle errors gracefully">
|
|
357
|
+
Wrap exec calls in try-catch for better error handling:
|
|
358
|
+
|
|
359
|
+
```javascript
|
|
360
|
+
try {
|
|
361
|
+
await testdriver.exec('pwsh', 'Some-Command', 5000);
|
|
362
|
+
} catch (error) {
|
|
363
|
+
console.error('Command failed:', error.message);
|
|
364
|
+
// Fall back or retry
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
</Accordion>
|
|
368
|
+
|
|
369
|
+
<Accordion title="Use silent mode for background operations">
|
|
370
|
+
Suppress output for installation and background tasks:
|
|
371
|
+
|
|
372
|
+
```javascript
|
|
373
|
+
// Silent install
|
|
374
|
+
await testdriver.exec('pwsh', 'npm install -g tool', 30000, true);
|
|
375
|
+
|
|
376
|
+
// Background process
|
|
377
|
+
await testdriver.exec('pwsh', 'Start-Process app', 5000, true);
|
|
378
|
+
```
|
|
379
|
+
</Accordion>
|
|
380
|
+
|
|
381
|
+
<Accordion title="Focus applications before interaction">
|
|
382
|
+
Always focus the target application before UI interactions:
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
await testdriver.focusApplication('Google Chrome');
|
|
386
|
+
const button = await testdriver.find('submit button');
|
|
387
|
+
await button.click();
|
|
388
|
+
```
|
|
389
|
+
</Accordion>
|
|
390
|
+
|
|
391
|
+
<Accordion title="Escape strings properly in PowerShell">
|
|
392
|
+
Use proper escaping for special characters:
|
|
393
|
+
|
|
394
|
+
```javascript
|
|
395
|
+
// Use backticks for newlines in PowerShell strings
|
|
396
|
+
await testdriver.exec('pwsh', `
|
|
397
|
+
Write-Host "Line 1\`nLine 2"
|
|
398
|
+
`, 5000);
|
|
399
|
+
|
|
400
|
+
// Use single quotes to avoid variable expansion
|
|
401
|
+
await testdriver.exec('pwsh', "Write-Host 'Text with $special chars'", 5000);
|
|
402
|
+
```
|
|
403
|
+
</Accordion>
|
|
404
|
+
</AccordionGroup>
|