@houwert/conductor 0.3.0 → 0.4.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/dist/commands/cheat-sheet.js +2 -0
- package/dist/commands/clear-state.js +27 -0
- package/dist/commands/list-apps.js +1 -1
- package/dist/commands/uninstall-app.js +31 -0
- package/dist/drivers/android.js +4 -0
- package/dist/drivers/flow-runner.js +15 -0
- package/dist/drivers/ios.js +5 -0
- package/dist/index.js +14 -0
- package/drivers/ios/conductor-driver-ios.zip +0 -0
- package/drivers/ios/conductor-driver-iosUITests-Runner.zip +0 -0
- package/drivers/tvos/conductor-driver-tvos.zip +0 -0
- package/drivers/tvos/conductor-driver-tvosUITests-Runner.zip +0 -0
- package/package.json +1 -1
- package/skills/conductor/SKILL.md +22 -0
- package/skills/conductor/references/flow-syntax.md +2 -0
|
@@ -39,6 +39,8 @@ APP CONTROL
|
|
|
39
39
|
--clear-keychain Wipe keychain before launching
|
|
40
40
|
--argument key=value Set launch argument (repeatable)
|
|
41
41
|
stop-app [<appId>] Stop app (uses session appId if omitted)
|
|
42
|
+
clear-state [<appId>] Clear app data/state (uses session appId if omitted)
|
|
43
|
+
uninstall-app <appId> Uninstall app from device
|
|
42
44
|
|
|
43
45
|
INTERACTIONS
|
|
44
46
|
tap <element> Tap element by text
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HELP = void 0;
|
|
4
|
+
exports.clearState = clearState;
|
|
5
|
+
exports.HELP = ` clear-state [<appId>] Clear app data/state`;
|
|
6
|
+
const runner_js_1 = require("../runner.js");
|
|
7
|
+
const session_js_1 = require("../session.js");
|
|
8
|
+
const output_js_1 = require("../output.js");
|
|
9
|
+
async function clearState(appId, opts = {}, sessionName = 'default') {
|
|
10
|
+
const session = await (0, session_js_1.getSession)(sessionName);
|
|
11
|
+
const resolvedAppId = appId ?? session.appId;
|
|
12
|
+
if (!resolvedAppId) {
|
|
13
|
+
(0, output_js_1.printError)('clear-state: no appId provided and no active session. Run launch-app first.', opts);
|
|
14
|
+
return 1;
|
|
15
|
+
}
|
|
16
|
+
const result = await (0, runner_js_1.runDirect)(async (driver) => {
|
|
17
|
+
await driver.clearAppState(resolvedAppId);
|
|
18
|
+
}, sessionName);
|
|
19
|
+
if (result.success) {
|
|
20
|
+
(0, output_js_1.printSuccess)(`clear-state "${resolvedAppId}" — done`, opts);
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
(0, output_js_1.printError)(`clear-state "${resolvedAppId}" — failed\n${result.stderr}`, opts);
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -21,7 +21,7 @@ async function listApps(opts = {}, sessionName = 'default') {
|
|
|
21
21
|
}
|
|
22
22
|
const platform = await (0, bootstrap_js_1.detectPlatform)(deviceId);
|
|
23
23
|
let appIds;
|
|
24
|
-
if (platform === 'ios') {
|
|
24
|
+
if (platform === 'ios' || platform === 'tvos') {
|
|
25
25
|
const result = await (0, runner_js_1.spawnCommand)('bash', [
|
|
26
26
|
'-c',
|
|
27
27
|
`xcrun simctl listapps ${deviceId} | plutil -convert json - -o -`,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HELP = void 0;
|
|
4
|
+
exports.uninstallApp = uninstallApp;
|
|
5
|
+
exports.HELP = ` uninstall-app <appId> Uninstall app from device`;
|
|
6
|
+
const runner_js_1 = require("../runner.js");
|
|
7
|
+
const output_js_1 = require("../output.js");
|
|
8
|
+
const ios_js_1 = require("../drivers/ios.js");
|
|
9
|
+
const android_js_1 = require("../drivers/android.js");
|
|
10
|
+
async function uninstallApp(appId, opts = {}, sessionName = 'default') {
|
|
11
|
+
if (!appId) {
|
|
12
|
+
(0, output_js_1.printError)('uninstall-app requires <appId>', opts);
|
|
13
|
+
return 1;
|
|
14
|
+
}
|
|
15
|
+
const result = await (0, runner_js_1.runDirect)(async (driver) => {
|
|
16
|
+
if (driver instanceof ios_js_1.IOSDriver) {
|
|
17
|
+
await driver.uninstallApp(appId);
|
|
18
|
+
}
|
|
19
|
+
else if (driver instanceof android_js_1.AndroidDriver) {
|
|
20
|
+
await driver.uninstallApp(appId);
|
|
21
|
+
}
|
|
22
|
+
}, sessionName);
|
|
23
|
+
if (result.success) {
|
|
24
|
+
(0, output_js_1.printSuccess)(`uninstall-app "${appId}" — done`, opts);
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
(0, output_js_1.printError)(`uninstall-app "${appId}" — failed\n${result.stderr}`, opts);
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
}
|
package/dist/drivers/android.js
CHANGED
|
@@ -208,6 +208,10 @@ class AndroidDriver {
|
|
|
208
208
|
async clearAppState(packageName) {
|
|
209
209
|
await this.adb(['shell', 'pm', 'clear', packageName]);
|
|
210
210
|
}
|
|
211
|
+
async uninstallApp(packageName) {
|
|
212
|
+
await this.adb(['shell', 'am', 'force-stop', packageName]).catch(() => { });
|
|
213
|
+
await this.adb(['uninstall', packageName]);
|
|
214
|
+
}
|
|
211
215
|
async clearKeychain() {
|
|
212
216
|
// No-op on Android — keychain is an iOS concept
|
|
213
217
|
}
|
|
@@ -987,6 +987,21 @@ async function executeCommandBody(key, val, driver, opts) {
|
|
|
987
987
|
await driver.clearKeychain();
|
|
988
988
|
break;
|
|
989
989
|
}
|
|
990
|
+
case 'uninstallApp': {
|
|
991
|
+
const appId = val == null || val === ''
|
|
992
|
+
? (opts.appId ??
|
|
993
|
+
(() => {
|
|
994
|
+
throw new Error('uninstallApp: no appId in command or flow header');
|
|
995
|
+
})())
|
|
996
|
+
: resolveAppId(val, 'uninstallApp');
|
|
997
|
+
if (driver instanceof ios_js_1.IOSDriver) {
|
|
998
|
+
await driver.uninstallApp(appId);
|
|
999
|
+
}
|
|
1000
|
+
else {
|
|
1001
|
+
await driver.uninstallApp(appId);
|
|
1002
|
+
}
|
|
1003
|
+
break;
|
|
1004
|
+
}
|
|
990
1005
|
// ── Keys ───────────────────────────────────────────────────────────────
|
|
991
1006
|
case 'pressKey': {
|
|
992
1007
|
const keyName = val.toUpperCase();
|
package/dist/drivers/ios.js
CHANGED
|
@@ -168,6 +168,11 @@ class IOSDriver {
|
|
|
168
168
|
await promises_1.default.rm(tmpDir, { recursive: true, force: true }).catch(() => { });
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
+
async uninstallApp(bundleId) {
|
|
172
|
+
const deviceId = this.requireDeviceId();
|
|
173
|
+
await this.simctl(['terminate', deviceId, bundleId]).catch(() => { });
|
|
174
|
+
await this.simctl(['uninstall', deviceId, bundleId]);
|
|
175
|
+
}
|
|
171
176
|
async clearKeychain() {
|
|
172
177
|
const deviceId = this.requireDeviceId();
|
|
173
178
|
await this.simctl(['keychain', deviceId, 'reset']);
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,8 @@ const verbose_js_1 = require("./verbose.js");
|
|
|
9
9
|
const list_devices_js_1 = require("./commands/list-devices.js");
|
|
10
10
|
const launch_app_js_1 = require("./commands/launch-app.js");
|
|
11
11
|
const stop_app_js_1 = require("./commands/stop-app.js");
|
|
12
|
+
const clear_state_js_1 = require("./commands/clear-state.js");
|
|
13
|
+
const uninstall_app_js_1 = require("./commands/uninstall-app.js");
|
|
12
14
|
const tap_js_1 = require("./commands/tap.js");
|
|
13
15
|
const type_js_1 = require("./commands/type.js");
|
|
14
16
|
const back_js_1 = require("./commands/back.js");
|
|
@@ -48,6 +50,8 @@ const COMMAND_HELP = {
|
|
|
48
50
|
'copy-app': copy_app_js_1.HELP,
|
|
49
51
|
'launch-app': launch_app_js_1.HELP,
|
|
50
52
|
'stop-app': stop_app_js_1.HELP,
|
|
53
|
+
'clear-state': clear_state_js_1.HELP,
|
|
54
|
+
'uninstall-app': uninstall_app_js_1.HELP,
|
|
51
55
|
tap: tap_js_1.HELP,
|
|
52
56
|
type: type_js_1.HELP,
|
|
53
57
|
'erase-text': erase_text_js_1.HELP,
|
|
@@ -240,6 +244,16 @@ async function main() {
|
|
|
240
244
|
exitCode = await (0, stop_app_js_1.stopApp)(appId, opts, sessionName);
|
|
241
245
|
break;
|
|
242
246
|
}
|
|
247
|
+
case 'clear-state': {
|
|
248
|
+
const appId = rest[0];
|
|
249
|
+
exitCode = await (0, clear_state_js_1.clearState)(appId, opts, sessionName);
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
case 'uninstall-app': {
|
|
253
|
+
const appId = rest[0] ?? '';
|
|
254
|
+
exitCode = await (0, uninstall_app_js_1.uninstallApp)(appId, opts, sessionName);
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
243
257
|
case 'tap': {
|
|
244
258
|
const element = rest.join(' ');
|
|
245
259
|
exitCode = await (0, tap_js_1.tap)(element, opts, sessionName, {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -124,6 +124,28 @@ conductor stop-app com.example.myapp
|
|
|
124
124
|
|
|
125
125
|
---
|
|
126
126
|
|
|
127
|
+
### `clear-state [<appId>]`
|
|
128
|
+
|
|
129
|
+
Clear app data/state without relaunching. Uses the session `appId` if not specified. On iOS this terminates the app, preserves the .app bundle, uninstalls, and reinstalls (clearing all user data). On Android this runs `pm clear`.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
conductor clear-state
|
|
133
|
+
conductor clear-state com.example.myapp
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### `uninstall-app <appId>`
|
|
139
|
+
|
|
140
|
+
Uninstall an app from the device. The app ID is required.
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
conductor uninstall-app com.example.myapp
|
|
144
|
+
conductor uninstall-app com.example.myapp --device emulator-5554
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
127
149
|
### `tap <element>`
|
|
128
150
|
|
|
129
151
|
Tap a UI element by its text label or accessibility ID. **Try the most obvious text label or ID first** — e.g. `"Sign In"`, `"Submit"`, `"btn_login"`. Only run `inspect` to look up the exact identifier if your first attempt fails. **For icon-only buttons (no visible text label), always run `inspect` first** to find the accessibility ID before tapping.
|
|
@@ -26,6 +26,8 @@ appId: com.example.myapp
|
|
|
26
26
|
appId: com.other.app
|
|
27
27
|
- clearState # clear app data
|
|
28
28
|
- clearKeychain # clear keychain (iOS: full keychain; Android: account credentials)
|
|
29
|
+
- uninstallApp # uninstall app from device
|
|
30
|
+
- uninstallApp: com.other.app # uninstall a specific app
|
|
29
31
|
```
|
|
30
32
|
|
|
31
33
|
### Tapping
|