obsidian-integration-testing 8.1.2 → 8.2.1

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/README.md CHANGED
@@ -703,7 +703,7 @@ Runs tests against Obsidian Mobile on an Android emulator or real device via App
703
703
  adb shell appops set md.obsidian MANAGE_EXTERNAL_STORAGE allow
704
704
  ```
705
705
 
706
- 4. Install [Appium](https://appium.io/) and the [UiAutomator2 driver](https://github.com/appium/appium-uiautomator2-driver):
706
+ 4. (Optional) Install [Appium](https://appium.io/) and the [UiAutomator2 driver](https://github.com/appium/appium-uiautomator2-driver):
707
707
 
708
708
  ```bash
709
709
  npm install -g appium
@@ -712,7 +712,7 @@ Runs tests against Obsidian Mobile on an Android emulator or real device via App
712
712
 
713
713
  > [!NOTE]
714
714
  >
715
- > You do not need to start the Appium server manually — the test framework auto-starts it if it is not already running.
715
+ > This step is optional. You do not need to start the Appium server manually — the test framework auto-starts it if it is not already running, and by default it also **auto-installs** Appium (globally) and the UiAutomator2 driver when they are missing. Set `shouldAutoInstallAppiumDependencies: false` to manage the Appium toolchain yourself and skip the global install.
716
716
 
717
717
  5. Configure vitest:
718
718
 
@@ -735,18 +735,19 @@ Runs tests against Obsidian Mobile on an Android emulator or real device via App
735
735
 
736
736
  Besides the required `appiumUrl` and `avdName`, the transport accepts these optional knobs (all with sensible defaults):
737
737
 
738
- | Option | Purpose | Default |
739
- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------- |
740
- | `appId` | App package (Android) or bundle ID (iOS). | `'md.obsidian'` |
741
- | `appiumStartTimeoutInMilliseconds` | Max wait for the auto-started Appium server to become ready; only when the harness auto-starts it. | `180000` |
742
- | `deviceIdleTimeoutInMilliseconds` | Max wait after boot for a started emulator to go idle before the session; avoids inflated cold setup. 0 skips. | `60000` |
743
- | `isAppiumConsoleVisible` | Show the auto-started Appium server console window and live output. Hidden and quiet by default. | `false` |
744
- | `isEmulatorVisible` | Show the auto-started emulator window. Hidden (`-no-window`, headless) by default so it never steals focus. | `false` |
745
- | `layoutReadyTimeoutInMilliseconds` | Max wait for `app.workspace.layoutReady` after the vault (re)opens; raise on slow emulators. | `90000` |
746
- | `sessionConnectionRetryTimeoutInMilliseconds` | Max wait to establish the Appium session (UiAutomator2 install + app launch); the dominant startup cost. | `180000` |
747
- | `shouldAutoStartAppium` | Auto-start the Appium server when it is not already reachable. | `true` |
748
- | `vaultBasePath` | Base device path where Obsidian stores vaults. | `'/sdcard/Documents/'` |
749
- | `webviewTimeoutInMilliseconds` | Max wait for the WebView context after the Appium session starts. | `60000` |
738
+ | Option | Purpose | Default |
739
+ | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------- |
740
+ | `appId` | App package (Android) or bundle ID (iOS). | `'md.obsidian'` |
741
+ | `appiumStartTimeoutInMilliseconds` | Max wait for the auto-started Appium server to become ready; only when the harness auto-starts it. | `180000` |
742
+ | `deviceIdleTimeoutInMilliseconds` | Max wait after boot for a started emulator to go idle before the session; avoids inflated cold setup. 0 skips. | `60000` |
743
+ | `isAppiumConsoleVisible` | Show the auto-started Appium server console window and live output. Hidden and quiet by default. | `false` |
744
+ | `isEmulatorVisible` | Show the auto-started emulator window. Hidden (`-no-window`, headless) by default so it never steals focus. | `false` |
745
+ | `layoutReadyTimeoutInMilliseconds` | Max wait for `app.workspace.layoutReady` after the vault (re)opens; raise on slow emulators. | `90000` |
746
+ | `sessionConnectionRetryTimeoutInMilliseconds` | Max wait to establish the Appium session (UiAutomator2 install + app launch); the dominant startup cost. | `180000` |
747
+ | `shouldAutoInstallAppiumDependencies` | Auto-install missing Appium + the UiAutomator2 driver before auto-starting the server (global `npm install -g`). | `true` |
748
+ | `shouldAutoStartAppium` | Auto-start the Appium server when it is not already reachable. | `true` |
749
+ | `vaultBasePath` | Base device path where Obsidian stores vaults. | `'/sdcard/Documents/'` |
750
+ | `webviewTimeoutInMilliseconds` | Max wait for the WebView context after the Appium session starts. | `60000` |
750
751
 
751
752
  > [!NOTE]
752
753
  >
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var appium_dependencies_exports = {};
20
+ __export(appium_dependencies_exports, {
21
+ UIAUTOMATOR2_DRIVER_NAME: () => UIAUTOMATOR2_DRIVER_NAME,
22
+ checkIsAppiumDriverInstalled: () => checkIsAppiumDriverInstalled,
23
+ resolveShouldAutoInstallAppiumDependencies: () => resolveShouldAutoInstallAppiumDependencies
24
+ });
25
+ module.exports = __toCommonJS(appium_dependencies_exports);
26
+ const UIAUTOMATOR2_DRIVER_NAME = "uiautomator2";
27
+ function checkIsAppiumDriverInstalled(params) {
28
+ let parsed;
29
+ try {
30
+ parsed = JSON.parse(params.driverListJson);
31
+ } catch {
32
+ return false;
33
+ }
34
+ if (typeof parsed !== "object" || parsed === null) {
35
+ return false;
36
+ }
37
+ return params.driverName in parsed;
38
+ }
39
+ function resolveShouldAutoInstallAppiumDependencies(options) {
40
+ return options.shouldAutoInstallAppiumDependencies ?? true;
41
+ }
42
+ // Annotate the CommonJS export names for ESM import in node:
43
+ 0 && (module.exports = {
44
+ UIAUTOMATOR2_DRIVER_NAME,
45
+ checkIsAppiumDriverInstalled,
46
+ resolveShouldAutoInstallAppiumDependencies
47
+ });
48
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2FwcGl1bS1kZXBlbmRlbmNpZXMudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBQdXJlIGhlbHBlcnMgZm9yIGRlY2lkaW5nIHdoZXRoZXIgdGhlIGhhcm5lc3MgbXVzdCBhdXRvLWluc3RhbGwgdGhlIEFwcGl1bVxuICogZGVwZW5kZW5jaWVzICh0aGUgYHVpYXV0b21hdG9yMmAgZHJpdmVyKSBiZWZvcmUgaXQgYXV0by1zdGFydHMgdGhlIEFwcGl1bVxuICogc2VydmVyLCBwbHVzIHJlc29sdmluZyB0aGUgYXV0by1pbnN0YWxsIG9wdC1vdXQgZnJvbSB0aGUgdHJhbnNwb3J0IG9wdGlvbnMuXG4gKiBLZXB0IHNlcGFyYXRlIGZyb20gdGhlIGludGVncmF0aW9uLW9ubHkgYHRyYW5zcG9ydC1mYWN0b3J5YCBzbyB0aGUgcGFyc2luZyBhbmRcbiAqIGRlZmF1bHQgcmVzb2x1dGlvbiBzdGF5IHVuaXQtdGVzdGFibGUgKHRoZSBmYWN0b3J5IGl0c2VsZiBzaGVsbHMgb3V0IHRvIGBucG1gXG4gKiAvIGBucHhgIGFuZCBpcyBleGNsdWRlZCBmcm9tIHVuaXQgdGVzdHMpLlxuICovXG5cbmltcG9ydCB0eXBlIHsgT2JzaWRpYW5BbmRyb2lkQXBwaXVtVHJhbnNwb3J0T3B0aW9ucyB9IGZyb20gJy4vdHJhbnNwb3J0LW9wdGlvbnMuY2pzJztcblxuLyoqXG4gKiBUaGUgQXBwaXVtIGRyaXZlciBuYW1lIHJlcXVpcmVkIHRvIGF1dG9tYXRlIE9ic2lkaWFuIE1vYmlsZSBvbiBBbmRyb2lkLlxuICovXG5leHBvcnQgY29uc3QgVUlBVVRPTUFUT1IyX0RSSVZFUl9OQU1FID0gJ3VpYXV0b21hdG9yMic7XG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGNoZWNrSXNBcHBpdW1Ecml2ZXJJbnN0YWxsZWR9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENoZWNrSXNBcHBpdW1Ecml2ZXJJbnN0YWxsZWRQYXJhbXMge1xuICAvKipcbiAgICogUmF3IHN0ZG91dCBvZiBgYXBwaXVtIGRyaXZlciBsaXN0IC0taW5zdGFsbGVkIC0tanNvbmAgXHUyMDE0IGEgSlNPTiBvYmplY3Qga2V5ZWRcbiAgICogYnkgaW5zdGFsbGVkIGRyaXZlciBuYW1lIChge31gIHdoZW4gbm9uZSBhcmUgaW5zdGFsbGVkKS5cbiAgICovXG4gIHJlYWRvbmx5IGRyaXZlckxpc3RKc29uOiBzdHJpbmc7XG5cbiAgLyoqIFRoZSBkcml2ZXIgbmFtZSB0byBsb29rIGZvciAoZS5nLiB7QGxpbmsgVUlBVVRPTUFUT1IyX0RSSVZFUl9OQU1FfSkuICovXG4gIHJlYWRvbmx5IGRyaXZlck5hbWU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBEZWNpZGVzIHdoZXRoZXIgYSBnaXZlbiBBcHBpdW0gZHJpdmVyIGlzIGluc3RhbGxlZCwgZnJvbSB0aGUgcmF3IEpTT04gb3V0cHV0XG4gKiBvZiBgYXBwaXVtIGRyaXZlciBsaXN0IC0taW5zdGFsbGVkIC0tanNvbmAuXG4gKlxuICogYC0taW5zdGFsbGVkYCByZXN0cmljdHMgdGhlIGxpc3RpbmcgdG8gaW5zdGFsbGVkIGRyaXZlcnMsIHNvIGEgZHJpdmVyIGlzXG4gKiBwcmVzZW50IGV4YWN0bHkgd2hlbiBpdHMgbmFtZSBpcyBhIGtleSBvZiB0aGUgcGFyc2VkIG9iamVjdC4gTWFsZm9ybWVkIG9yXG4gKiBub24tb2JqZWN0IG91dHB1dCAoYW4gZW1wdHkgc3RyaW5nLCBhIGxvZyBsaW5lIHRoYXQgbGVha2VkIG9udG8gc3Rkb3V0LCBhXG4gKiBKU09OIHByaW1pdGl2ZSwgYG51bGxgKSBpcyB0cmVhdGVkIGFzIFwibm90IGluc3RhbGxlZFwiIHNvIHRoZSBjYWxsZXIgcHJvY2VlZHNcbiAqIHRvIGluc3RhbGwgXHUyMDE0IHRoZSBpbnN0YWxsIGNvbW1hbmQgaXMgb25seSBpc3N1ZWQgd2hlbiB0aGlzIHJldHVybnMgYGZhbHNlYC5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHNhbXBsZWQgZHJpdmVyLWxpc3Qgb3V0cHV0IGFuZCB0aGUgZHJpdmVyIG5hbWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgZHJpdmVyIGlzIGxpc3RlZCBhcyBpbnN0YWxsZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGVja0lzQXBwaXVtRHJpdmVySW5zdGFsbGVkKHBhcmFtczogQ2hlY2tJc0FwcGl1bURyaXZlckluc3RhbGxlZFBhcmFtcyk6IGJvb2xlYW4ge1xuICBsZXQgcGFyc2VkOiB1bmtub3duO1xuICB0cnkge1xuICAgIHBhcnNlZCA9IEpTT04ucGFyc2UocGFyYW1zLmRyaXZlckxpc3RKc29uKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBwYXJzZWQgIT09ICdvYmplY3QnIHx8IHBhcnNlZCA9PT0gbnVsbCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBwYXJhbXMuZHJpdmVyTmFtZSBpbiBwYXJzZWQ7XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgd2hldGhlciB0aGUgaGFybmVzcyBtYXkgYXV0by1pbnN0YWxsIG1pc3NpbmcgQXBwaXVtIGRlcGVuZGVuY2llcyxcbiAqIGFwcGx5aW5nIHRoZSBkZWZhdWx0IHdoZW4gdGhlIG9wdGlvbiBpcyBvbWl0dGVkLlxuICpcbiAqIFRoaXMgb25seSBnb3Zlcm5zIHRoZSBtYWNoaW5lLW11dGF0aW5nIGluc3RhbGwgc3RlcCAoYSBnbG9iYWwgYG5wbSBpbnN0YWxsIC1nXG4gKiBhcHBpdW1gIGFuZCBhbiBgYXBwaXVtIGRyaXZlciBpbnN0YWxsYCk7IGl0IGlzIGEgbm8tb3AgdW5sZXNzIHRoZSBoYXJuZXNzIGlzXG4gKiBhbHNvIGF1dG8tc3RhcnRpbmcgdGhlIEFwcGl1bSBzZXJ2ZXIgKHtAbGlua1xuICogT2JzaWRpYW5BbmRyb2lkQXBwaXVtVHJhbnNwb3J0T3B0aW9ucy5zaG91bGRBdXRvU3RhcnRBcHBpdW19KS4gU2V0IGl0IHRvXG4gKiBgZmFsc2VgIHRvIG1hbmFnZSB0aGUgQXBwaXVtIHRvb2xjaGFpbiB5b3Vyc2VsZi5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBBbmRyb2lkIEFwcGl1bSB0cmFuc3BvcnQgb3B0aW9ucy5cbiAqIEByZXR1cm5zIFdoZXRoZXIgbWlzc2luZyBBcHBpdW0gZGVwZW5kZW5jaWVzIG1heSBiZSBhdXRvLWluc3RhbGxlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTaG91bGRBdXRvSW5zdGFsbEFwcGl1bURlcGVuZGVuY2llcyhcbiAgb3B0aW9uczogT2JzaWRpYW5BbmRyb2lkQXBwaXVtVHJhbnNwb3J0T3B0aW9uc1xuKTogYm9vbGVhbiB7XG4gIHJldHVybiBvcHRpb25zLnNob3VsZEF1dG9JbnN0YWxsQXBwaXVtRGVwZW5kZW5jaWVzID8/IHRydWU7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWdCTyxNQUFNLDJCQUEyQjtBQTZCakMsU0FBUyw2QkFBNkIsUUFBcUQ7QUFDaEcsTUFBSTtBQUNKLE1BQUk7QUFDRixhQUFTLEtBQUssTUFBTSxPQUFPLGNBQWM7QUFBQSxFQUMzQyxRQUFRO0FBQ04sV0FBTztBQUFBLEVBQ1Q7QUFFQSxNQUFJLE9BQU8sV0FBVyxZQUFZLFdBQVcsTUFBTTtBQUNqRCxXQUFPO0FBQUEsRUFDVDtBQUVBLFNBQU8sT0FBTyxjQUFjO0FBQzlCO0FBZU8sU0FBUywyQ0FDZCxTQUNTO0FBQ1QsU0FBTyxRQUFRLHVDQUF1QztBQUN4RDsiLAogICJuYW1lcyI6IFtdCn0K
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Pure helpers for deciding whether the harness must auto-install the Appium
5
+ * dependencies (the `uiautomator2` driver) before it auto-starts the Appium
6
+ * server, plus resolving the auto-install opt-out from the transport options.
7
+ * Kept separate from the integration-only `transport-factory` so the parsing and
8
+ * default resolution stay unit-testable (the factory itself shells out to `npm`
9
+ * / `npx` and is excluded from unit tests).
10
+ */
11
+ import type { ObsidianAndroidAppiumTransportOptions } from './transport-options.cjs';
12
+ /**
13
+ * The Appium driver name required to automate Obsidian Mobile on Android.
14
+ */
15
+ export declare const UIAUTOMATOR2_DRIVER_NAME = "uiautomator2";
16
+ /**
17
+ * Parameters for {@link checkIsAppiumDriverInstalled}.
18
+ */
19
+ export interface CheckIsAppiumDriverInstalledParams {
20
+ /**
21
+ * Raw stdout of `appium driver list --installed --json` — a JSON object keyed
22
+ * by installed driver name (`{}` when none are installed).
23
+ */
24
+ readonly driverListJson: string;
25
+ /** The driver name to look for (e.g. {@link UIAUTOMATOR2_DRIVER_NAME}). */
26
+ readonly driverName: string;
27
+ }
28
+ /**
29
+ * Decides whether a given Appium driver is installed, from the raw JSON output
30
+ * of `appium driver list --installed --json`.
31
+ *
32
+ * `--installed` restricts the listing to installed drivers, so a driver is
33
+ * present exactly when its name is a key of the parsed object. Malformed or
34
+ * non-object output (an empty string, a log line that leaked onto stdout, a
35
+ * JSON primitive, `null`) is treated as "not installed" so the caller proceeds
36
+ * to install — the install command is only issued when this returns `false`.
37
+ *
38
+ * @param params - The sampled driver-list output and the driver name to check.
39
+ * @returns `true` when the driver is listed as installed.
40
+ */
41
+ export declare function checkIsAppiumDriverInstalled(params: CheckIsAppiumDriverInstalledParams): boolean;
42
+ /**
43
+ * Resolves whether the harness may auto-install missing Appium dependencies,
44
+ * applying the default when the option is omitted.
45
+ *
46
+ * This only governs the machine-mutating install step (a global `npm install -g
47
+ * appium` and an `appium driver install`); it is a no-op unless the harness is
48
+ * also auto-starting the Appium server ({@link
49
+ * ObsidianAndroidAppiumTransportOptions.shouldAutoStartAppium}). Set it to
50
+ * `false` to manage the Appium toolchain yourself.
51
+ *
52
+ * @param options - The Android Appium transport options.
53
+ * @returns Whether missing Appium dependencies may be auto-installed.
54
+ */
55
+ export declare function resolveShouldAutoInstallAppiumDependencies(options: ObsidianAndroidAppiumTransportOptions): boolean;
@@ -21,7 +21,7 @@ __export(library_exports, {
21
21
  LIBRARY_VERSION: () => LIBRARY_VERSION
22
22
  });
23
23
  module.exports = __toCommonJS(library_exports);
24
- const LIBRARY_VERSION = false ? "dev" : "8.1.1";
24
+ const LIBRARY_VERSION = false ? "dev" : "8.2.0";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  LIBRARY_VERSION
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var spawn_options_exports = {};
20
+ __export(spawn_options_exports, {
21
+ resolveAppiumSpawnFlags: () => resolveAppiumSpawnFlags,
22
+ resolveEmulatorSpawnFlags: () => resolveEmulatorSpawnFlags
23
+ });
24
+ module.exports = __toCommonJS(spawn_options_exports);
25
+ function resolveAppiumSpawnFlags(isConsoleHidden) {
26
+ return {
27
+ detached: !isConsoleHidden,
28
+ windowsHide: isConsoleHidden
29
+ };
30
+ }
31
+ function resolveEmulatorSpawnFlags(isWindowHidden) {
32
+ return {
33
+ detached: false,
34
+ windowsHide: isWindowHidden
35
+ };
36
+ }
37
+ // Annotate the CommonJS export names for ESM import in node:
38
+ 0 && (module.exports = {
39
+ resolveAppiumSpawnFlags,
40
+ resolveEmulatorSpawnFlags
41
+ });
42
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3NwYXduLW9wdGlvbnMudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBQdXJlIHJlc29sdXRpb24gb2YgdGhlIGBkZXRhY2hlZGAgLyBgd2luZG93c0hpZGVgIHNwYXduIGZsYWdzIGZvciB0aGVcbiAqIGF1dG8tc3RhcnRlZCBBcHBpdW0gc2VydmVyIGFuZCBBbmRyb2lkIGVtdWxhdG9yLCBkZXJpdmVkIGZyb20gd2hldGhlciB0aGVpclxuICogY29uc29sZSB3aW5kb3dzIHNob3VsZCBiZSBoaWRkZW4uXG4gKlxuICogS2VwdCBzZXBhcmF0ZSBmcm9tIHRoZSBpbnRlZ3JhdGlvbi1vbmx5IGxhdW5jaCBjb2RlIChgdHJhbnNwb3J0LWZhY3RvcnlgLFxuICogZXhjbHVkZWQgZnJvbSB1bml0IHRlc3RzKSBzbyB0aGUgZmxhZyByZXNvbHV0aW9uIHN0YXlzIHVuaXQtdGVzdGFibGUgXHUyMDE0IHRoZVxuICogbGF1bmNoZXIgaXRzZWxmIG5lZWRzIGEgcmVhbCBBcHBpdW0gc2VydmVyIC8gZW11bGF0b3IuIE1pcnJvcnMgdGhlIHNwbGl0IGluXG4gKiBgdmlzaWJpbGl0eS50c2AgYW5kIGBlbXVsYXRvci1hcmdzLnRzYC5cbiAqXG4gKiAqKldoeSB0aGVzZSBleGFjdCBmbGFncyoqIChlbXBpcmljYWxseSB2ZXJpZmllZCBvbiBXaW5kb3dzKTpcbiAqIC0gYGRldGFjaGVkOiB0cnVlYCBzZXRzIGBERVRBQ0hFRF9QUk9DRVNTYCwgd2hpY2ggZ2l2ZXMgdGhlIGNoaWxkIG5vIGNvbnNvbGUuXG4gKiAgIEZvciBhIGNvbnNvbGUtc3Vic3lzdGVtIGNoaWxkIHRoYXQgbWVhbnMgV2luZG93cy90aGUgY2hpbGQgbGF0ZXIgYWxsb2NhdGVzIGFcbiAqICAgKipmcmVzaCwgdmlzaWJsZSoqIGNvbnNvbGUgXHUyMDE0IGFuZCBgd2luZG93c0hpZGVgICh3aGljaCBvbmx5IHNldHMgYFNXX0hJREVgIG9uXG4gKiAgIGFuIGluaGVyaXRlZC9uZXcgY29uc29sZSBhdCBgQ3JlYXRlUHJvY2Vzc2AgdGltZSkgaXMgc2lsZW50bHkgZGVmZWF0ZWQuIFNvIGFcbiAqICAgcHJvY2VzcyB3ZSB3YW50IGhpZGRlbiBtdXN0IE5PVCBiZSBkZXRhY2hlZC5cbiAqIC0gTm90IGRldGFjaGluZyBsZXRzIHRoZSBjaGlsZCBpbmhlcml0IHRoZSBwYXJlbnQncyAoaGlkZGVuKSBjb25zb2xlLCBhbmQgYW55XG4gKiAgIGNvbnNvbGUtYXBwICoqZ3JhbmRjaGlsZHJlbioqIGl0IHNwYXducyAoZS5nLiB0aGUgZW11bGF0b3IncyBuZXRzaW0vcWVtdVxuICogICBoZWxwZXJzKSBpbmhlcml0IHRoYXQgaGlkZGVuIGNvbnNvbGUgdG9vLCBpbnN0ZWFkIG9mIGVhY2ggcG9wcGluZyB0aGVpciBvd24uXG4gKiAtIFRlYXJkb3duIGRvZXMgbm90IHJlbHkgb24gYGRldGFjaGVkYDogYGtpbGxQcm9jZXNzVHJlZWAgdXNlc1xuICogICBgdGFza2tpbGwgL0YgL1QgL1BJRGAsIGFuZCBgY2hpbGQudW5yZWYoKWAgYWxvbmUgbGV0cyB0aGUgcGFyZW50IGV2ZW50IGxvb3BcbiAqICAgZXhpdCB3aXRob3V0IHdhaXRpbmcgb24gdGhlIGNoaWxkLlxuICovXG5cbi8qKlxuICogVGhlIHN1YnNldCBvZiBzcGF3biBvcHRpb25zIHRoYXQgY29udHJvbCBjb25zb2xlLXdpbmRvdyB2aXNpYmlsaXR5LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwYXduVmlzaWJpbGl0eUZsYWdzIHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gcnVuIHRoZSBjaGlsZCBpbiBpdHMgb3duIHByb2Nlc3MgZ3JvdXAgLyBkZXRhY2hlZCBmcm9tIHRoZVxuICAgKiBwYXJlbnQgY29uc29sZSAoYERFVEFDSEVEX1BST0NFU1NgIG9uIFdpbmRvd3MpLlxuICAgKi9cbiAgcmVhZG9ubHkgZGV0YWNoZWQ6IGJvb2xlYW47XG5cbiAgLyoqIFdoZXRoZXIgdG8gaGlkZSB0aGUgY2hpbGQncyBjb25zb2xlIHdpbmRvdyAoYHdpbmRvd3NIaWRlYCkuICovXG4gIHJlYWRvbmx5IHdpbmRvd3NIaWRlOiBib29sZWFuO1xufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSB2aXNpYmlsaXR5IHNwYXduIGZsYWdzIGZvciB0aGUgYXV0by1zdGFydGVkIEFwcGl1bSBzZXJ2ZXIuXG4gKlxuICogV2hlbiBoaWRkZW4sIHRoZSBzZXJ2ZXIgbXVzdCBOT1QgYmUgZGV0YWNoZWQgKG90aGVyd2lzZSBhIGNvbnNvbGUgd2luZG93XG4gKiBhcHBlYXJzIGRlc3BpdGUgYHdpbmRvd3NIaWRlYCkuIFdoZW4gdGhlIHVzZXIgb3B0cyB0byBzZWUgdGhlIGNvbnNvbGUsIGl0IGlzXG4gKiBkZXRhY2hlZCBzbyBpdCBnZXRzIGl0cyBvd24gZGVkaWNhdGVkIHdpbmRvdy5cbiAqXG4gKiBAcGFyYW0gaXNDb25zb2xlSGlkZGVuIC0gV2hldGhlciB0aGUgQXBwaXVtIGNvbnNvbGUgc2hvdWxkIGJlIGhpZGRlbi5cbiAqIEByZXR1cm5zIFRoZSBgZGV0YWNoZWRgIC8gYHdpbmRvd3NIaWRlYCBmbGFncyB0byBwYXNzIHRvIGBzcGF3bmAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQXBwaXVtU3Bhd25GbGFncyhpc0NvbnNvbGVIaWRkZW46IGJvb2xlYW4pOiBTcGF3blZpc2liaWxpdHlGbGFncyB7XG4gIHJldHVybiB7XG4gICAgZGV0YWNoZWQ6ICFpc0NvbnNvbGVIaWRkZW4sXG4gICAgd2luZG93c0hpZGU6IGlzQ29uc29sZUhpZGRlblxuICB9O1xufVxuXG4vKipcbiAqIFJlc29sdmVzIHRoZSB2aXNpYmlsaXR5IHNwYXduIGZsYWdzIGZvciB0aGUgYXV0by1zdGFydGVkIEFuZHJvaWQgZW11bGF0b3IuXG4gKlxuICogVGhlIGVtdWxhdG9yIGlzIG5ldmVyIGRldGFjaGVkOiBkZXRhY2hpbmcgb25seSBjYXVzZXMgaXRzIGNvbnNvbGUtYXBwXG4gKiBncmFuZGNoaWxkcmVuIChuZXRzaW0vcWVtdSkgdG8gYWxsb2NhdGUgdGhlaXIgb3duIHZpc2libGUgY29uc29sZXMuIEl0c1xuICogb24tc2NyZWVuIGRldmljZSB3aW5kb3cgaXMgYSBHVUkgd2luZG93IGNvbnRyb2xsZWQgYnkgdGhlIGAtbm8td2luZG93YFxuICogYXJndW1lbnQgKHNlZSBgZW11bGF0b3ItYXJncy50c2ApLCBpbmRlcGVuZGVudCBvZiB0aGVzZSBjb25zb2xlIGZsYWdzLlxuICpcbiAqIEBwYXJhbSBpc1dpbmRvd0hpZGRlbiAtIFdoZXRoZXIgdGhlIGVtdWxhdG9yIChhbmQgaXRzIGNvbnNvbGUpIHNob3VsZCBiZSBoaWRkZW4uXG4gKiBAcmV0dXJucyBUaGUgYGRldGFjaGVkYCAvIGB3aW5kb3dzSGlkZWAgZmxhZ3MgdG8gcGFzcyB0byBgc3Bhd25gLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUVtdWxhdG9yU3Bhd25GbGFncyhpc1dpbmRvd0hpZGRlbjogYm9vbGVhbik6IFNwYXduVmlzaWJpbGl0eUZsYWdzIHtcbiAgcmV0dXJuIHtcbiAgICBkZXRhY2hlZDogZmFsc2UsXG4gICAgd2luZG93c0hpZGU6IGlzV2luZG93SGlkZGVuXG4gIH07XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrRE8sU0FBUyx3QkFBd0IsaUJBQWdEO0FBQ3RGLFNBQU87QUFBQSxJQUNMLFVBQVUsQ0FBQztBQUFBLElBQ1gsYUFBYTtBQUFBLEVBQ2Y7QUFDRjtBQWFPLFNBQVMsMEJBQTBCLGdCQUErQztBQUN2RixTQUFPO0FBQUEsSUFDTCxVQUFVO0FBQUEsSUFDVixhQUFhO0FBQUEsRUFDZjtBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Pure resolution of the `detached` / `windowsHide` spawn flags for the
5
+ * auto-started Appium server and Android emulator, derived from whether their
6
+ * console windows should be hidden.
7
+ *
8
+ * Kept separate from the integration-only launch code (`transport-factory`,
9
+ * excluded from unit tests) so the flag resolution stays unit-testable — the
10
+ * launcher itself needs a real Appium server / emulator. Mirrors the split in
11
+ * `visibility.ts` and `emulator-args.ts`.
12
+ *
13
+ * **Why these exact flags** (empirically verified on Windows):
14
+ * - `detached: true` sets `DETACHED_PROCESS`, which gives the child no console.
15
+ * For a console-subsystem child that means Windows/the child later allocates a
16
+ * **fresh, visible** console — and `windowsHide` (which only sets `SW_HIDE` on
17
+ * an inherited/new console at `CreateProcess` time) is silently defeated. So a
18
+ * process we want hidden must NOT be detached.
19
+ * - Not detaching lets the child inherit the parent's (hidden) console, and any
20
+ * console-app **grandchildren** it spawns (e.g. the emulator's netsim/qemu
21
+ * helpers) inherit that hidden console too, instead of each popping their own.
22
+ * - Teardown does not rely on `detached`: `killProcessTree` uses
23
+ * `taskkill /F /T /PID`, and `child.unref()` alone lets the parent event loop
24
+ * exit without waiting on the child.
25
+ */
26
+ /**
27
+ * The subset of spawn options that control console-window visibility.
28
+ */
29
+ export interface SpawnVisibilityFlags {
30
+ /**
31
+ * Whether to run the child in its own process group / detached from the
32
+ * parent console (`DETACHED_PROCESS` on Windows).
33
+ */
34
+ readonly detached: boolean;
35
+ /** Whether to hide the child's console window (`windowsHide`). */
36
+ readonly windowsHide: boolean;
37
+ }
38
+ /**
39
+ * Resolves the visibility spawn flags for the auto-started Appium server.
40
+ *
41
+ * When hidden, the server must NOT be detached (otherwise a console window
42
+ * appears despite `windowsHide`). When the user opts to see the console, it is
43
+ * detached so it gets its own dedicated window.
44
+ *
45
+ * @param isConsoleHidden - Whether the Appium console should be hidden.
46
+ * @returns The `detached` / `windowsHide` flags to pass to `spawn`.
47
+ */
48
+ export declare function resolveAppiumSpawnFlags(isConsoleHidden: boolean): SpawnVisibilityFlags;
49
+ /**
50
+ * Resolves the visibility spawn flags for the auto-started Android emulator.
51
+ *
52
+ * The emulator is never detached: detaching only causes its console-app
53
+ * grandchildren (netsim/qemu) to allocate their own visible consoles. Its
54
+ * on-screen device window is a GUI window controlled by the `-no-window`
55
+ * argument (see `emulator-args.ts`), independent of these console flags.
56
+ *
57
+ * @param isWindowHidden - Whether the emulator (and its console) should be hidden.
58
+ * @returns The `detached` / `windowsHide` flags to pass to `spawn`.
59
+ */
60
+ export declare function resolveEmulatorSpawnFlags(isWindowHidden: boolean): SpawnVisibilityFlags;