webdriverio-execute 0.2.1 → 0.2.2
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/LICENSE +21 -21
- package/README.md +157 -157
- package/bin/wdiox.js +0 -0
- package/build/cli.js +23 -0
- package/build/cli.js.map +1 -1
- package/package.json +68 -68
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Vince Graics
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vince Graics
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,157 +1,157 @@
|
|
|
1
|
-
# wdiox — WebdriverIO Execute
|
|
2
|
-
|
|
3
|
-
Interactive browser and app CLI for developers, powered by [WebdriverIO](https://webdriver.io).
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
npm install -g webdriverio-execute
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
## How it works
|
|
10
|
-
|
|
11
|
-
Each command is stateless. Sessions are stored as JSON in `~/.wdio-x/sessions/`. Commands attach to an existing session by reading that file — no daemon, no background process.
|
|
12
|
-
|
|
13
|
-
`snapshot` captures all interactable elements and assigns short refs (`e1`, `e2`, …). Subsequent commands use those refs to act on elements.
|
|
14
|
-
|
|
15
|
-
## Commands
|
|
16
|
-
|
|
17
|
-
### `open` / `new` / `start`
|
|
18
|
-
|
|
19
|
-
Open a browser or Appium session.
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
wdiox open https://example.com
|
|
23
|
-
wdiox open https://example.com --browser firefox
|
|
24
|
-
wdiox open --app /path/to/app.apk --device "emulator-5554"
|
|
25
|
-
wdiox open --app /path/to/app.ipa --device "iPhone 15"
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
| Option | Default | Description |
|
|
29
|
-
|---|---|---|
|
|
30
|
-
| `--browser` | `chrome` | Browser to use (`chrome`, `firefox`, `edge`, `safari`) |
|
|
31
|
-
| `--app` | — | Path to mobile app (`.apk`, `.ipa`, `.app`) |
|
|
32
|
-
| `--device` | `emulator-5554` | Device name |
|
|
33
|
-
| `--platform` | auto-detected | `android` or `ios` |
|
|
34
|
-
| `--hostname` | `localhost` | WebDriver/Appium server hostname |
|
|
35
|
-
| `--port` | `4723` (mobile) / `4444` (browser) | Server port |
|
|
36
|
-
| `--grant-permissions` | `true` | Auto-grant app permissions (Appium) |
|
|
37
|
-
| `--accept-alert` | `true` | Auto-accept native alerts (Appium) |
|
|
38
|
-
| `--auto-dismiss` | `false` | Auto-dismiss native alerts (Appium) |
|
|
39
|
-
| `--session` | `default` | Session name |
|
|
40
|
-
|
|
41
|
-
If a session with the given name is already active, you'll be prompted to close it first.
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
### `snapshot`
|
|
46
|
-
|
|
47
|
-
Capture interactable elements on the current page or screen and assign numbered refs.
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
wdiox snapshot
|
|
51
|
-
wdiox snapshot --no-visible # include off-screen elements
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
Page: https://example.com/login
|
|
56
|
-
|
|
57
|
-
e1 input[email] "Email address" #email
|
|
58
|
-
e2 input[password] "Password" #password
|
|
59
|
-
e3 button "Sign in" button*=Sign in
|
|
60
|
-
|
|
61
|
-
3 elements - default session
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
### `click`
|
|
67
|
-
|
|
68
|
-
Click an element by ref.
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
wdiox click e3
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
### `fill` / `type`
|
|
77
|
-
|
|
78
|
-
Clear and type into an input by ref.
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
wdiox fill e1 "hello@example.com"
|
|
82
|
-
wdiox type e2 "mysecretpassword"
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
### `screenshot`
|
|
88
|
-
|
|
89
|
-
Save a screenshot.
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
wdiox screenshot
|
|
93
|
-
wdiox screenshot /tmp/login-page.png
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
### `close` / `stop`
|
|
99
|
-
|
|
100
|
-
Close the current session.
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
wdiox close
|
|
104
|
-
wdiox close --session myapp
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
### `ls` / `session-list`
|
|
110
|
-
|
|
111
|
-
List all active sessions.
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
wdiox ls
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
```
|
|
118
|
-
NAME BROWSER URL STATUS
|
|
119
|
-
default chrome https://example.com active
|
|
120
|
-
myapp Android /path/to/app.apk active
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Multi-session
|
|
126
|
-
|
|
127
|
-
Every command accepts `--session <name>` (or `-s <name>`) to target a specific session. The `WDIO_SESSION` environment variable sets the default session name.
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
wdiox open https://site-a.com --session a
|
|
131
|
-
wdiox open https://site-b.com --session b
|
|
132
|
-
wdiox snapshot --session a
|
|
133
|
-
wdiox click e1 --session a
|
|
134
|
-
wdiox close --session b
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## Typical browser workflow
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
wdiox open https://example.com
|
|
141
|
-
wdiox snapshot
|
|
142
|
-
wdiox fill e1 "user@example.com"
|
|
143
|
-
wdiox fill e2 "password"
|
|
144
|
-
wdiox click e3
|
|
145
|
-
wdiox screenshot
|
|
146
|
-
wdiox close
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Typical mobile workflow
|
|
150
|
-
|
|
151
|
-
```bash
|
|
152
|
-
wdiox open --app ./app.apk --device "emulator-5554"
|
|
153
|
-
wdiox snapshot
|
|
154
|
-
wdiox click e1
|
|
155
|
-
wdiox fill e2 "hello"
|
|
156
|
-
wdiox close
|
|
157
|
-
```
|
|
1
|
+
# wdiox — WebdriverIO Execute
|
|
2
|
+
|
|
3
|
+
Interactive browser and app CLI for developers, powered by [WebdriverIO](https://webdriver.io).
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
npm install -g webdriverio-execute
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## How it works
|
|
10
|
+
|
|
11
|
+
Each command is stateless. Sessions are stored as JSON in `~/.wdio-x/sessions/`. Commands attach to an existing session by reading that file — no daemon, no background process.
|
|
12
|
+
|
|
13
|
+
`snapshot` captures all interactable elements and assigns short refs (`e1`, `e2`, …). Subsequent commands use those refs to act on elements.
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### `open` / `new` / `start`
|
|
18
|
+
|
|
19
|
+
Open a browser or Appium session.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
wdiox open https://example.com
|
|
23
|
+
wdiox open https://example.com --browser firefox
|
|
24
|
+
wdiox open --app /path/to/app.apk --device "emulator-5554"
|
|
25
|
+
wdiox open --app /path/to/app.ipa --device "iPhone 15"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
| Option | Default | Description |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `--browser` | `chrome` | Browser to use (`chrome`, `firefox`, `edge`, `safari`) |
|
|
31
|
+
| `--app` | — | Path to mobile app (`.apk`, `.ipa`, `.app`) |
|
|
32
|
+
| `--device` | `emulator-5554` | Device name |
|
|
33
|
+
| `--platform` | auto-detected | `android` or `ios` |
|
|
34
|
+
| `--hostname` | `localhost` | WebDriver/Appium server hostname |
|
|
35
|
+
| `--port` | `4723` (mobile) / `4444` (browser) | Server port |
|
|
36
|
+
| `--grant-permissions` | `true` | Auto-grant app permissions (Appium) |
|
|
37
|
+
| `--accept-alert` | `true` | Auto-accept native alerts (Appium) |
|
|
38
|
+
| `--auto-dismiss` | `false` | Auto-dismiss native alerts (Appium) |
|
|
39
|
+
| `--session` | `default` | Session name |
|
|
40
|
+
|
|
41
|
+
If a session with the given name is already active, you'll be prompted to close it first.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### `snapshot`
|
|
46
|
+
|
|
47
|
+
Capture interactable elements on the current page or screen and assign numbered refs.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
wdiox snapshot
|
|
51
|
+
wdiox snapshot --no-visible # include off-screen elements
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Page: https://example.com/login
|
|
56
|
+
|
|
57
|
+
e1 input[email] "Email address" #email
|
|
58
|
+
e2 input[password] "Password" #password
|
|
59
|
+
e3 button "Sign in" button*=Sign in
|
|
60
|
+
|
|
61
|
+
3 elements - default session
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
### `click`
|
|
67
|
+
|
|
68
|
+
Click an element by ref.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
wdiox click e3
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### `fill` / `type`
|
|
77
|
+
|
|
78
|
+
Clear and type into an input by ref.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
wdiox fill e1 "hello@example.com"
|
|
82
|
+
wdiox type e2 "mysecretpassword"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### `screenshot`
|
|
88
|
+
|
|
89
|
+
Save a screenshot.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
wdiox screenshot
|
|
93
|
+
wdiox screenshot /tmp/login-page.png
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### `close` / `stop`
|
|
99
|
+
|
|
100
|
+
Close the current session.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
wdiox close
|
|
104
|
+
wdiox close --session myapp
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### `ls` / `session-list`
|
|
110
|
+
|
|
111
|
+
List all active sessions.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
wdiox ls
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
NAME BROWSER URL STATUS
|
|
119
|
+
default chrome https://example.com active
|
|
120
|
+
myapp Android /path/to/app.apk active
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Multi-session
|
|
126
|
+
|
|
127
|
+
Every command accepts `--session <name>` (or `-s <name>`) to target a specific session. The `WDIO_SESSION` environment variable sets the default session name.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
wdiox open https://site-a.com --session a
|
|
131
|
+
wdiox open https://site-b.com --session b
|
|
132
|
+
wdiox snapshot --session a
|
|
133
|
+
wdiox click e1 --session a
|
|
134
|
+
wdiox close --session b
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Typical browser workflow
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
wdiox open https://example.com
|
|
141
|
+
wdiox snapshot
|
|
142
|
+
wdiox fill e1 "user@example.com"
|
|
143
|
+
wdiox fill e2 "password"
|
|
144
|
+
wdiox click e3
|
|
145
|
+
wdiox screenshot
|
|
146
|
+
wdiox close
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Typical mobile workflow
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
wdiox open --app ./app.apk --device "emulator-5554"
|
|
153
|
+
wdiox snapshot
|
|
154
|
+
wdiox click e1
|
|
155
|
+
wdiox fill e2 "hello"
|
|
156
|
+
wdiox close
|
|
157
|
+
```
|
package/bin/wdiox.js
CHANGED
|
File without changes
|
package/build/cli.js
CHANGED
|
@@ -188,6 +188,7 @@ Close it and start a new one? (y/N) `);
|
|
|
188
188
|
capabilities["appium:autoDismissAlerts"] = argv.autoDismiss;
|
|
189
189
|
} else {
|
|
190
190
|
capabilities.browserName = argv.browser;
|
|
191
|
+
capabilities["wdio:chromedriverOptions"] = { spawnOpts: { detached: true } };
|
|
191
192
|
}
|
|
192
193
|
const remoteOpts = { capabilities, logLevel: process.env.WDIO_LOG_LEVEL ?? "error" };
|
|
193
194
|
if (argv.hostname || argv.port || isMobile) {
|
|
@@ -218,15 +219,37 @@ __export(close_exports, {
|
|
|
218
219
|
desc: () => desc2,
|
|
219
220
|
handler: () => handler2
|
|
220
221
|
});
|
|
222
|
+
import os2 from "os";
|
|
223
|
+
import { execSync } from "child_process";
|
|
221
224
|
import { attach as attach2 } from "webdriverio";
|
|
222
225
|
var command2 = ["close", "stop"];
|
|
223
226
|
var desc2 = "Close the current session";
|
|
227
|
+
function killProcess(pid) {
|
|
228
|
+
const platform = os2.platform();
|
|
229
|
+
try {
|
|
230
|
+
if (platform === "win32") {
|
|
231
|
+
execSync(`taskkill /F /PID ${pid}`, { stdio: "ignore" });
|
|
232
|
+
} else {
|
|
233
|
+
execSync(`kill -9 ${pid}`, { stdio: "ignore" });
|
|
234
|
+
}
|
|
235
|
+
} catch {
|
|
236
|
+
}
|
|
237
|
+
}
|
|
224
238
|
var handler2 = withSession(async (argv, meta, sessionsDir) => {
|
|
225
239
|
const sessionName = argv.session;
|
|
240
|
+
const caps = meta.capabilities;
|
|
241
|
+
const browserPid = typeof caps["goog:processID"] === "number" ? caps["goog:processID"] : void 0;
|
|
242
|
+
const driverPid = typeof caps["wdio:driverPID"] === "number" ? caps["wdio:driverPID"] : void 0;
|
|
226
243
|
try {
|
|
227
244
|
const browser = await attach2(buildAttachOptions(meta));
|
|
228
245
|
await browser.deleteSession();
|
|
229
246
|
} catch {
|
|
247
|
+
if (browserPid) {
|
|
248
|
+
killProcess(browserPid);
|
|
249
|
+
}
|
|
250
|
+
if (driverPid && driverPid !== browserPid) {
|
|
251
|
+
killProcess(driverPid);
|
|
252
|
+
}
|
|
230
253
|
}
|
|
231
254
|
await deleteSessionFiles(sessionName, sessionsDir);
|
|
232
255
|
console.log(`Session "${sessionName}" closed.`);
|
package/build/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/open.ts","../src/session.ts","../src/commands/close.ts","../src/commands/snapshot.ts","../src/refs.ts","../src/format.ts","../src/commands/click.ts","../src/commands/type.ts","../src/commands/screenshot.ts","../src/commands/session-list.ts"],"sourcesContent":["import yargs from 'yargs';\nimport type { CommandModule } from 'yargs';\nimport { hideBin } from 'yargs/helpers';\n\nimport * as openCmd from './commands/open.js';\nimport * as closeCmd from './commands/close.js';\nimport * as snapshotCmd from './commands/snapshot.js';\nimport * as clickCmd from './commands/click.js';\nimport * as fillCmd from './commands/type';\nimport * as screenshotCmd from './commands/screenshot.js';\nimport * as sessionListCmd from './commands/session-list.js';\n\nconst commands = [\n openCmd, closeCmd, snapshotCmd, clickCmd,\n fillCmd, screenshotCmd, sessionListCmd,\n] as unknown as CommandModule[];\n\nexport async function run() {\n\n // webdriverio's attach() can spawn async BiDi connections that fail after\n // the function returns (e.g. stale session). Suppress these so the CLI\n // doesn't crash during close/reconnect of dead sessions.\n process.on('unhandledRejection', () => {});\n\n let cli = yargs(hideBin(process.argv))\n .scriptName('wdiox')\n .usage('$0 <command> [options]')\n .option('session', {\n alias: 's',\n type: 'string',\n default: process.env.WDIO_SESSION || 'default',\n describe: 'Session name',\n });\n\n for (const cmd of commands) {\n cli = cli.command(cmd);\n }\n\n await cli\n .demandCommand(1, 'You need to specify a command. Try: wdiox open <url>')\n .strict()\n .help()\n .version()\n .parse();\n\n // webdriverio keeps HTTP agents alive — force clean exit after command completes\n process.exit(0);\n}\n","import readline from 'node:readline/promises';\nimport type { ArgumentsCamelCase, Argv } from 'yargs';\nimport type { Capabilities } from '@wdio/types';\nimport { attach, remote } from 'webdriverio';\n\nimport { writeSession, readSession, getSessionDir, buildAttachOptions, deleteSessionFiles } from '../session.js';\n\nexport const command = ['open [url]', 'new [url]', 'start [url]'];\nexport const desc = 'Open a browser or Appium session';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('url', {\n type: 'string',\n describe: 'URL to navigate to',\n })\n .option('browser', {\n alias: 'b',\n type: 'string',\n default: 'chrome',\n describe: 'Browser to use (chrome, firefox, edge, safari)',\n })\n .option('app', {\n type: 'string',\n describe: 'Path to mobile app (.apk, .ipa, .app)',\n })\n .option('device', {\n alias: 'd',\n type: 'string',\n describe: 'Device name for mobile testing',\n })\n .option('platform', {\n type: 'string',\n describe: 'Mobile platform (android, ios)',\n })\n .option('path', {\n type: 'string',\n describe: 'WebDriver/Appium server session path (default: /)',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n describe: 'WebDriver/Appium server port (default: 4723)',\n })\n .option('hostname', {\n type: 'string',\n describe: 'WebDriver/Appium server hostname (default: localhost)',\n })\n .option('grant-permissions', {\n type: 'boolean',\n default: true,\n describe: 'Auto-grant app permissions (Appium only)',\n })\n .option('accept-alert', {\n type: 'boolean',\n default: true,\n describe: 'Auto-accept native alerts (Appium only)',\n })\n .option('auto-dismiss', {\n type: 'boolean',\n default: false,\n describe: 'Auto-dismiss native alerts (Appium only)',\n });\n};\n\ninterface OpenArgs {\n url?: string\n browser: string\n session: string\n app?: string\n device?: string\n platform?: string\n port?: number\n hostname?: string\n grantPermissions: boolean\n acceptAlert: boolean\n autoDismiss: boolean\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<OpenArgs>) {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const existing = await readSession(sessionName, sessionsDir);\n if (existing) {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const context = existing.url || (existing.capabilities['appium:app'] as string) || '';\n const answer = await rl.question(`Session [${sessionName}] is already active${context ? ` (${context})` : ''}.\\nClose it and start a new one? (y/N) `);\n rl.close();\n\n if (answer.trim().toLowerCase() !== 'y') {\n return;\n }\n\n try {\n const old = await attach(buildAttachOptions(existing));\n await old.deleteSession();\n } catch {\n // Already dead\n }\n await deleteSessionFiles(sessionName, sessionsDir);\n }\n\n const capabilities: Record<string, unknown> = {};\n\n const isMobile = !!argv.app;\n if (isMobile) {\n const platform = argv.platform ?? (argv.app?.endsWith('.apk') ? 'android' : 'ios');\n\n capabilities.platformName = platform === 'ios' ? 'iOS' : 'Android';\n capabilities['appium:app'] = argv.app;\n capabilities['appium:deviceName'] = argv.device ?? 'emulator-5554';\n capabilities['appium:newCommandTimeout'] = 300;\n capabilities['appium:automationName'] = platform === 'ios' ? 'XCUITest' : 'UiAutomator2';\n capabilities['appium:autoGrantPermissions'] = argv.grantPermissions;\n capabilities['appium:autoAcceptAlerts'] = argv.acceptAlert;\n capabilities['appium:autoDismissAlerts'] = argv.autoDismiss;\n } else {\n capabilities.browserName = argv.browser;\n }\n\n const remoteOpts: Record<string, unknown> = { capabilities, logLevel: process.env.WDIO_LOG_LEVEL ?? 'error' };\n // For mobile / Appium, explicit connection is required\n if (argv.hostname || argv.port || isMobile) {\n remoteOpts.hostname = argv.hostname ?? 'localhost';\n remoteOpts.port = argv.port ?? (isMobile ? 4723 : 4444);\n remoteOpts.path = argv.path ?? '/';\n }\n\n const browser = await remote(remoteOpts as unknown as Capabilities.WebdriverIOConfig);\n\n if (argv.url) {\n await browser.url(argv.url);\n }\n\n const opts = browser.options as Capabilities.WebdriverIOConfig;\n await writeSession(sessionName, {\n sessionId: browser.sessionId,\n hostname: opts?.hostname || 'localhost',\n port: opts?.port || 4444,\n capabilities: { ...capabilities, ...browser.capabilities as Record<string, unknown> },\n created: new Date().toISOString(),\n url: argv.url || '',\n }, sessionsDir);\n\n console.log(`Session \"${sessionName}\" started.`);\n}\n","import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { AttachOptions } from 'webdriverio';\nimport type { ArgumentsCamelCase } from 'yargs';\n\nexport interface SessionMetadata {\n sessionId: string\n hostname: string\n port: number\n capabilities: Record<string, unknown>\n created: string\n url: string\n}\n\nexport interface SessionEntry {\n name: string\n metadata: SessionMetadata\n}\n\nconst DEFAULT_SESSION_DIR = path.join(os.homedir(), '.wdio-x', 'sessions');\n\nfunction isEnoent(err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Build attach options from session metadata for use with webdriverio's `attach()`.\n */\nexport function buildAttachOptions(meta: SessionMetadata): AttachOptions {\n return {\n sessionId: meta.sessionId,\n capabilities: meta.capabilities as WebdriverIO.Capabilities,\n options: {\n hostname: meta.hostname,\n port: meta.port,\n logLevel: process.env.WDIO_LOG_LEVEL ?? 'error',\n },\n } as AttachOptions;\n}\n\n/**\n * Returns the session directory path. Defaults to ~/.wdio-x/sessions/.\n */\nexport function getSessionDir (baseDir?: string): string {\n return baseDir ?? DEFAULT_SESSION_DIR;\n}\n\n/**\n * Returns the file path for a session's metadata JSON file.\n */\nexport function getSessionPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.json`);\n}\n\n/**\n * Returns the file path for a session's refs JSON file.\n */\nexport function getRefsPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.refs.json`);\n}\n\n/**\n * Writes session metadata to disk, creating the directory if needed.\n */\nexport async function writeSession (\n name: string,\n metadata: SessionMetadata,\n baseDir?: string,\n): Promise<void> {\n const dir = getSessionDir(baseDir);\n await fs.mkdir(dir, { recursive: true });\n const filePath = getSessionPath(name, baseDir);\n await fs.writeFile(filePath, JSON.stringify(metadata, null, 2));\n}\n\n/**\n * Reads session metadata from disk. Returns null if the session file does not exist.\n */\nexport async function readSession (\n name: string,\n baseDir?: string,\n): Promise<SessionMetadata | null> {\n const filePath = getSessionPath(name, baseDir);\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as SessionMetadata;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Deletes both the .json and .refs.json files for a session.\n * Does not throw if the files do not exist.\n */\nexport async function deleteSessionFiles (\n name: string,\n baseDir?: string,\n): Promise<void> {\n const sessionPath = getSessionPath(name, baseDir);\n const refsPath = getRefsPath(name, baseDir);\n await Promise.all([\n fs.rm(sessionPath, { force: true }),\n fs.rm(refsPath, { force: true }),\n ]);\n}\n\n/**\n * Lists all sessions in the session directory.\n * Only considers .json files (excludes .refs.json).\n * Returns an empty array if the directory does not exist.\n */\nexport async function listSessions (baseDir?: string): Promise<SessionEntry[]> {\n const dir = getSessionDir(baseDir);\n let files: string[];\n try {\n files = await fs.readdir(dir);\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return [];\n }\n throw err;\n }\n\n const sessionFiles = files.filter(\n (f) => f.endsWith('.json') && !f.endsWith('.refs.json'),\n );\n\n return await Promise.all(\n sessionFiles.map(async (f) => {\n const name = f.replace(/\\.json$/, '');\n const metadata = await readSession(name, baseDir);\n return { name, metadata: metadata! };\n }),\n );\n}\n\ninterface SessionArgs {\n session: string\n _sessionsDir?: string\n}\n\n/**\n * Wraps a command handler that requires an active session.\n * Reads the session from disk and exits early with an error if not found.\n */\nexport function withSession<T extends SessionArgs>(\n fn: (argv: ArgumentsCamelCase<T>, meta: SessionMetadata, sessionsDir: string) => Promise<void>,\n): (argv: ArgumentsCamelCase<T>) => Promise<void> {\n return async function handler(argv: ArgumentsCamelCase<T>): Promise<void> {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const meta = await readSession(sessionName, sessionsDir);\n if (!meta) {\n console.error(`Error: No active session [${sessionName}]. Run wdiox open <url> first.`);\n return;\n }\n\n await fn(argv, meta, sessionsDir);\n };\n}\n","import type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { deleteSessionFiles, buildAttachOptions, withSession } from '../session.js';\n\nexport const command = ['close', 'stop'];\nexport const desc = 'Close the current session';\n\ninterface CloseArgs {\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<CloseArgs>(async (argv: ArgumentsCamelCase<CloseArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n\n try {\n const browser = await attach(buildAttachOptions(meta));\n await browser.deleteSession();\n } catch {\n // Session may already be dead - clean up anyway\n }\n\n await deleteSessionFiles(sessionName, sessionsDir);\n console.log(`Session \"${sessionName}\" closed.`);\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { writeRefs, type RefMap } from '../refs.js';\nimport { getInteractableBrowserElements, getMobileVisibleElements } from '@wdio/mcp/snapshot';\nimport {\n formatBrowserElement,\n formatMobileElement,\n} from '../format.js';\n\nexport const command = 'snapshot';\nexport const desc = 'Capture interactive elements on the page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .option('visible', {\n type: 'boolean',\n default: true,\n describe: 'Only show elements in viewport',\n });\n};\n\ninterface SnapshotArgs {\n session: string\n visible: boolean\n _sessionsDir?: string\n}\n\nexport const handler = withSession<SnapshotArgs>(async (argv: ArgumentsCamelCase<SnapshotArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const browser = await attach(buildAttachOptions(meta));\n\n const isMobile = browser.isAndroid || browser.isIOS;\n const refs: RefMap = {};\n\n if (isMobile) {\n const platform = browser.isIOS ? 'ios' : 'android';\n const elements = await getMobileVisibleElements(browser, platform);\n const filtered = argv.visible\n ? elements.filter(el => el.isInViewport)\n : elements;\n\n const appName = (meta.capabilities['appium:app'] as string) || 'unknown';\n console.log(`\\n App: ${appName}\\n`);\n\n filtered.forEach((el, i) => {\n const ref = `e${i + 1}`;\n console.log(formatMobileElement(ref, {\n tagName: el.tagName,\n text: el.text,\n selector: el.selector,\n accessibilityId: el.accessibilityId,\n resourceId: el.resourceId,\n }));\n refs[ref] = {\n selector: el.selector,\n tagName: el.tagName,\n text: el.text,\n };\n });\n\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\n } else {\n const elements = await getInteractableBrowserElements(browser);\n const filtered = argv.visible\n ? elements.filter(el => el.isInViewport)\n : elements;\n\n const currentUrl = await browser.getUrl();\n console.log(`\\n Page: ${currentUrl}\\n`);\n\n filtered.forEach((el, i) => {\n const ref = `e${i + 1}`;\n console.log(formatBrowserElement(ref, el));\n refs[ref] = {\n selector: el.selector,\n tagName: el.tagName,\n text: el.name || '',\n };\n });\n\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\n }\n\n await writeRefs(getRefsPath(sessionName, sessionsDir), refs);\n});\n","import fs from 'node:fs/promises';\n\nexport interface RefEntry {\n selector?: string\n tagName: string\n text?: string\n placeholder?: string\n [key: string]: unknown\n}\n\nexport type RefMap = Record<string, RefEntry>;\n\nfunction isEnoent (err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Writes a ref map to disk as JSON.\n */\nexport async function writeRefs (refsPath: string, refs: RefMap): Promise<void> {\n await fs.writeFile(refsPath, JSON.stringify(refs, null, 2), 'utf-8');\n}\n\n/**\n * Reads a ref map from disk. Returns null if the file doesn't exist.\n */\nexport async function readRefs (refsPath: string): Promise<RefMap | null> {\n try {\n const content = await fs.readFile(refsPath, 'utf-8');\n return JSON.parse(content) as RefMap;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Look up a ref by key: reads refs file, finds the entry, resolves its selector.\n * Logs appropriate error messages and returns null on failure.\n */\nexport async function lookupRef (\n refsPath: string,\n refKey: string,\n): Promise<{ ref: RefEntry; selector: string } | null> {\n const refs = await readRefs(refsPath);\n if (!refs) {\n console.error('Error: No snapshot taken. Run wdiox snapshot first.');\n return null;\n }\n\n const ref = refs[refKey];\n if (!ref) {\n const available = Object.keys(refs);\n const range = available.length > 0\n ? `Available: ${available[0]}-${available[available.length - 1]}`\n : 'No refs available';\n console.error(`Error: ${refKey} not found in snapshot. ${range}`);\n return null;\n }\n\n if (!ref.selector) {\n console.error(`Error: Could not resolve selector for ${refKey}`);\n return null;\n }\n\n return { ref, selector: ref.selector };\n}\n","export interface BrowserElementFormatInput {\n tagName: string\n role?: string\n type?: string\n name?: string\n href?: string\n selector: string\n}\n\nexport interface MobileElementFormatInput {\n tagName: string\n text?: string\n selector: string\n accessibilityId?: string\n resourceId?: string\n}\n\nexport interface SessionListEntry {\n name: string\n browser: string\n url: string\n status: string\n}\n\nfunction truncate(str: string, max = 80): string {\n return str.length <= max ? str : str.slice(0, max - 3) + '...';\n}\n\nexport function formatBrowserElement(ref: string, el: BrowserElementFormatInput): string {\n const tag = (el.role && el.role !== el.tagName ? el.role : el.tagName) + (el.type ? `[${el.type}]` : '');\n const desc = [el.name && `\"${truncate(el.name)}\"`, el.href && `-> ${truncate(el.href)}`].filter(Boolean).join(' ');\n return [ref.padEnd(4), tag, desc, el.selector].filter(Boolean).join(' ');\n}\n\nexport function formatMobileElement(ref: string, el: MobileElementFormatInput): string {\n const selector = el.accessibilityId ? `[accessibility-id: ${el.accessibilityId}]`\n : el.resourceId ? `[resource-id: ${el.resourceId}]`\n : truncate(el.selector);\n const parts = [ref.padEnd(4), el.tagName.padEnd(28), el.text && `\"${truncate(el.text)}\"`, selector];\n return parts.filter(Boolean).join(' ');\n}\n\nexport function formatSessionList(entries: SessionListEntry[]): string {\n if (entries.length === 0) return 'No active sessions.';\n\n const cols = (['name', 'browser', 'url', 'status'] as const).map((key) => ({\n key,\n header: key.toUpperCase(),\n width: Math.max(key.length, ...entries.map((e) => e[key].length)),\n }));\n\n const row = (e: SessionListEntry) => cols.map((c) => e[c.key].padEnd(c.width)).join(' ');\n const header = cols.map((c) => c.header.padEnd(c.width)).join(' ');\n\n return [header, ...entries.map(row)].join('\\n');\n}\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, getRefsPath, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = 'click <ref>';\nexport const desc = 'Click an element by snapshot reference (e.g., e1)';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1, a3)',\n });\n};\n\ninterface ClickArgs {\n ref: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ClickArgs>(async (argv: ArgumentsCamelCase<ClickArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n await browser.$(result.selector).click();\n console.log(`Clicked ${refKey} (${result.ref.selector})`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error clicking ${refKey}: ${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = ['type <ref> <text>', 'fill <ref> <text>'];\nexport const desc = 'Clear and type text into an input element by snapshot reference';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1)',\n })\n .positional('text', {\n type: 'string',\n describe: 'Text to type',\n });\n};\n\ninterface FillArgs {\n ref: string\n text: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<FillArgs>(async (argv: ArgumentsCamelCase<FillArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n const element = await browser.$(result.selector);\n await element.clearValue();\n await element.addValue(argv.text as string);\n console.log(`Filled ${refKey} with \"${argv.text}\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error: ${refKey} not found on page — the page may have changed. Run wdiox snapshot to refresh.\\n${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, withSession } from '../session.js';\n\nexport const command = 'screenshot [path]';\nexport const desc = 'Save a screenshot of the current page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('path', {\n type: 'string',\n describe: 'File path to save screenshot (default: ./screenshot-<timestamp>.png)',\n });\n};\n\ninterface ScreenshotArgs {\n path?: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ScreenshotArgs>(async (argv: ArgumentsCamelCase<ScreenshotArgs>, meta) => {\n const browser = await attach(buildAttachOptions(meta));\n\n const filePath = (argv.path as string) ||\n `screenshot-${new Date().toISOString().replace(/[:.]/g, '-')}.png`;\n\n await browser.saveScreenshot(filePath);\n console.log(`Screenshot saved to ${filePath}`);\n});\n","import type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { listSessions, getSessionDir, deleteSessionFiles, buildAttachOptions } from '../session.js';\nimport { formatSessionList, type SessionListEntry } from '../format.js';\n\nexport const command = ['session-list', 'ls'];\nexport const desc = 'List all active sessions';\n\ninterface SessionListArgs {\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<SessionListArgs>) {\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n const sessions = await listSessions(sessionsDir);\n\n if (sessions.length === 0) {\n console.log('No active sessions.');\n return;\n }\n\n const entries: SessionListEntry[] = [];\n\n for (const session of sessions) {\n let status = 'active';\n try {\n const browser = await attach(buildAttachOptions(session.metadata));\n await browser.getPageSource();\n } catch {\n status = 'expired';\n await deleteSessionFiles(session.name, sessionsDir);\n }\n\n const caps = session.metadata.capabilities;\n const browserName = (caps.browserName as string)\n || (caps.platformName as string)\n || 'unknown';\n entries.push({\n name: session.name,\n browser: browserName,\n url: session.metadata.url,\n status,\n });\n }\n\n console.log(formatSessionList(entries));\n}\n"],"mappings":"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","names":["handler","yargs","command","desc","handler","attach","command","desc","handler","attach","builder","command","desc","handler","attach","fs","isEnoent","desc","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","command","desc","handler","attach","command","desc","handler","attach"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/open.ts","../src/session.ts","../src/commands/close.ts","../src/commands/snapshot.ts","../src/refs.ts","../src/format.ts","../src/commands/click.ts","../src/commands/type.ts","../src/commands/screenshot.ts","../src/commands/session-list.ts"],"sourcesContent":["import yargs from 'yargs';\r\nimport type { CommandModule } from 'yargs';\r\nimport { hideBin } from 'yargs/helpers';\r\n\r\nimport * as openCmd from './commands/open.js';\r\nimport * as closeCmd from './commands/close.js';\r\nimport * as snapshotCmd from './commands/snapshot.js';\r\nimport * as clickCmd from './commands/click.js';\r\nimport * as fillCmd from './commands/type';\r\nimport * as screenshotCmd from './commands/screenshot.js';\r\nimport * as sessionListCmd from './commands/session-list.js';\r\n\r\nconst commands = [\r\n openCmd, closeCmd, snapshotCmd, clickCmd,\r\n fillCmd, screenshotCmd, sessionListCmd,\r\n] as unknown as CommandModule[];\r\n\r\nexport async function run() {\r\n\r\n // webdriverio's attach() can spawn async BiDi connections that fail after\r\n // the function returns (e.g. stale session). Suppress these so the CLI\r\n // doesn't crash during close/reconnect of dead sessions.\r\n process.on('unhandledRejection', () => {});\r\n\r\n let cli = yargs(hideBin(process.argv))\r\n .scriptName('wdiox')\r\n .usage('$0 <command> [options]')\r\n .option('session', {\r\n alias: 's',\r\n type: 'string',\r\n default: process.env.WDIO_SESSION || 'default',\r\n describe: 'Session name',\r\n });\r\n\r\n for (const cmd of commands) {\r\n cli = cli.command(cmd);\r\n }\r\n\r\n await cli\r\n .demandCommand(1, 'You need to specify a command. Try: wdiox open <url>')\r\n .strict()\r\n .help()\r\n .version()\r\n .parse();\r\n\r\n // webdriverio keeps HTTP agents alive — force clean exit after command completes\r\n process.exit(0);\r\n}\r\n","import readline from 'node:readline/promises';\nimport type { ArgumentsCamelCase, Argv } from 'yargs';\nimport type { Capabilities } from '@wdio/types';\nimport { attach, remote } from 'webdriverio';\n\nimport { writeSession, readSession, getSessionDir, buildAttachOptions, deleteSessionFiles } from '../session.js';\n\nexport const command = ['open [url]', 'new [url]', 'start [url]'];\nexport const desc = 'Open a browser or Appium session';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('url', {\n type: 'string',\n describe: 'URL to navigate to',\n })\n .option('browser', {\n alias: 'b',\n type: 'string',\n default: 'chrome',\n describe: 'Browser to use (chrome, firefox, edge, safari)',\n })\n .option('app', {\n type: 'string',\n describe: 'Path to mobile app (.apk, .ipa, .app)',\n })\n .option('device', {\n alias: 'd',\n type: 'string',\n describe: 'Device name for mobile testing',\n })\n .option('platform', {\n type: 'string',\n describe: 'Mobile platform (android, ios)',\n })\n .option('path', {\n type: 'string',\n describe: 'WebDriver/Appium server session path (default: /)',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n describe: 'WebDriver/Appium server port (default: 4723)',\n })\n .option('hostname', {\n type: 'string',\n describe: 'WebDriver/Appium server hostname (default: localhost)',\n })\n .option('grant-permissions', {\n type: 'boolean',\n default: true,\n describe: 'Auto-grant app permissions (Appium only)',\n })\n .option('accept-alert', {\n type: 'boolean',\n default: true,\n describe: 'Auto-accept native alerts (Appium only)',\n })\n .option('auto-dismiss', {\n type: 'boolean',\n default: false,\n describe: 'Auto-dismiss native alerts (Appium only)',\n });\n};\n\ninterface OpenArgs {\n url?: string\n browser: string\n session: string\n app?: string\n device?: string\n platform?: string\n port?: number\n hostname?: string\n grantPermissions: boolean\n acceptAlert: boolean\n autoDismiss: boolean\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<OpenArgs>) {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const existing = await readSession(sessionName, sessionsDir);\n if (existing) {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const context = existing.url || (existing.capabilities['appium:app'] as string) || '';\n const answer = await rl.question(`Session [${sessionName}] is already active${context ? ` (${context})` : ''}.\\nClose it and start a new one? (y/N) `);\n rl.close();\n\n if (answer.trim().toLowerCase() !== 'y') {\n return;\n }\n\n try {\n const old = await attach(buildAttachOptions(existing));\n await old.deleteSession();\n } catch {\n // Already dead\n }\n await deleteSessionFiles(sessionName, sessionsDir);\n }\n\n const capabilities: Record<string, unknown> = {};\n\n const isMobile = !!argv.app;\n if (isMobile) {\n const platform = argv.platform ?? (argv.app?.endsWith('.apk') ? 'android' : 'ios');\n\n capabilities.platformName = platform === 'ios' ? 'iOS' : 'Android';\n capabilities['appium:app'] = argv.app;\n capabilities['appium:deviceName'] = argv.device ?? 'emulator-5554';\n capabilities['appium:newCommandTimeout'] = 300;\n capabilities['appium:automationName'] = platform === 'ios' ? 'XCUITest' : 'UiAutomator2';\n capabilities['appium:autoGrantPermissions'] = argv.grantPermissions;\n capabilities['appium:autoAcceptAlerts'] = argv.acceptAlert;\n capabilities['appium:autoDismissAlerts'] = argv.autoDismiss;\n } else {\n capabilities.browserName = argv.browser;\n capabilities['wdio:chromedriverOptions'] = { spawnOpts: { detached: true } };\n }\n\n const remoteOpts: Record<string, unknown> = { capabilities, logLevel: process.env.WDIO_LOG_LEVEL ?? 'error' };\n // For mobile / Appium, explicit connection is required\n if (argv.hostname || argv.port || isMobile) {\n remoteOpts.hostname = argv.hostname ?? 'localhost';\n remoteOpts.port = argv.port ?? (isMobile ? 4723 : 4444);\n remoteOpts.path = argv.path ?? '/';\n }\n\n const browser = await remote(remoteOpts as unknown as Capabilities.WebdriverIOConfig);\n\n if (argv.url) {\n await browser.url(argv.url);\n }\n\n const opts = browser.options as Capabilities.WebdriverIOConfig;\n await writeSession(sessionName, {\n sessionId: browser.sessionId,\n hostname: opts?.hostname || 'localhost',\n port: opts?.port || 4444,\n capabilities: { ...capabilities, ...browser.capabilities as Record<string, unknown> },\n created: new Date().toISOString(),\n url: argv.url || '',\n }, sessionsDir);\n\n console.log(`Session \"${sessionName}\" started.`);\n}\n","import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { AttachOptions } from 'webdriverio';\nimport type { ArgumentsCamelCase } from 'yargs';\n\nexport interface SessionMetadata {\n sessionId: string\n hostname: string\n port: number\n capabilities: Record<string, unknown>\n created: string\n url: string\n}\n\nexport interface SessionEntry {\n name: string\n metadata: SessionMetadata\n}\n\nconst DEFAULT_SESSION_DIR = path.join(os.homedir(), '.wdio-x', 'sessions');\n\nfunction isEnoent(err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Build attach options from session metadata for use with webdriverio's `attach()`.\n */\nexport function buildAttachOptions(meta: SessionMetadata): AttachOptions {\n return {\n sessionId: meta.sessionId,\n capabilities: meta.capabilities as WebdriverIO.Capabilities,\n options: {\n hostname: meta.hostname,\n port: meta.port,\n logLevel: process.env.WDIO_LOG_LEVEL ?? 'error',\n },\n } as AttachOptions;\n}\n\n/**\n * Returns the session directory path. Defaults to ~/.wdio-x/sessions/.\n */\nexport function getSessionDir (baseDir?: string): string {\n return baseDir ?? DEFAULT_SESSION_DIR;\n}\n\n/**\n * Returns the file path for a session's metadata JSON file.\n */\nexport function getSessionPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.json`);\n}\n\n/**\n * Returns the file path for a session's refs JSON file.\n */\nexport function getRefsPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.refs.json`);\n}\n\n/**\n * Writes session metadata to disk, creating the directory if needed.\n */\nexport async function writeSession (\n name: string,\n metadata: SessionMetadata,\n baseDir?: string,\n): Promise<void> {\n const dir = getSessionDir(baseDir);\n await fs.mkdir(dir, { recursive: true });\n const filePath = getSessionPath(name, baseDir);\n await fs.writeFile(filePath, JSON.stringify(metadata, null, 2));\n}\n\n/**\n * Reads session metadata from disk. Returns null if the session file does not exist.\n */\nexport async function readSession (\n name: string,\n baseDir?: string,\n): Promise<SessionMetadata | null> {\n const filePath = getSessionPath(name, baseDir);\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as SessionMetadata;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Deletes both the .json and .refs.json files for a session.\n * Does not throw if the files do not exist.\n */\nexport async function deleteSessionFiles (\n name: string,\n baseDir?: string,\n): Promise<void> {\n const sessionPath = getSessionPath(name, baseDir);\n const refsPath = getRefsPath(name, baseDir);\n await Promise.all([\n fs.rm(sessionPath, { force: true }),\n fs.rm(refsPath, { force: true }),\n ]);\n}\n\n/**\n * Lists all sessions in the session directory.\n * Only considers .json files (excludes .refs.json).\n * Returns an empty array if the directory does not exist.\n */\nexport async function listSessions (baseDir?: string): Promise<SessionEntry[]> {\n const dir = getSessionDir(baseDir);\n let files: string[];\n try {\n files = await fs.readdir(dir);\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return [];\n }\n throw err;\n }\n\n const sessionFiles = files.filter(\n (f) => f.endsWith('.json') && !f.endsWith('.refs.json'),\n );\n\n return await Promise.all(\n sessionFiles.map(async (f) => {\n const name = f.replace(/\\.json$/, '');\n const metadata = await readSession(name, baseDir);\n return { name, metadata: metadata! };\n }),\n );\n}\n\ninterface SessionArgs {\n session: string\n _sessionsDir?: string\n}\n\n/**\n * Wraps a command handler that requires an active session.\n * Reads the session from disk and exits early with an error if not found.\n */\nexport function withSession<T extends SessionArgs>(\n fn: (argv: ArgumentsCamelCase<T>, meta: SessionMetadata, sessionsDir: string) => Promise<void>,\n): (argv: ArgumentsCamelCase<T>) => Promise<void> {\n return async function handler(argv: ArgumentsCamelCase<T>): Promise<void> {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const meta = await readSession(sessionName, sessionsDir);\n if (!meta) {\n console.error(`Error: No active session [${sessionName}]. Run wdiox open <url> first.`);\n return;\n }\n\n await fn(argv, meta, sessionsDir);\n };\n}\n","import os from 'node:os';\nimport { execSync } from 'node:child_process';\n\nimport type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { deleteSessionFiles, buildAttachOptions, withSession } from '../session.js';\n\nexport const command = ['close', 'stop'];\nexport const desc = 'Close the current session';\n\ninterface CloseArgs {\n session: string\n _sessionsDir?: string\n}\n\nfunction killProcess(pid: number): void {\n const platform = os.platform();\n try {\n if (platform === 'win32') {\n execSync(`taskkill /F /PID ${pid}`, { stdio: 'ignore' });\n } else {\n execSync(`kill -9 ${pid}`, { stdio: 'ignore' });\n }\n } catch {\n // Process may already be dead\n }\n}\n\nexport const handler = withSession<CloseArgs>(async (argv: ArgumentsCamelCase<CloseArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const caps = meta.capabilities as Record<string, unknown>;\n const browserPid = typeof caps['goog:processID'] === 'number' ? caps['goog:processID'] : undefined;\n const driverPid = typeof caps['wdio:driverPID'] === 'number' ? caps['wdio:driverPID'] : undefined;\n\n try {\n const browser = await attach(buildAttachOptions(meta));\n await browser.deleteSession();\n } catch {\n if (browserPid) {\n killProcess(browserPid);\n }\n if (driverPid && driverPid !== browserPid) {\n killProcess(driverPid);\n }\n }\n\n await deleteSessionFiles(sessionName, sessionsDir);\n console.log(`Session \"${sessionName}\" closed.`);\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\r\nimport { attach } from 'webdriverio';\r\n\r\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\r\nimport { writeRefs, type RefMap } from '../refs.js';\r\nimport { getInteractableBrowserElements, getMobileVisibleElements } from '@wdio/mcp/snapshot';\r\nimport {\r\n formatBrowserElement,\r\n formatMobileElement,\r\n} from '../format.js';\r\n\r\nexport const command = 'snapshot';\r\nexport const desc = 'Capture interactive elements on the page or screen';\r\n\r\nexport const builder = (yargs: Argv) => {\r\n return yargs\r\n .option('visible', {\r\n type: 'boolean',\r\n default: true,\r\n describe: 'Only show elements in viewport',\r\n });\r\n};\r\n\r\ninterface SnapshotArgs {\r\n session: string\r\n visible: boolean\r\n _sessionsDir?: string\r\n}\r\n\r\nexport const handler = withSession<SnapshotArgs>(async (argv: ArgumentsCamelCase<SnapshotArgs>, meta, sessionsDir) => {\r\n const sessionName = argv.session as string;\r\n const browser = await attach(buildAttachOptions(meta));\r\n\r\n const isMobile = browser.isAndroid || browser.isIOS;\r\n const refs: RefMap = {};\r\n\r\n if (isMobile) {\r\n const platform = browser.isIOS ? 'ios' : 'android';\r\n const elements = await getMobileVisibleElements(browser, platform);\r\n const filtered = argv.visible\r\n ? elements.filter(el => el.isInViewport)\r\n : elements;\r\n\r\n const appName = (meta.capabilities['appium:app'] as string) || 'unknown';\r\n console.log(`\\n App: ${appName}\\n`);\r\n\r\n filtered.forEach((el, i) => {\r\n const ref = `e${i + 1}`;\r\n console.log(formatMobileElement(ref, {\r\n tagName: el.tagName,\r\n text: el.text,\r\n selector: el.selector,\r\n accessibilityId: el.accessibilityId,\r\n resourceId: el.resourceId,\r\n }));\r\n refs[ref] = {\r\n selector: el.selector,\r\n tagName: el.tagName,\r\n text: el.text,\r\n };\r\n });\r\n\r\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\r\n } else {\r\n const elements = await getInteractableBrowserElements(browser);\r\n const filtered = argv.visible\r\n ? elements.filter(el => el.isInViewport)\r\n : elements;\r\n\r\n const currentUrl = await browser.getUrl();\r\n console.log(`\\n Page: ${currentUrl}\\n`);\r\n\r\n filtered.forEach((el, i) => {\r\n const ref = `e${i + 1}`;\r\n console.log(formatBrowserElement(ref, el));\r\n refs[ref] = {\r\n selector: el.selector,\r\n tagName: el.tagName,\r\n text: el.name || '',\r\n };\r\n });\r\n\r\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\r\n }\r\n\r\n await writeRefs(getRefsPath(sessionName, sessionsDir), refs);\r\n});\r\n","import fs from 'node:fs/promises';\r\n\r\nexport interface RefEntry {\r\n selector?: string\r\n tagName: string\r\n text?: string\r\n placeholder?: string\r\n [key: string]: unknown\r\n}\r\n\r\nexport type RefMap = Record<string, RefEntry>;\r\n\r\nfunction isEnoent (err: unknown): boolean {\r\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\r\n}\r\n\r\n/**\r\n * Writes a ref map to disk as JSON.\r\n */\r\nexport async function writeRefs (refsPath: string, refs: RefMap): Promise<void> {\r\n await fs.writeFile(refsPath, JSON.stringify(refs, null, 2), 'utf-8');\r\n}\r\n\r\n/**\r\n * Reads a ref map from disk. Returns null if the file doesn't exist.\r\n */\r\nexport async function readRefs (refsPath: string): Promise<RefMap | null> {\r\n try {\r\n const content = await fs.readFile(refsPath, 'utf-8');\r\n return JSON.parse(content) as RefMap;\r\n } catch (err: unknown) {\r\n if (isEnoent(err)) {\r\n return null;\r\n }\r\n throw err;\r\n }\r\n}\r\n\r\n/**\r\n * Look up a ref by key: reads refs file, finds the entry, resolves its selector.\r\n * Logs appropriate error messages and returns null on failure.\r\n */\r\nexport async function lookupRef (\r\n refsPath: string,\r\n refKey: string,\r\n): Promise<{ ref: RefEntry; selector: string } | null> {\r\n const refs = await readRefs(refsPath);\r\n if (!refs) {\r\n console.error('Error: No snapshot taken. Run wdiox snapshot first.');\r\n return null;\r\n }\r\n\r\n const ref = refs[refKey];\r\n if (!ref) {\r\n const available = Object.keys(refs);\r\n const range = available.length > 0\r\n ? `Available: ${available[0]}-${available[available.length - 1]}`\r\n : 'No refs available';\r\n console.error(`Error: ${refKey} not found in snapshot. ${range}`);\r\n return null;\r\n }\r\n\r\n if (!ref.selector) {\r\n console.error(`Error: Could not resolve selector for ${refKey}`);\r\n return null;\r\n }\r\n\r\n return { ref, selector: ref.selector };\r\n}\r\n","export interface BrowserElementFormatInput {\r\n tagName: string\r\n role?: string\r\n type?: string\r\n name?: string\r\n href?: string\r\n selector: string\r\n}\r\n\r\nexport interface MobileElementFormatInput {\r\n tagName: string\r\n text?: string\r\n selector: string\r\n accessibilityId?: string\r\n resourceId?: string\r\n}\r\n\r\nexport interface SessionListEntry {\r\n name: string\r\n browser: string\r\n url: string\r\n status: string\r\n}\r\n\r\nfunction truncate(str: string, max = 80): string {\r\n return str.length <= max ? str : str.slice(0, max - 3) + '...';\r\n}\r\n\r\nexport function formatBrowserElement(ref: string, el: BrowserElementFormatInput): string {\r\n const tag = (el.role && el.role !== el.tagName ? el.role : el.tagName) + (el.type ? `[${el.type}]` : '');\r\n const desc = [el.name && `\"${truncate(el.name)}\"`, el.href && `-> ${truncate(el.href)}`].filter(Boolean).join(' ');\r\n return [ref.padEnd(4), tag, desc, el.selector].filter(Boolean).join(' ');\r\n}\r\n\r\nexport function formatMobileElement(ref: string, el: MobileElementFormatInput): string {\r\n const selector = el.accessibilityId ? `[accessibility-id: ${el.accessibilityId}]`\r\n : el.resourceId ? `[resource-id: ${el.resourceId}]`\r\n : truncate(el.selector);\r\n const parts = [ref.padEnd(4), el.tagName.padEnd(28), el.text && `\"${truncate(el.text)}\"`, selector];\r\n return parts.filter(Boolean).join(' ');\r\n}\r\n\r\nexport function formatSessionList(entries: SessionListEntry[]): string {\r\n if (entries.length === 0) return 'No active sessions.';\r\n\r\n const cols = (['name', 'browser', 'url', 'status'] as const).map((key) => ({\r\n key,\r\n header: key.toUpperCase(),\r\n width: Math.max(key.length, ...entries.map((e) => e[key].length)),\r\n }));\r\n\r\n const row = (e: SessionListEntry) => cols.map((c) => e[c.key].padEnd(c.width)).join(' ');\r\n const header = cols.map((c) => c.header.padEnd(c.width)).join(' ');\r\n\r\n return [header, ...entries.map(row)].join('\\n');\r\n}\r\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, getRefsPath, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = 'click <ref>';\nexport const desc = 'Click an element by snapshot reference (e.g., e1)';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1, a3)',\n });\n};\n\ninterface ClickArgs {\n ref: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ClickArgs>(async (argv: ArgumentsCamelCase<ClickArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n await browser.$(result.selector).click();\n console.log(`Clicked ${refKey} (${result.ref.selector})`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error clicking ${refKey}: ${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = ['type <ref> <text>', 'fill <ref> <text>'];\nexport const desc = 'Clear and type text into an input element by snapshot reference';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1)',\n })\n .positional('text', {\n type: 'string',\n describe: 'Text to type',\n });\n};\n\ninterface FillArgs {\n ref: string\n text: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<FillArgs>(async (argv: ArgumentsCamelCase<FillArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n const element = await browser.$(result.selector);\n await element.clearValue();\n await element.addValue(argv.text as string);\n console.log(`Filled ${refKey} with \"${argv.text}\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error: ${refKey} not found on page — the page may have changed. Run wdiox snapshot to refresh.\\n${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, withSession } from '../session.js';\n\nexport const command = 'screenshot [path]';\nexport const desc = 'Save a screenshot of the current page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('path', {\n type: 'string',\n describe: 'File path to save screenshot (default: ./screenshot-<timestamp>.png)',\n });\n};\n\ninterface ScreenshotArgs {\n path?: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ScreenshotArgs>(async (argv: ArgumentsCamelCase<ScreenshotArgs>, meta) => {\n const browser = await attach(buildAttachOptions(meta));\n\n const filePath = (argv.path as string) ||\n `screenshot-${new Date().toISOString().replace(/[:.]/g, '-')}.png`;\n\n await browser.saveScreenshot(filePath);\n console.log(`Screenshot saved to ${filePath}`);\n});\n","import type { ArgumentsCamelCase } from 'yargs';\r\nimport { attach } from 'webdriverio';\r\n\r\nimport { listSessions, getSessionDir, deleteSessionFiles, buildAttachOptions } from '../session.js';\r\nimport { formatSessionList, type SessionListEntry } from '../format.js';\r\n\r\nexport const command = ['session-list', 'ls'];\r\nexport const desc = 'List all active sessions';\r\n\r\ninterface SessionListArgs {\r\n _sessionsDir?: string\r\n}\r\n\r\nexport async function handler (argv: ArgumentsCamelCase<SessionListArgs>) {\r\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\r\n const sessions = await listSessions(sessionsDir);\r\n\r\n if (sessions.length === 0) {\r\n console.log('No active sessions.');\r\n return;\r\n }\r\n\r\n const entries: SessionListEntry[] = [];\r\n\r\n for (const session of sessions) {\r\n let status = 'active';\r\n try {\r\n const browser = await attach(buildAttachOptions(session.metadata));\r\n await browser.getPageSource();\r\n } catch {\r\n status = 'expired';\r\n await deleteSessionFiles(session.name, sessionsDir);\r\n }\r\n\r\n const caps = session.metadata.capabilities;\r\n const browserName = (caps.browserName as string)\r\n || (caps.platformName as string)\r\n || 'unknown';\r\n entries.push({\r\n name: session.name,\r\n browser: browserName,\r\n url: session.metadata.url,\r\n status,\r\n });\r\n }\r\n\r\n console.log(formatSessionList(entries));\r\n}\r\n"],"mappings":"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","names":["handler","yargs","command","desc","handler","os","attach","command","desc","os","handler","attach","builder","command","desc","handler","attach","fs","isEnoent","desc","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","command","desc","handler","attach","command","desc","handler","attach"]}
|
package/package.json
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "webdriverio-execute",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"repository": {
|
|
5
|
-
"type": "git",
|
|
6
|
-
"url": "git+https://github.com/Winify/webdriverio-execute.git"
|
|
7
|
-
},
|
|
8
|
-
"description": "Interactive browser and app CLI for developers using WebdriverIO",
|
|
9
|
-
"author": "Vince Graics <wince17@gmail.com>",
|
|
10
|
-
"homepage": "https://github.com/Winify/webdriverio-execute",
|
|
11
|
-
"license": "MIT",
|
|
12
|
-
"bin": {
|
|
13
|
-
"wdiox": "./bin/wdiox.js"
|
|
14
|
-
},
|
|
15
|
-
"engines": {
|
|
16
|
-
"node": ">=18.20.0"
|
|
17
|
-
},
|
|
18
|
-
"keywords": [
|
|
19
|
-
"webdriver",
|
|
20
|
-
"webdriverio",
|
|
21
|
-
"wdio",
|
|
22
|
-
"cli",
|
|
23
|
-
"browser",
|
|
24
|
-
"automation"
|
|
25
|
-
],
|
|
26
|
-
"bugs": {
|
|
27
|
-
"url": "https://github.com/Winify/webdriverio-execute/issues"
|
|
28
|
-
},
|
|
29
|
-
"type": "module",
|
|
30
|
-
"files": [
|
|
31
|
-
"bin",
|
|
32
|
-
"build",
|
|
33
|
-
"README.md"
|
|
34
|
-
],
|
|
35
|
-
"types": "./dist/index.d.ts",
|
|
36
|
-
"scripts": {
|
|
37
|
-
"bundle": "rimraf build && tsup",
|
|
38
|
-
"postbundle": "pnpm pack",
|
|
39
|
-
"dev": "tsup --watch",
|
|
40
|
-
"test": "vitest run",
|
|
41
|
-
"typecheck": "tsc --noEmit",
|
|
42
|
-
"lint": "eslint --fix && pnpm run typecheck",
|
|
43
|
-
"link": "pnpm run bundle && pnpm i && pnpm link --global"
|
|
44
|
-
},
|
|
45
|
-
"dependencies": {
|
|
46
|
-
"@wdio/mcp": "^2.3.0",
|
|
47
|
-
"@wdio/types": "^9.24.0",
|
|
48
|
-
"webdriverio": "^9.24.0",
|
|
49
|
-
"yargs": "^17.7.2"
|
|
50
|
-
},
|
|
51
|
-
"devDependencies": {
|
|
52
|
-
"@types/node": "^24.10.13",
|
|
53
|
-
"@types/yargs": "^17.0.24",
|
|
54
|
-
"@wdio/eslint": "^0.1.3",
|
|
55
|
-
"eslint": "^9.39.2",
|
|
56
|
-
"husky": "^9.1.7",
|
|
57
|
-
"lint-staged": "^16.2.7",
|
|
58
|
-
"release-it": "^19.2.4",
|
|
59
|
-
"rimraf": "^6.1.2",
|
|
60
|
-
"tsup": "^8.0.0",
|
|
61
|
-
"typescript": "^5.0.0",
|
|
62
|
-
"vitest": "^2.0.0"
|
|
63
|
-
},
|
|
64
|
-
"publishConfig": {
|
|
65
|
-
"access": "public"
|
|
66
|
-
},
|
|
67
|
-
"packageManager": "pnpm@10.26.2"
|
|
68
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "webdriverio-execute",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/Winify/webdriverio-execute.git"
|
|
7
|
+
},
|
|
8
|
+
"description": "Interactive browser and app CLI for developers using WebdriverIO",
|
|
9
|
+
"author": "Vince Graics <wince17@gmail.com>",
|
|
10
|
+
"homepage": "https://github.com/Winify/webdriverio-execute",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"bin": {
|
|
13
|
+
"wdiox": "./bin/wdiox.js"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18.20.0"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"webdriver",
|
|
20
|
+
"webdriverio",
|
|
21
|
+
"wdio",
|
|
22
|
+
"cli",
|
|
23
|
+
"browser",
|
|
24
|
+
"automation"
|
|
25
|
+
],
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/Winify/webdriverio-execute/issues"
|
|
28
|
+
},
|
|
29
|
+
"type": "module",
|
|
30
|
+
"files": [
|
|
31
|
+
"bin",
|
|
32
|
+
"build",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"scripts": {
|
|
37
|
+
"bundle": "rimraf build && tsup",
|
|
38
|
+
"postbundle": "pnpm pack",
|
|
39
|
+
"dev": "tsup --watch",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"typecheck": "tsc --noEmit",
|
|
42
|
+
"lint": "eslint --fix && pnpm run typecheck",
|
|
43
|
+
"link": "pnpm run bundle && pnpm i && pnpm link --global"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@wdio/mcp": "^2.3.0",
|
|
47
|
+
"@wdio/types": "^9.24.0",
|
|
48
|
+
"webdriverio": "^9.24.0",
|
|
49
|
+
"yargs": "^17.7.2"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^24.10.13",
|
|
53
|
+
"@types/yargs": "^17.0.24",
|
|
54
|
+
"@wdio/eslint": "^0.1.3",
|
|
55
|
+
"eslint": "^9.39.2",
|
|
56
|
+
"husky": "^9.1.7",
|
|
57
|
+
"lint-staged": "^16.2.7",
|
|
58
|
+
"release-it": "^19.2.4",
|
|
59
|
+
"rimraf": "^6.1.2",
|
|
60
|
+
"tsup": "^8.0.0",
|
|
61
|
+
"typescript": "^5.0.0",
|
|
62
|
+
"vitest": "^2.0.0"
|
|
63
|
+
},
|
|
64
|
+
"publishConfig": {
|
|
65
|
+
"access": "public"
|
|
66
|
+
},
|
|
67
|
+
"packageManager": "pnpm@10.26.2"
|
|
68
|
+
}
|