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: "Web Apps"
|
|
3
|
+
sidebarTitle: "Web Apps"
|
|
4
|
+
description: "Automatically launch and test Chrome browser applications"
|
|
5
|
+
icon: "chrome"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
The `chrome()` preset automatically sets up a Chrome browser with TestDriver and Dashcam recording. It's the easiest way to test web applications.
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
import { test } from 'vitest';
|
|
16
|
+
import { chrome } from 'testdriverai/presets';
|
|
17
|
+
|
|
18
|
+
test('login test', async (context) => {
|
|
19
|
+
const { testdriver } = await chrome(context, {
|
|
20
|
+
url: 'https://myapp.com/login'
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
await testdriver.find('email input').type('user@example.com');
|
|
24
|
+
await testdriver.find('password input').type('password123');
|
|
25
|
+
await testdriver.find('Login button').click();
|
|
26
|
+
|
|
27
|
+
await testdriver.assert('Welcome message is visible');
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Signature
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
chrome(context, options): Promise<ChromeResult>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Parameters
|
|
38
|
+
|
|
39
|
+
<ParamField path="context" type="object" required>
|
|
40
|
+
Vitest test context - automatically passed to your test function
|
|
41
|
+
</ParamField>
|
|
42
|
+
|
|
43
|
+
<ParamField path="options" type="object">
|
|
44
|
+
Configuration options for Chrome
|
|
45
|
+
|
|
46
|
+
<Expandable title="properties">
|
|
47
|
+
<ParamField path="url" type="string" default="http://testdriver-sandbox.vercel.app/">
|
|
48
|
+
URL to navigate to when Chrome launches
|
|
49
|
+
</ParamField>
|
|
50
|
+
|
|
51
|
+
<ParamField path="maximized" type="boolean" default={true}>
|
|
52
|
+
Start Chrome in maximized window mode
|
|
53
|
+
</ParamField>
|
|
54
|
+
|
|
55
|
+
<ParamField path="guest" type="boolean" default={true}>
|
|
56
|
+
Use Chrome guest/incognito mode (no profile data)
|
|
57
|
+
</ParamField>
|
|
58
|
+
|
|
59
|
+
<ParamField path="dashcam" type="boolean" default={true}>
|
|
60
|
+
Enable Dashcam test recording
|
|
61
|
+
</ParamField>
|
|
62
|
+
|
|
63
|
+
<ParamField path="os" type="'linux' | 'mac' | 'windows'" default="linux">
|
|
64
|
+
Target operating system for the test
|
|
65
|
+
</ParamField>
|
|
66
|
+
</Expandable>
|
|
67
|
+
</ParamField>
|
|
68
|
+
|
|
69
|
+
### Returns
|
|
70
|
+
|
|
71
|
+
<ResponseField name="testdriver" type="TestDriver" required>
|
|
72
|
+
TestDriver instance ready to use
|
|
73
|
+
</ResponseField>
|
|
74
|
+
|
|
75
|
+
<ResponseField name="dashcam" type="Dashcam">
|
|
76
|
+
Dashcam instance for test recording (if enabled)
|
|
77
|
+
</ResponseField>
|
|
78
|
+
|
|
79
|
+
## Examples
|
|
80
|
+
|
|
81
|
+
### Basic Web App Testing
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
import { test } from 'vitest';
|
|
85
|
+
import { chrome } from 'testdriverai/presets';
|
|
86
|
+
|
|
87
|
+
test('search functionality', async (context) => {
|
|
88
|
+
const { testdriver } = await chrome(context, {
|
|
89
|
+
url: 'https://example.com'
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
await testdriver.find('search input').type('TestDriver');
|
|
93
|
+
await testdriver.find('search button').click();
|
|
94
|
+
await testdriver.assert('search results are displayed');
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### With Dashcam Recording
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
import { test, expect } from 'vitest';
|
|
102
|
+
import { chrome } from 'testdriverai/presets';
|
|
103
|
+
|
|
104
|
+
test('checkout flow', async (context) => {
|
|
105
|
+
const { testdriver, dashcam } = await chrome(context, {
|
|
106
|
+
url: 'https://shop.example.com',
|
|
107
|
+
maximized: true
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Add items to cart
|
|
111
|
+
await testdriver.find('Add to Cart button').click();
|
|
112
|
+
await testdriver.find('View Cart').click();
|
|
113
|
+
|
|
114
|
+
// Proceed to checkout
|
|
115
|
+
await testdriver.find('Checkout button').click();
|
|
116
|
+
|
|
117
|
+
// Fill shipping info
|
|
118
|
+
await testdriver.find('Name input').type('John Doe');
|
|
119
|
+
await testdriver.find('Address input').type('123 Main St');
|
|
120
|
+
|
|
121
|
+
// Submit order
|
|
122
|
+
await testdriver.find('Place Order').click();
|
|
123
|
+
|
|
124
|
+
// Verify confirmation
|
|
125
|
+
const confirmed = await testdriver.assert('Order confirmed');
|
|
126
|
+
expect(confirmed).toBeTruthy();
|
|
127
|
+
|
|
128
|
+
// Dashcam automatically saves replay URL when test completes
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Testing on Different Operating Systems
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
import { test } from 'vitest';
|
|
136
|
+
import { chrome } from 'testdriverai/presets';
|
|
137
|
+
|
|
138
|
+
test('windows chrome test', async (context) => {
|
|
139
|
+
const { testdriver } = await chrome(context, {
|
|
140
|
+
url: 'https://myapp.com',
|
|
141
|
+
os: 'windows'
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
await testdriver.find('Start').click();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('mac chrome test', async (context) => {
|
|
148
|
+
const { testdriver } = await chrome(context, {
|
|
149
|
+
url: 'https://myapp.com',
|
|
150
|
+
os: 'mac'
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
await testdriver.find('Start').click();
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Without Dashcam
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
import { test } from 'vitest';
|
|
161
|
+
import { chrome } from 'testdriverai/presets';
|
|
162
|
+
|
|
163
|
+
test('quick test without recording', async (context) => {
|
|
164
|
+
const { testdriver } = await chrome(context, {
|
|
165
|
+
url: 'https://example.com',
|
|
166
|
+
dashcam: false // Disable Dashcam for faster execution
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
await testdriver.find('button').click();
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Testing Chrome Extensions
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
import { test } from 'vitest';
|
|
177
|
+
import { chrome } from 'testdriverai/presets';
|
|
178
|
+
|
|
179
|
+
test('chrome extension', async (context) => {
|
|
180
|
+
const { testdriver } = await chrome(context, {
|
|
181
|
+
url: 'chrome://extensions',
|
|
182
|
+
guest: false, // Need profile for extensions
|
|
183
|
+
maximized: true
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
await testdriver.find('Developer mode toggle').click();
|
|
187
|
+
await testdriver.find('Load unpacked').click();
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## What It Does
|
|
192
|
+
|
|
193
|
+
When you call `chrome()`, it automatically:
|
|
194
|
+
|
|
195
|
+
1. **Initializes TestDriver** - Creates and connects to sandbox
|
|
196
|
+
2. **Sets up Dashcam** - Authenticates and starts recording (if enabled)
|
|
197
|
+
3. **Launches Chrome** - Opens browser with your specified options
|
|
198
|
+
4. **Navigates to URL** - Loads your application
|
|
199
|
+
5. **Waits for Ready** - Ensures Chrome is focused and page is loaded
|
|
200
|
+
6. **Returns Instances** - Provides ready-to-use testdriver and dashcam
|
|
201
|
+
|
|
202
|
+
At test end:
|
|
203
|
+
- Dashcam automatically stops and saves replay URL
|
|
204
|
+
- TestDriver automatically disconnects
|
|
205
|
+
- All cleanup is handled for you
|
|
206
|
+
|
|
207
|
+
## Common Patterns
|
|
208
|
+
|
|
209
|
+
### Form Filling
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
test('user registration', async (context) => {
|
|
213
|
+
const { testdriver } = await chrome(context, {
|
|
214
|
+
url: 'https://myapp.com/register'
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
await testdriver.find('email field').type('user@example.com');
|
|
218
|
+
await testdriver.find('password field').type('SecurePass123!');
|
|
219
|
+
await testdriver.find('confirm password field').type('SecurePass123!');
|
|
220
|
+
await testdriver.find('terms checkbox').click();
|
|
221
|
+
await testdriver.find('Sign Up button').click();
|
|
222
|
+
|
|
223
|
+
await testdriver.assert('Registration successful message appears');
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Navigation Testing
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
test('multi-page navigation', async (context) => {
|
|
231
|
+
const { testdriver } = await chrome(context, {
|
|
232
|
+
url: 'https://myapp.com'
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Navigate through pages
|
|
236
|
+
await testdriver.find('About link').click();
|
|
237
|
+
await testdriver.assert('About page heading is visible');
|
|
238
|
+
|
|
239
|
+
await testdriver.find('Services link').click();
|
|
240
|
+
await testdriver.assert('Services page content is loaded');
|
|
241
|
+
|
|
242
|
+
await testdriver.find('Contact link').click();
|
|
243
|
+
await testdriver.assert('Contact form is displayed');
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Error Handling
|
|
248
|
+
|
|
249
|
+
```javascript
|
|
250
|
+
test('handles errors gracefully', async (context) => {
|
|
251
|
+
try {
|
|
252
|
+
const { testdriver } = await chrome(context, {
|
|
253
|
+
url: 'https://myapp.com'
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
await testdriver.find('non-existent element').click();
|
|
257
|
+
} catch (error) {
|
|
258
|
+
// Cleanup still happens automatically via Vitest hooks
|
|
259
|
+
console.error('Test failed:', error);
|
|
260
|
+
throw error; // Re-throw to mark test as failed
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Using with provision()
|
|
266
|
+
|
|
267
|
+
The `chrome()` preset can also be called via the unified `provision()` function:
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
import { provision } from 'testdriverai/presets';
|
|
271
|
+
|
|
272
|
+
test('using provision', async (context) => {
|
|
273
|
+
const { testdriver } = await provision('chrome', {
|
|
274
|
+
url: 'https://example.com'
|
|
275
|
+
}, context);
|
|
276
|
+
|
|
277
|
+
// Same functionality as chrome() directly
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## See Also
|
|
282
|
+
|
|
283
|
+
- [Provision API](/v7/progressive-apis/PROVISION) - Overview of all presets
|
|
284
|
+
- [VS Code Preset](/v7/presets/vscode) - Testing VS Code extensions
|
|
285
|
+
- [Electron Preset](/v7/presets/electron) - Testing Electron apps
|
|
286
|
+
- [Vitest Integration](/v7/guides/vitest) - Complete Vitest setup guide
|
|
287
|
+
- [Hooks API](/v7/progressive-apis/HOOKS) - Manual lifecycle control
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Desktop Apps"
|
|
3
|
+
sidebarTitle: "Desktop Apps"
|
|
4
|
+
description: "Automatically launch and test Electron applications"
|
|
5
|
+
icon: "atom"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
The `electron()` preset automatically sets up an Electron application with TestDriver and Dashcam recording. Perfect for testing desktop apps built with Electron.
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
import { test } from 'vitest';
|
|
16
|
+
import { electron } from 'testdriverai/presets';
|
|
17
|
+
|
|
18
|
+
test('electron app test', async (context) => {
|
|
19
|
+
const { app } = await electron(context, {
|
|
20
|
+
appPath: './dist/my-app'
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
await app.find('main window').click();
|
|
24
|
+
await app.find('File menu').click();
|
|
25
|
+
await app.find('New Document').click();
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Signature
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
electron(context, options): Promise<ElectronResult>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Parameters
|
|
36
|
+
|
|
37
|
+
<ParamField path="context" type="object" required>
|
|
38
|
+
Vitest test context - automatically passed to your test function
|
|
39
|
+
</ParamField>
|
|
40
|
+
|
|
41
|
+
<ParamField path="options" type="object">
|
|
42
|
+
Configuration options for Electron
|
|
43
|
+
|
|
44
|
+
<Expandable title="properties">
|
|
45
|
+
<ParamField path="appPath" type="string" required>
|
|
46
|
+
Path to your Electron application executable or main file
|
|
47
|
+
</ParamField>
|
|
48
|
+
|
|
49
|
+
<ParamField path="args" type="string[]" default={[]}>
|
|
50
|
+
Additional command-line arguments to pass to Electron
|
|
51
|
+
</ParamField>
|
|
52
|
+
|
|
53
|
+
<ParamField path="dashcam" type="boolean" default={true}>
|
|
54
|
+
Enable Dashcam test recording
|
|
55
|
+
</ParamField>
|
|
56
|
+
|
|
57
|
+
<ParamField path="os" type="'linux' | 'mac' | 'windows'" default="linux">
|
|
58
|
+
Target operating system for the test
|
|
59
|
+
</ParamField>
|
|
60
|
+
</Expandable>
|
|
61
|
+
</ParamField>
|
|
62
|
+
|
|
63
|
+
### Returns
|
|
64
|
+
|
|
65
|
+
<ResponseField name="testdriver" type="TestDriver" required>
|
|
66
|
+
TestDriver instance ready to use
|
|
67
|
+
</ResponseField>
|
|
68
|
+
|
|
69
|
+
<ResponseField name="app" type="TestDriver" required>
|
|
70
|
+
Alias for testdriver (semantic clarity for Electron apps)
|
|
71
|
+
</ResponseField>
|
|
72
|
+
|
|
73
|
+
<ResponseField name="dashcam" type="Dashcam">
|
|
74
|
+
Dashcam instance for test recording (if enabled)
|
|
75
|
+
</ResponseField>
|
|
76
|
+
|
|
77
|
+
## Examples
|
|
78
|
+
|
|
79
|
+
### Basic Electron App
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { test } from 'vitest';
|
|
83
|
+
import { electron } from 'testdriverai/presets';
|
|
84
|
+
|
|
85
|
+
test('opens main window', async (context) => {
|
|
86
|
+
const { app } = await electron(context, {
|
|
87
|
+
appPath: './dist/my-electron-app'
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
await app.assert('Main window is visible');
|
|
91
|
+
await app.find('Welcome message').click();
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### With Command-Line Arguments
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
import { test } from 'vitest';
|
|
99
|
+
import { electron } from 'testdriverai/presets';
|
|
100
|
+
|
|
101
|
+
test('app with debug mode', async (context) => {
|
|
102
|
+
const { app } = await electron(context, {
|
|
103
|
+
appPath: './dist/app',
|
|
104
|
+
args: [
|
|
105
|
+
'--enable-logging',
|
|
106
|
+
'--debug',
|
|
107
|
+
'--user-data-dir=/tmp/test-data'
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
await app.find('Debug panel').click();
|
|
112
|
+
await app.assert('Debug information is visible');
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Menu Navigation
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
import { test } from 'vitest';
|
|
120
|
+
import { electron } from 'testdriverai/presets';
|
|
121
|
+
|
|
122
|
+
test('file menu operations', async (context) => {
|
|
123
|
+
const { app } = await electron(context, {
|
|
124
|
+
appPath: './dist/editor-app'
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Open File menu
|
|
128
|
+
await app.find('File').click();
|
|
129
|
+
await app.find('New File').click();
|
|
130
|
+
|
|
131
|
+
// Verify new file created
|
|
132
|
+
await app.assert('Untitled document is open');
|
|
133
|
+
|
|
134
|
+
// Save file
|
|
135
|
+
await app.find('File').click();
|
|
136
|
+
await app.find('Save As').click();
|
|
137
|
+
await app.type('test-document.txt');
|
|
138
|
+
await app.pressKeys(['enter']);
|
|
139
|
+
|
|
140
|
+
await app.assert('File saved successfully');
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Testing on Different Platforms
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
import { test } from 'vitest';
|
|
148
|
+
import { electron } from 'testdriverai/presets';
|
|
149
|
+
|
|
150
|
+
test('windows electron app', async (context) => {
|
|
151
|
+
const { app } = await electron(context, {
|
|
152
|
+
appPath: 'C:\\Program Files\\MyApp\\MyApp.exe',
|
|
153
|
+
os: 'windows'
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
await app.find('Start button').click();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('mac electron app', async (context) => {
|
|
160
|
+
const { app } = await electron(context, {
|
|
161
|
+
appPath: '/Applications/MyApp.app/Contents/MacOS/MyApp',
|
|
162
|
+
os: 'mac'
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
await app.find('Start button').click();
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Preferences and Settings
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
import { test } from 'vitest';
|
|
173
|
+
import { electron } from 'testdriverai/presets';
|
|
174
|
+
|
|
175
|
+
test('configure app settings', async (context) => {
|
|
176
|
+
const { app } = await electron(context, {
|
|
177
|
+
appPath: './dist/my-app'
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Open preferences
|
|
181
|
+
await app.find('Settings').click();
|
|
182
|
+
|
|
183
|
+
// Change theme
|
|
184
|
+
await app.find('Appearance').click();
|
|
185
|
+
await app.find('Dark mode toggle').click();
|
|
186
|
+
|
|
187
|
+
// Verify change
|
|
188
|
+
await app.assert('Dark mode is enabled');
|
|
189
|
+
|
|
190
|
+
// Save settings
|
|
191
|
+
await app.find('Save button').click();
|
|
192
|
+
|
|
193
|
+
await app.assert('Settings saved');
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Window Management
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
import { test } from 'vitest';
|
|
201
|
+
import { electron } from 'testdriverai/presets';
|
|
202
|
+
|
|
203
|
+
test('multiple windows', async (context) => {
|
|
204
|
+
const { app } = await electron(context, {
|
|
205
|
+
appPath: './dist/multi-window-app'
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Open new window
|
|
209
|
+
await app.find('File').click();
|
|
210
|
+
await app.find('New Window').click();
|
|
211
|
+
|
|
212
|
+
// Switch between windows
|
|
213
|
+
await app.find('second window').click();
|
|
214
|
+
await app.assert('Second window is focused');
|
|
215
|
+
|
|
216
|
+
// Close window
|
|
217
|
+
await app.find('Close button').click();
|
|
218
|
+
|
|
219
|
+
await app.assert('Window closed');
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Form Interaction
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
import { test } from 'vitest';
|
|
227
|
+
import { electron } from 'testdriverai/presets';
|
|
228
|
+
|
|
229
|
+
test('form submission', async (context) => {
|
|
230
|
+
const { app, dashcam } = await electron(context, {
|
|
231
|
+
appPath: './dist/form-app'
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Fill form
|
|
235
|
+
await app.find('Name input').type('John Doe');
|
|
236
|
+
await app.find('Email input').type('john@example.com');
|
|
237
|
+
await app.find('Phone input').type('555-1234');
|
|
238
|
+
|
|
239
|
+
// Select dropdown
|
|
240
|
+
await app.find('Country dropdown').click();
|
|
241
|
+
await app.find('United States').click();
|
|
242
|
+
|
|
243
|
+
// Check checkbox
|
|
244
|
+
await app.find('Terms and conditions').click();
|
|
245
|
+
|
|
246
|
+
// Submit
|
|
247
|
+
await app.find('Submit button').click();
|
|
248
|
+
|
|
249
|
+
await app.assert('Form submitted successfully');
|
|
250
|
+
|
|
251
|
+
// Dashcam captures entire interaction
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## What It Does
|
|
256
|
+
|
|
257
|
+
When you call `electron()`, it automatically:
|
|
258
|
+
|
|
259
|
+
1. **Initializes TestDriver** - Creates and connects to sandbox
|
|
260
|
+
2. **Sets up Dashcam** - Authenticates and starts recording (if enabled)
|
|
261
|
+
3. **Launches Electron** - Starts your app with specified arguments
|
|
262
|
+
4. **Waits for Ready** - Ensures app is focused and windows are loaded
|
|
263
|
+
5. **Returns Instances** - Provides ready-to-use testdriver, app alias, and dashcam
|
|
264
|
+
|
|
265
|
+
At test end:
|
|
266
|
+
- Dashcam automatically stops and saves replay URL
|
|
267
|
+
- TestDriver automatically disconnects
|
|
268
|
+
- All cleanup is handled for you
|
|
269
|
+
|
|
270
|
+
## Common Patterns
|
|
271
|
+
|
|
272
|
+
### IPC Communication Testing
|
|
273
|
+
|
|
274
|
+
```javascript
|
|
275
|
+
test('ipc events', async (context) => {
|
|
276
|
+
const { app } = await electron(context, {
|
|
277
|
+
appPath: './dist/ipc-app'
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Trigger IPC event from renderer
|
|
281
|
+
await app.find('Send Message button').click();
|
|
282
|
+
|
|
283
|
+
// Verify main process response
|
|
284
|
+
await app.assert('Response received from main process');
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Notification Testing
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
test('system notifications', async (context) => {
|
|
292
|
+
const { app } = await electron(context, {
|
|
293
|
+
appPath: './dist/notification-app'
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
await app.find('Show Notification').click();
|
|
297
|
+
await app.assert('System notification appears');
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Tray Icon Interaction
|
|
302
|
+
|
|
303
|
+
```javascript
|
|
304
|
+
test('system tray', async (context) => {
|
|
305
|
+
const { app } = await electron(context, {
|
|
306
|
+
appPath: './dist/tray-app'
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Click tray icon
|
|
310
|
+
await app.find('app tray icon').click();
|
|
311
|
+
|
|
312
|
+
// Interact with tray menu
|
|
313
|
+
await app.find('Show Window').click();
|
|
314
|
+
|
|
315
|
+
await app.assert('Main window appears');
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Auto-Update Flow
|
|
320
|
+
|
|
321
|
+
```javascript
|
|
322
|
+
test('app update', async (context) => {
|
|
323
|
+
const { app } = await electron(context, {
|
|
324
|
+
appPath: './dist/updatable-app',
|
|
325
|
+
args: ['--check-updates']
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
await app.find('Check for Updates').click();
|
|
329
|
+
await app.assert('Checking for updates message');
|
|
330
|
+
|
|
331
|
+
// Assuming update is available
|
|
332
|
+
await app.find('Download Update').click();
|
|
333
|
+
await app.assert('Update downloaded');
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Development Paths
|
|
338
|
+
|
|
339
|
+
### Common Development Paths
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
// Electron Forge
|
|
343
|
+
appPath: './out/my-app-linux-x64/my-app'
|
|
344
|
+
|
|
345
|
+
// Electron Builder
|
|
346
|
+
appPath: './dist/linux-unpacked/my-app'
|
|
347
|
+
|
|
348
|
+
// Direct execution
|
|
349
|
+
appPath: './node_modules/.bin/electron'
|
|
350
|
+
args: ['./main.js']
|
|
351
|
+
|
|
352
|
+
// Packaged app (Windows)
|
|
353
|
+
appPath: 'C:\\Program Files\\MyApp\\MyApp.exe'
|
|
354
|
+
|
|
355
|
+
// Packaged app (macOS)
|
|
356
|
+
appPath: '/Applications/MyApp.app/Contents/MacOS/MyApp'
|
|
357
|
+
|
|
358
|
+
// Packaged app (Linux)
|
|
359
|
+
appPath: '/opt/MyApp/my-app'
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Using with provision()
|
|
363
|
+
|
|
364
|
+
The `electron()` preset can also be called via the unified `provision()` function:
|
|
365
|
+
|
|
366
|
+
```javascript
|
|
367
|
+
import { provision } from 'testdriverai/presets';
|
|
368
|
+
|
|
369
|
+
test('using provision', async (context) => {
|
|
370
|
+
const { app } = await provision('electron', {
|
|
371
|
+
appPath: './dist/my-app'
|
|
372
|
+
}, context);
|
|
373
|
+
|
|
374
|
+
// Same functionality as electron() directly
|
|
375
|
+
});
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Error Handling
|
|
379
|
+
|
|
380
|
+
```javascript
|
|
381
|
+
test('handles missing app path', async (context) => {
|
|
382
|
+
try {
|
|
383
|
+
const { app } = await electron(context, {
|
|
384
|
+
appPath: '/nonexistent/path'
|
|
385
|
+
});
|
|
386
|
+
} catch (error) {
|
|
387
|
+
// Cleanup still happens automatically
|
|
388
|
+
expect(error.message).toContain('appPath');
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
test('handles app crashes', async (context) => {
|
|
393
|
+
const { app } = await electron(context, {
|
|
394
|
+
appPath: './dist/my-app'
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
// Trigger something that might crash
|
|
399
|
+
await app.find('Crash button').click();
|
|
400
|
+
} catch (error) {
|
|
401
|
+
// Dashcam still saves replay of crash
|
|
402
|
+
console.error('App crashed:', error);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Debugging Tips
|
|
408
|
+
|
|
409
|
+
1. **Enable Electron DevTools** - Pass `--enable-logging` in args
|
|
410
|
+
2. **Use Dashcam** - Review test recordings to see what happened
|
|
411
|
+
3. **Custom User Data** - Use `--user-data-dir` for isolated testing
|
|
412
|
+
4. **Remote Debugging** - Use `--remote-debugging-port=9222`
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
test('with debugging enabled', async (context) => {
|
|
416
|
+
const { app } = await electron(context, {
|
|
417
|
+
appPath: './dist/my-app',
|
|
418
|
+
args: [
|
|
419
|
+
'--enable-logging',
|
|
420
|
+
'--remote-debugging-port=9222',
|
|
421
|
+
'--user-data-dir=/tmp/test-profile'
|
|
422
|
+
]
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Test with full debugging capabilities
|
|
426
|
+
});
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## See Also
|
|
430
|
+
|
|
431
|
+
- [Provision API](/v7/progressive-apis/PROVISION) - Overview of all presets
|
|
432
|
+
- [Chrome Preset](/v7/presets/chrome) - Testing web applications
|
|
433
|
+
- [VS Code Preset](/v7/presets/vscode) - Testing VS Code extensions
|
|
434
|
+
- [Vitest Integration](/v7/guides/vitest) - Complete Vitest setup guide
|
|
435
|
+
- [Hooks API](/v7/progressive-apis/HOOKS) - Manual lifecycle control
|