testdriverai 6.2.2 → 7.0.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/MIGRATION.md +389 -0
- package/PLUGIN_MIGRATION.md +222 -0
- package/PROMPT_CACHE.md +200 -0
- package/SDK_LOGGING.md +222 -0
- package/SDK_MIGRATION.md +474 -0
- package/SDK_README.md +1122 -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 +258 -68
- 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 +143 -188
- package/agent/lib/redraw.js +6 -3
- package/agent/lib/sandbox.js +19 -5
- package/agent/lib/sdk.js +1 -0
- package/agent/lib/system.js +0 -3
- package/agent/lib/validation.js +1 -7
- package/debug-locate-response.js +82 -0
- package/debug-screenshot-1763401388589.png +0 -0
- package/debugger/index.html +15 -4
- package/docs/ARCHITECTURE.md +424 -0
- package/docs/AWESOME_LOGS_QUICK_REF.md +100 -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 +232 -152
- 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/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/pressKeys.mdx +349 -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/quickstart.mdx +199 -0
- package/docs/v7/guides/migration.mdx +562 -0
- package/docs/{getting-started → v7/guides}/self-hosting.mdx +11 -12
- package/docs/v7/playwright.mdx +342 -0
- package/eslint.config.js +19 -1
- package/examples/run-tests-with-recording.sh +70 -0
- package/examples/screenshot-example.js +63 -0
- package/examples/sdk-awesome-logs-demo.js +177 -0
- package/examples/sdk-cache-thresholds.js +96 -0
- package/examples/sdk-element-properties.js +155 -0
- package/examples/sdk-simple-example.js +65 -0
- package/examples/test-recording-example.test.js +166 -0
- 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 +744 -0
- package/mcp-server/AI_GUIDELINES.md +57 -0
- package/package.json +18 -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 +735 -0
- package/sdk.js +1906 -0
- package/{.github/workflows/self-hosted.yml → self-hosted.yml} +13 -4
- package/setup/aws/cloudformation.yaml +9 -2
- package/test/mcp-example-test.yaml +27 -0
- package/test-find-api.js +73 -0
- package/test-prompt-cache.js +96 -0
- package/test-sandbox-render.js +28 -0
- package/test-sdk-methods.js +15 -0
- package/test-sdk-refactor.js +53 -0
- package/test-stack-trace.mjs +57 -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 +44 -0
- package/testdriver/acceptance-sdk/drag-and-drop.test.mjs +70 -0
- package/testdriver/acceptance-sdk/element-not-found.test.mjs +38 -0
- package/testdriver/acceptance-sdk/exec-js.test.mjs +55 -0
- package/testdriver/acceptance-sdk/exec-output.test.mjs +71 -0
- package/testdriver/acceptance-sdk/exec-pwsh.test.mjs +69 -0
- package/testdriver/acceptance-sdk/focus-window.test.mjs +48 -0
- package/testdriver/acceptance-sdk/formatted-logging.test.mjs +41 -0
- package/testdriver/acceptance-sdk/hover-image.test.mjs +43 -0
- package/testdriver/acceptance-sdk/hover-text-with-description.test.mjs +50 -0
- package/testdriver/acceptance-sdk/hover-text.test.mjs +41 -0
- package/testdriver/acceptance-sdk/match-image.test.mjs +48 -0
- package/testdriver/acceptance-sdk/press-keys.test.mjs +64 -0
- package/testdriver/acceptance-sdk/prompt.test.mjs +45 -0
- package/testdriver/acceptance-sdk/scroll-keyboard.test.mjs +52 -0
- package/testdriver/acceptance-sdk/scroll-until-image.test.mjs +51 -0
- package/testdriver/acceptance-sdk/scroll-until-text.test.mjs +42 -0
- package/testdriver/acceptance-sdk/scroll.test.mjs +50 -0
- package/testdriver/acceptance-sdk/setup/globalTeardown.mjs +11 -0
- package/testdriver/acceptance-sdk/setup/lifecycleHelpers.mjs +239 -0
- package/testdriver/acceptance-sdk/setup/testHelpers.mjs +648 -0
- package/testdriver/acceptance-sdk/setup/vitestSetup.mjs +40 -0
- package/testdriver/acceptance-sdk/type-checking-demo.js +49 -0
- package/testdriver/acceptance-sdk/type.test.mjs +84 -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 +65 -0
- package/vitest.config.mjs.bak +44 -0
- package/.github/workflows/acceptance-v6.yml +0 -169
- 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,314 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "type()"
|
|
3
|
+
sidebarTitle: "type"
|
|
4
|
+
description: "Type text into focused input fields"
|
|
5
|
+
icon: "keyboard"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Type text or numbers into the currently focused input field with optional delay between keystrokes.
|
|
11
|
+
|
|
12
|
+
## Syntax
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
await testdriver.type(text, delay)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Parameters
|
|
19
|
+
|
|
20
|
+
<ParamField path="text" type="string | number" required>
|
|
21
|
+
Text to type (can be a string or number)
|
|
22
|
+
</ParamField>
|
|
23
|
+
|
|
24
|
+
<ParamField path="delay" type="number" default="250">
|
|
25
|
+
Delay between keystrokes in milliseconds
|
|
26
|
+
</ParamField>
|
|
27
|
+
|
|
28
|
+
## Returns
|
|
29
|
+
|
|
30
|
+
`Promise<void>`
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
### Basic Typing
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
// Type text
|
|
38
|
+
await testdriver.type('hello@example.com');
|
|
39
|
+
|
|
40
|
+
// Type numbers
|
|
41
|
+
await testdriver.type(12345);
|
|
42
|
+
|
|
43
|
+
// Type with custom delay
|
|
44
|
+
await testdriver.type('slow typing', 500); // 500ms between each character
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Form Filling
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
// Focus field and type
|
|
51
|
+
const emailField = await testdriver.find('email input');
|
|
52
|
+
await emailField.click();
|
|
53
|
+
await testdriver.type('user@example.com');
|
|
54
|
+
|
|
55
|
+
// Tab to next field and type
|
|
56
|
+
await testdriver.pressKeys(['tab']);
|
|
57
|
+
await testdriver.type('John Doe');
|
|
58
|
+
|
|
59
|
+
// Type password
|
|
60
|
+
await testdriver.pressKeys(['tab']);
|
|
61
|
+
await testdriver.type('MySecureP@ssw0rd');
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Clearing and Replacing Text
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
const searchBox = await testdriver.find('search input');
|
|
68
|
+
await searchBox.click();
|
|
69
|
+
|
|
70
|
+
// Clear existing text
|
|
71
|
+
await testdriver.pressKeys(['ctrl', 'a']); // Select all
|
|
72
|
+
await testdriver.type('new search query');
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Best Practices
|
|
76
|
+
|
|
77
|
+
<Check>
|
|
78
|
+
**Focus the field first**
|
|
79
|
+
|
|
80
|
+
Always click the input field or navigate to it before typing:
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const input = await testdriver.find('username input');
|
|
84
|
+
await input.click();
|
|
85
|
+
await testdriver.type('testuser');
|
|
86
|
+
```
|
|
87
|
+
</Check>
|
|
88
|
+
|
|
89
|
+
<Check>
|
|
90
|
+
**Use Tab for navigation**
|
|
91
|
+
|
|
92
|
+
Navigate between fields using Tab instead of clicking each one:
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const firstField = await testdriver.find('first name');
|
|
96
|
+
await firstField.click();
|
|
97
|
+
await testdriver.type('John');
|
|
98
|
+
|
|
99
|
+
await testdriver.pressKeys(['tab']);
|
|
100
|
+
await testdriver.type('Doe');
|
|
101
|
+
|
|
102
|
+
await testdriver.pressKeys(['tab']);
|
|
103
|
+
await testdriver.type('john@example.com');
|
|
104
|
+
```
|
|
105
|
+
</Check>
|
|
106
|
+
|
|
107
|
+
<Check>
|
|
108
|
+
**Clear fields before typing**
|
|
109
|
+
|
|
110
|
+
Clear existing content to avoid appending:
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
const input = await testdriver.find('search field');
|
|
114
|
+
await input.click();
|
|
115
|
+
await testdriver.pressKeys(['ctrl', 'a']); // Select all
|
|
116
|
+
await testdriver.type('new search');
|
|
117
|
+
```
|
|
118
|
+
</Check>
|
|
119
|
+
|
|
120
|
+
<Warning>
|
|
121
|
+
**Field must be focused**
|
|
122
|
+
|
|
123
|
+
Typing will only work if an input field is currently focused. If no field is focused, the text may be lost or trigger unexpected keyboard shortcuts.
|
|
124
|
+
</Warning>
|
|
125
|
+
|
|
126
|
+
## Use Cases
|
|
127
|
+
|
|
128
|
+
<AccordionGroup>
|
|
129
|
+
<Accordion title="Login Forms">
|
|
130
|
+
```javascript
|
|
131
|
+
await testdriver.focusApplication('Google Chrome');
|
|
132
|
+
|
|
133
|
+
const usernameField = await testdriver.find('username input');
|
|
134
|
+
await usernameField.click();
|
|
135
|
+
await testdriver.type('testuser@example.com');
|
|
136
|
+
|
|
137
|
+
await testdriver.pressKeys(['tab']);
|
|
138
|
+
await testdriver.type('MyP@ssword123');
|
|
139
|
+
|
|
140
|
+
await testdriver.pressKeys(['enter']);
|
|
141
|
+
```
|
|
142
|
+
</Accordion>
|
|
143
|
+
|
|
144
|
+
<Accordion title="Search Fields">
|
|
145
|
+
```javascript
|
|
146
|
+
const searchBox = await testdriver.find('search input');
|
|
147
|
+
await searchBox.click();
|
|
148
|
+
await testdriver.type('laptop computers');
|
|
149
|
+
await testdriver.pressKeys(['enter']);
|
|
150
|
+
|
|
151
|
+
// Wait for results
|
|
152
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
153
|
+
```
|
|
154
|
+
</Accordion>
|
|
155
|
+
|
|
156
|
+
<Accordion title="Multi-Field Forms">
|
|
157
|
+
```javascript
|
|
158
|
+
// First field
|
|
159
|
+
const nameField = await testdriver.find('full name input');
|
|
160
|
+
await nameField.click();
|
|
161
|
+
await testdriver.type('Jane Smith');
|
|
162
|
+
|
|
163
|
+
// Navigate with Tab
|
|
164
|
+
await testdriver.pressKeys(['tab']);
|
|
165
|
+
await testdriver.type('jane.smith@example.com');
|
|
166
|
+
|
|
167
|
+
await testdriver.pressKeys(['tab']);
|
|
168
|
+
await testdriver.type('+1-555-0123');
|
|
169
|
+
|
|
170
|
+
await testdriver.pressKeys(['tab']);
|
|
171
|
+
await testdriver.type('123 Main Street');
|
|
172
|
+
```
|
|
173
|
+
</Accordion>
|
|
174
|
+
|
|
175
|
+
<Accordion title="Text Editors">
|
|
176
|
+
```javascript
|
|
177
|
+
const editor = await testdriver.find('text editor area');
|
|
178
|
+
await editor.click();
|
|
179
|
+
|
|
180
|
+
await testdriver.type('# My Document', 100);
|
|
181
|
+
await testdriver.pressKeys(['enter', 'enter']);
|
|
182
|
+
await testdriver.type('This is the first paragraph.', 50);
|
|
183
|
+
```
|
|
184
|
+
</Accordion>
|
|
185
|
+
|
|
186
|
+
<Accordion title="Numeric Input">
|
|
187
|
+
```javascript
|
|
188
|
+
const quantityField = await testdriver.find('quantity input');
|
|
189
|
+
await quantityField.click();
|
|
190
|
+
|
|
191
|
+
// Clear field
|
|
192
|
+
await testdriver.pressKeys(['ctrl', 'a']);
|
|
193
|
+
|
|
194
|
+
// Type number
|
|
195
|
+
await testdriver.type(5);
|
|
196
|
+
```
|
|
197
|
+
</Accordion>
|
|
198
|
+
</AccordionGroup>
|
|
199
|
+
|
|
200
|
+
## Typing Speed
|
|
201
|
+
|
|
202
|
+
Adjust the delay parameter based on your needs:
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
// Fast typing (100ms delay)
|
|
206
|
+
await testdriver.type('quick entry', 100);
|
|
207
|
+
|
|
208
|
+
// Normal typing (250ms - default)
|
|
209
|
+
await testdriver.type('standard speed');
|
|
210
|
+
|
|
211
|
+
// Slow typing (500ms delay) - useful for fields with live validation
|
|
212
|
+
await testdriver.type('slow and steady', 500);
|
|
213
|
+
|
|
214
|
+
// Very slow (1000ms delay) - for problematic fields
|
|
215
|
+
await testdriver.type('one by one', 1000);
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
<Note>
|
|
219
|
+
Some applications with live validation or autocomplete may require slower typing speeds to avoid race conditions.
|
|
220
|
+
</Note>
|
|
221
|
+
|
|
222
|
+
## Special Characters
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
// Email addresses
|
|
226
|
+
await testdriver.type('user@example.com');
|
|
227
|
+
|
|
228
|
+
// URLs
|
|
229
|
+
await testdriver.type('https://example.com/path?query=value');
|
|
230
|
+
|
|
231
|
+
// Passwords with special characters
|
|
232
|
+
await testdriver.type('P@ssw0rd!#$%');
|
|
233
|
+
|
|
234
|
+
// Paths
|
|
235
|
+
await testdriver.type('C:\\Users\\Documents\\file.txt');
|
|
236
|
+
|
|
237
|
+
// Multi-line text (use pressKeys for Enter)
|
|
238
|
+
await testdriver.type('Line 1');
|
|
239
|
+
await testdriver.pressKeys(['enter']);
|
|
240
|
+
await testdriver.type('Line 2');
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Complete Example
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
import { beforeAll, afterAll, describe, it, expect } from 'vitest';
|
|
247
|
+
import TestDriver from 'testdriverai';
|
|
248
|
+
|
|
249
|
+
describe('Form Filling with Type', () => {
|
|
250
|
+
let testdriver;
|
|
251
|
+
|
|
252
|
+
beforeAll(async () => {
|
|
253
|
+
client = new TestDriver(process.env.TD_API_KEY);
|
|
254
|
+
await testdriver.auth();
|
|
255
|
+
await testdriver.connect({ newSandbox: true });
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
afterAll(async () => {
|
|
259
|
+
await testdriver.disconnect();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('should fill out registration form', async () => {
|
|
263
|
+
await testdriver.focusApplication('Google Chrome');
|
|
264
|
+
|
|
265
|
+
// Email field
|
|
266
|
+
const emailField = await testdriver.find('email input field');
|
|
267
|
+
await emailField.click();
|
|
268
|
+
await testdriver.type('john.doe@example.com');
|
|
269
|
+
|
|
270
|
+
// Tab through form fields
|
|
271
|
+
await testdriver.pressKeys(['tab']);
|
|
272
|
+
await testdriver.type('John');
|
|
273
|
+
|
|
274
|
+
await testdriver.pressKeys(['tab']);
|
|
275
|
+
await testdriver.type('Doe');
|
|
276
|
+
|
|
277
|
+
await testdriver.pressKeys(['tab']);
|
|
278
|
+
await testdriver.type('MySecureP@ssword123');
|
|
279
|
+
|
|
280
|
+
await testdriver.pressKeys(['tab']);
|
|
281
|
+
await testdriver.type('MySecureP@ssword123'); // Confirm password
|
|
282
|
+
|
|
283
|
+
// Verify fields were filled
|
|
284
|
+
const result = await testdriver.assert('all form fields are filled');
|
|
285
|
+
expect(result).toBeTruthy();
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('should update search query', async () => {
|
|
289
|
+
const searchBox = await testdriver.find('search input');
|
|
290
|
+
await searchBox.click();
|
|
291
|
+
|
|
292
|
+
// Type initial search
|
|
293
|
+
await testdriver.type('laptops');
|
|
294
|
+
await testdriver.pressKeys(['enter']);
|
|
295
|
+
|
|
296
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
297
|
+
|
|
298
|
+
// Update search
|
|
299
|
+
await searchBox.click();
|
|
300
|
+
await testdriver.pressKeys(['ctrl', 'a']); // Select all
|
|
301
|
+
await testdriver.type('gaming laptops');
|
|
302
|
+
await testdriver.pressKeys(['enter']);
|
|
303
|
+
|
|
304
|
+
// Verify new search
|
|
305
|
+
await testdriver.assert('search results for "gaming laptops" are shown');
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Related Methods
|
|
311
|
+
|
|
312
|
+
- [`pressKeys()`](/v7/api/pressKeys) - Press keyboard keys and shortcuts
|
|
313
|
+
- [`find()`](/v7/api/find) - Locate input fields
|
|
314
|
+
- [`click()`](/v7/api/click) - Focus input fields
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "assert"
|
|
3
|
+
sidebarTitle: "assert"
|
|
4
|
+
description: "Validate conditions during a test using the assert command."
|
|
5
|
+
icon: "check"
|
|
6
|
+
mode: "wide"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
import Replay from "/snippets/tests/assert-replay.mdx";
|
|
10
|
+
import Example from "/snippets/tests/assert-yaml.mdx";
|
|
11
|
+
|
|
12
|
+
<Replay />
|
|
13
|
+
<Example />
|
|
14
|
+
|
|
15
|
+
## Description
|
|
16
|
+
|
|
17
|
+
The `assert` command validates that a specific condition is true. It ensures that a task completed successfully by checking the screen for the expected outcome. If the condition isn't met, the test will fail.
|
|
18
|
+
|
|
19
|
+
## Arguments
|
|
20
|
+
|
|
21
|
+
| Argument | Type | Description |
|
|
22
|
+
| -------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
23
|
+
| `expect` | `string` | The condition to check. This should describe what you expect to see on the screen. |
|
|
24
|
+
| `async` | `boolean` | (Optional) If set to `true`, the test will continue without waiting for the assertion to pass. Default is `false`. |
|
|
25
|
+
| `invert` | `boolean` | (Optional) If set to `true`, will fail if the assertion passes. |
|
|
26
|
+
|
|
27
|
+
## Example usage
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
command: assert
|
|
31
|
+
expect: the video is playing
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Example with `async`
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
command: assert
|
|
38
|
+
expect: There is no error message
|
|
39
|
+
async: true
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- Use `async: true` to speed up tests by allowing non-blocking assertions. However, the test will still fail if the condition isn't met.
|
|
45
|
+
- Ensure the `expect` string clearly describes the condition to avoid ambiguity.
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "exec"
|
|
3
|
+
sidebarTitle: "exec"
|
|
4
|
+
description: "Execute custom shell or Node.js scripts within your tests."
|
|
5
|
+
icon: "code"
|
|
6
|
+
mode: "wide"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
import Replay from "/snippets/tests/exec-shell-replay.mdx";
|
|
10
|
+
import Example from "/snippets/tests/exec-shell-yaml.mdx";
|
|
11
|
+
|
|
12
|
+
<Replay />
|
|
13
|
+
<Example />
|
|
14
|
+
|
|
15
|
+
## Description
|
|
16
|
+
|
|
17
|
+
The `exec` command allows you to execute custom Node.js scripts within your TestDriver tests. This is useful for tasks like generating dynamic data, interacting with APIs, or performing custom logic during a test. The output of the script can be stored in a variable for use in subsequent steps. It's important to note that the output from `exec` must be a `string`.
|
|
18
|
+
|
|
19
|
+
## Arguments
|
|
20
|
+
|
|
21
|
+
| Argument | Type | Description |
|
|
22
|
+
| :------: | :------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| `lang` | `string` | The language of the script to execute. Supported values are `pwsh` and `js`. |
|
|
24
|
+
| `output` | `string` | The variable name to store the result of the script. This variable can be accessed as `${OUTPUT.<var>}` in future steps. |
|
|
25
|
+
| `code` | `string` | The script to execute on Windows systems. For `js`, the script must define the output as `result`. |
|
|
26
|
+
| `silent` | `string` | Defaults to `false`. The command will print the output of the script. This is useful for suppressing unnecessary or private output in the test logs and it's useful for debugging. |
|
|
27
|
+
|
|
28
|
+
## Example usage
|
|
29
|
+
|
|
30
|
+
This example demonstrates how to use the `exec` command to generate a TOTP (Time-based One-Time Password) using the `totp-generator` library.
|
|
31
|
+
|
|
32
|
+
```yaml otp-generator.yaml
|
|
33
|
+
version: 6.0.0
|
|
34
|
+
steps:
|
|
35
|
+
- commands:
|
|
36
|
+
- command: exec
|
|
37
|
+
lang: pwsh
|
|
38
|
+
code: |
|
|
39
|
+
npm install totp-generator
|
|
40
|
+
- command: exec
|
|
41
|
+
lang: js
|
|
42
|
+
output: totp
|
|
43
|
+
code: |
|
|
44
|
+
const { TOTP } = require("totp-generator");
|
|
45
|
+
let otp = TOTP.generate("JBSWY3DPEB3W64TMMQQQ").otp;
|
|
46
|
+
console.log(otp);
|
|
47
|
+
result = otp;
|
|
48
|
+
- command: type
|
|
49
|
+
text: ${OUTPUT.totp}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Additional details
|
|
53
|
+
|
|
54
|
+
- Supported `lang` values are `js` or `pwsh`:
|
|
55
|
+
- `js` code is executed in a Node.js [VM](https://nodejs.org/api/vm.html) internally on the host machine (for example the machine where your CI/CD runs, or your computer if using the local agent).
|
|
56
|
+
- `pwsh` code is executed in the shell on target runner (which can be the cloud runner, local sandbox, or local machine, depending on where you run your tests).
|
|
57
|
+
- **Note:** You can also use `pwsh` in [lifecycle](/guide/lifecycle) scripts to install npm packages if you need them.
|
|
58
|
+
- Otherwise, the `pwsh` code can be used within test steps to launch applications or perform simple commands (like writing text to a file on the machine to perform a simple file upload).
|
|
59
|
+
- The `output`argument is assigned automatically by setting `result = somestringvalue` in the script you run.
|
|
60
|
+
|
|
61
|
+
## Protips
|
|
62
|
+
|
|
63
|
+
- The `result` variable is already available in your script, overwrite it to store the output as shown in the examples.
|
|
64
|
+
- Do any handling of arrays or nested objects within your `js` script:
|
|
65
|
+
- ✅ `result = users[1].profile.firstName`
|
|
66
|
+
- ✅ `result = data.length > 0 ? data[0].userEmail : 'no user found'` if no data is found the value of output will be `null`
|
|
67
|
+
- ✅ `result = someTestUserEmail`
|
|
68
|
+
- ✅ `result = someTextToAssert`
|
|
69
|
+
- ✅ `result = someDescriptionOfAnImageToScrollTo`
|
|
70
|
+
- Don't try to pass any non-string values to `output`:
|
|
71
|
+
- ❌ `result = [...users, ...values]`
|
|
72
|
+
- ❌ `result = {name: "Dale Earnhardt", starts: 676, wins: 76}`
|
|
73
|
+
- ❌ `result = [{user1: ...}, {user2: ...}]`
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Ways to use `exec`
|
|
78
|
+
|
|
79
|
+
Here is an example using both `pwsh` and `js` contexts within a `prerun.yaml` script which creates a temporary email account and automatically clicks links found in received emails.
|
|
80
|
+
|
|
81
|
+
```yaml ./lifecycle/prerun.yaml [expandable]
|
|
82
|
+
version: 6.0.0
|
|
83
|
+
steps:
|
|
84
|
+
- commands:
|
|
85
|
+
- command: exec
|
|
86
|
+
lang: pwsh
|
|
87
|
+
code: |
|
|
88
|
+
npm install @sendgrid/mail
|
|
89
|
+
- command: exec
|
|
90
|
+
lang: js
|
|
91
|
+
output: accountData
|
|
92
|
+
code: |
|
|
93
|
+
const Mailjs = require("@cemalgnlts/mailjs");
|
|
94
|
+
const mailjs = new Mailjs();
|
|
95
|
+
let account = await mailjs.createOneAccount()
|
|
96
|
+
console.log("Account created:", account);
|
|
97
|
+
result = JSON.stringify(account.data)
|
|
98
|
+
- command: exec
|
|
99
|
+
lang: js
|
|
100
|
+
output: emailAddress
|
|
101
|
+
code: |
|
|
102
|
+
const accountData = ${OUTPUT.accountData};
|
|
103
|
+
result = accountData.username
|
|
104
|
+
- prompt: Enter the generated email into the email field
|
|
105
|
+
commands:
|
|
106
|
+
- command: hover-text
|
|
107
|
+
text: standard_user
|
|
108
|
+
description: email input field label
|
|
109
|
+
action: click
|
|
110
|
+
- command: type
|
|
111
|
+
text: ${OUTPUT.emailAddress}
|
|
112
|
+
- prompt: Wait for an email, extract links, and open each link
|
|
113
|
+
commands:
|
|
114
|
+
- command: exec
|
|
115
|
+
lang: js
|
|
116
|
+
code: |
|
|
117
|
+
const Mailjs = require("@cemalgnlts/mailjs");
|
|
118
|
+
const { JSDOM } = require('jsdom'); // To parse HTML and extract links
|
|
119
|
+
|
|
120
|
+
const accountData = ${OUTPUT.accountData};
|
|
121
|
+
|
|
122
|
+
const getLatestEmailAndClickLinks = async () => {
|
|
123
|
+
try {
|
|
124
|
+
// Initialize the Mailjs client
|
|
125
|
+
const mailjs = new Mailjs();
|
|
126
|
+
|
|
127
|
+
// Login to your account
|
|
128
|
+
await mailjs.login(accountData.username, accountData.password);
|
|
129
|
+
|
|
130
|
+
// Fetch list of messages
|
|
131
|
+
const messages = await mailjs.getMessages();
|
|
132
|
+
|
|
133
|
+
if (messages.length === 0) {
|
|
134
|
+
console.log('No emails found.');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Assuming the latest email is the first one in the list
|
|
139
|
+
const latestMessage = messages[0];
|
|
140
|
+
|
|
141
|
+
// Fetch the full details of the latest email
|
|
142
|
+
const fullMessage = await mailjs.getMessage(latestMessage.id);
|
|
143
|
+
|
|
144
|
+
console.log('Latest Email Details:', fullMessage);
|
|
145
|
+
|
|
146
|
+
// Parse the HTML content to extract links
|
|
147
|
+
const dom = new JSDOM(fullMessage.html);
|
|
148
|
+
const links = Array.from(dom.window.document.querySelectorAll('a')).map(a => a.href);
|
|
149
|
+
|
|
150
|
+
console.log('Found Links:', links);
|
|
151
|
+
|
|
152
|
+
// Click (fetch) every link using native fetch
|
|
153
|
+
for (const link of links) {
|
|
154
|
+
try {
|
|
155
|
+
const response = await fetch(link);
|
|
156
|
+
console.log('Clicked ${link}: ${response.status}');
|
|
157
|
+
} catch (linkError) {
|
|
158
|
+
console.error('Error clicking ${link}:', linkError);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error('Error fetching latest email or clicking links:', error);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
getLatestEmailAndClickLinks();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Using `exec` pwsh commands in a test file
|
|
171
|
+
|
|
172
|
+
In a test file, you can use the `pwsh` context directly:
|
|
173
|
+
|
|
174
|
+
```yaml calculator.yaml highlight={5-8} [expandable]
|
|
175
|
+
version: 6.0.0
|
|
176
|
+
steps:
|
|
177
|
+
- prompt: launch a calculator
|
|
178
|
+
commands:
|
|
179
|
+
- command: exec
|
|
180
|
+
lang: pwsh
|
|
181
|
+
code: |
|
|
182
|
+
start /B calc.exe
|
|
183
|
+
timeout /t 5
|
|
184
|
+
- command: wait-for-text
|
|
185
|
+
text: "calculator"
|
|
186
|
+
timeout: 30000
|
|
187
|
+
- prompt: performing the operation 2 + 2 = on the calculator that is opened
|
|
188
|
+
commands:
|
|
189
|
+
- command: focus-application
|
|
190
|
+
name: galculator
|
|
191
|
+
- command: hover-image
|
|
192
|
+
description: button with number 2 on the calculator
|
|
193
|
+
action: click
|
|
194
|
+
- command: hover-image
|
|
195
|
+
description: plus button on the calculator
|
|
196
|
+
action: click
|
|
197
|
+
- command: hover-image
|
|
198
|
+
description: button with number 2 on the calculator
|
|
199
|
+
action: click
|
|
200
|
+
- command: hover-image
|
|
201
|
+
description: equals button on the calculator
|
|
202
|
+
action: click
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### One more option
|
|
206
|
+
|
|
207
|
+
You can also save reusable snippets (like launching the calculator) to be inserted into a script later with the [`run`](/commands/run) command. That version would look something like this:
|
|
208
|
+
|
|
209
|
+
```yaml snippets/launch-calculator.yaml [expandable]
|
|
210
|
+
version: 6.0.0
|
|
211
|
+
steps:
|
|
212
|
+
- prompt: launch a calculator
|
|
213
|
+
commands:
|
|
214
|
+
- command: exec
|
|
215
|
+
lang: pwsh
|
|
216
|
+
code: |
|
|
217
|
+
start /B calc.exe
|
|
218
|
+
timeout /t 5
|
|
219
|
+
- command: wait-for-text
|
|
220
|
+
text: "calculator"
|
|
221
|
+
timeout: 30000
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Then in the test:
|
|
225
|
+
|
|
226
|
+
```yaml calculator.yaml highlight={5-6} [expandable]
|
|
227
|
+
version: 6.0.0
|
|
228
|
+
steps:
|
|
229
|
+
- prompt: launch a calculator
|
|
230
|
+
commands:
|
|
231
|
+
- command: run
|
|
232
|
+
file: snippets/launch-calculator.yaml
|
|
233
|
+
- prompt: performing the operation 2 + 2 = on the calculator that is opened
|
|
234
|
+
commands:
|
|
235
|
+
- command: focus-application
|
|
236
|
+
name: galculator
|
|
237
|
+
- command: hover-image
|
|
238
|
+
description: button with number 2 on the calculator
|
|
239
|
+
action: click
|
|
240
|
+
- command: hover-image
|
|
241
|
+
description: plus button on the calculator
|
|
242
|
+
action: click
|
|
243
|
+
- command: hover-image
|
|
244
|
+
description: button with number 2 on the calculator
|
|
245
|
+
action: click
|
|
246
|
+
- command: hover-image
|
|
247
|
+
description: equals button on the calculator
|
|
248
|
+
action: click
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Don't try to run `js` within a test field
|
|
252
|
+
|
|
253
|
+
This example will fail at runtime, so don't try to execute `js` context directly in a test file. Remember - use this in `prerun` to setup your test!
|
|
254
|
+
|
|
255
|
+
```yaml badtestfile.yaml [expandable]
|
|
256
|
+
version: 6.0.0
|
|
257
|
+
commands:
|
|
258
|
+
- command: exec
|
|
259
|
+
lang: pwsh
|
|
260
|
+
code: |
|
|
261
|
+
npm install -g axios json2csv
|
|
262
|
+
- prompt: fetch user data from API
|
|
263
|
+
commands:
|
|
264
|
+
- command: exec
|
|
265
|
+
output: user
|
|
266
|
+
lang: js
|
|
267
|
+
code: |
|
|
268
|
+
const axios = require('axios');
|
|
269
|
+
const { Parser } = require('json2csv');
|
|
270
|
+
const fs = require('fs');
|
|
271
|
+
|
|
272
|
+
const response = await axios.get('https://jsonplaceholder.typicode.com/users');
|
|
273
|
+
const parser = new Parser();
|
|
274
|
+
const csv = parser.parse(response.data);
|
|
275
|
+
fs.writeFileSync('users.csv', csv);
|
|
276
|
+
const user = response.data[0].name;
|
|
277
|
+
result = user;
|
|
278
|
+
console.log('username', user);
|
|
279
|
+
...
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
This example will produce errors in the TestDriver output or CLI since the runner won't have access to the Node.js VM context.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "focus-application"
|
|
3
|
+
sidebarTitle: "focus-application"
|
|
4
|
+
description: "Bring a specific application window to the foreground."
|
|
5
|
+
icon: "window-restore"
|
|
6
|
+
mode: "wide"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Description
|
|
10
|
+
|
|
11
|
+
The `focus-application` command displays a specific application window to the foreground. This ensures that subsequent commands interact with the correct application during a test.
|
|
12
|
+
|
|
13
|
+
## Arguments
|
|
14
|
+
|
|
15
|
+
| Argument | Type | Description |
|
|
16
|
+
| -------- | -------- | --------------------------------------------------------------------------------------- |
|
|
17
|
+
| `name` | `string` | The name of the application to focus. This should match the application's display name. |
|
|
18
|
+
|
|
19
|
+
## Example usage
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
command: focus-application
|
|
23
|
+
name: Google Chrome
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Protips
|
|
27
|
+
|
|
28
|
+
- Ensure the application name matches the exact name displayed in your operating system's task manager.
|
|
29
|
+
- Use this command at the start of a test or before interacting with an application to avoid focus-related issues.
|
|
30
|
+
|
|
31
|
+
<Note>
|
|
32
|
+
If the specified application isn't running, the command will fail. Ensure the application is open before using this command.
|
|
33
|
+
For example, to launch chrome try using the exec command:
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
- command: exec
|
|
37
|
+
lang: pwsh
|
|
38
|
+
code: start chrome
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
</Note>
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- The `focus-application` command is useful for multi-application workflows where you need to switch between different apps during a test.
|