ObsidianAndroidAppiumTransportOptions
Transport options for Android testing via Appium WebView injection.
Import:
import type { ObsidianAndroidAppiumTransportOptions } from 'obsidian-integration-testing';Signature:
export interface ObsidianAndroidAppiumTransportOptionsProperties
| Property | Type | Description |
|---|---|---|
| appId? | string | App package (Android) or bundle ID (iOS). Defaults to 'md.obsidian' |
| appiumStartTimeoutInMilliseconds? | number | Timeout in milliseconds for the auto-started Appium server to become ready (its /status endpoint to respond).Only applies when the harness auto-starts the Appium server ( shouldAutoStartAppium); ignored when attaching to an already-running server. On a cold machine the npx appium server can take a while to finish booting, so raise this if startup times out. |
| appiumUrl | string | The Appium server URL (e.g. 'http://localhost:4723'). |
| avdName | string | The Android AVD (Android Virtual Device) name. The transport factory launches emulator -avd <avdName> as a background process and polls until the device appears. The emulator is killed on transport disposal.Run emulator -list-avds to see available AVD names. |
| deviceId? | string | The device UDID to reuse (e.g. 'emulator-5554').Populated automatically by the global setup after the Appium session is established. When present alongside sessionId, the transport factory skips emulator startup and attaches to the existing session. |
| deviceIdleTimeoutInMilliseconds? | number | Timeout in milliseconds for waiting, after sys.boot_completed, for a harness-started emulator to become idle before the Appium session is established.sys.boot_completed fires *before* the guest is actually idle: package optimization and system services keep churning, so establishing the session immediately makes every one of UiAutomator2's serialized adb round-trips contend with that work and inflates session establishment ~3x. The factory instead waits until the boot animation has stopped and the package manager is serving, proceeding early once idle or after this budget (best-effort — a timeout logs a warning and proceeds). Set 0 to skip the wait. Only applies to a harness-started emulator, not a reused one. |
| isAppiumConsoleVisible? | boolean | Whether the auto-started Appium server console window is shown. When false (the default), the npx appium server process is spawned with its console window hidden (windowsHide) and its output discarded, so it neither steals focus nor writes to the invoking terminal. Ignored when attaching to an already-running Appium server (shouldAutoStartAppium false, or the server already reachable). Set true to see the server log window and its live output. |
| isEmulatorVisible? | boolean | Whether the auto-started Android emulator window is shown on screen. When false (the default), the emulator is started with -no-window (headless), so it never steals focus. Ignored when reusing an already-running device (nothing is launched to hide). Set true to watch the emulator UI. |
| layoutReadyTimeoutInMilliseconds? | number | Timeout in milliseconds for waiting for app.workspace.layoutReady after the vault is (re)opened.Registering a vault triggers a full Obsidian re-init ( location.reload() reopens the vault and reloads every plugin — the heaviest startup step). On a cold-booted or under-provisioned emulator that init can take a while, so this budget is the largest of the transport timeouts. Raise it further if releases still flake on slow CI emulators. |
| leftoverMaxAgeInMilliseconds? | number | How old a leftover **host** directory must be before shouldSweepLeftovers removes it.Governs the host-side sweep only (the temp-vault-* staging directories this run's machine accumulates in its temp dir). The **device** sweep is unconditional: Android runs hold the exclusive android setup lock, so no concurrent run can own a device vault, and an age gate there would let a vault leaked minutes ago survive into the next run — which is the failure loop the sweep exists to break. Set 0 to remove every host match too. |
| pluginEnableRetryCount? | number | Number of extra attempts to enable the plugin and verify it loaded, on top of the first attempt. On a freshly cold-booted emulator the plugin subsystem can still be settling when the harness enables the plugin, so the enable lands in the enabled set but the load races and fails ( "<id>" is in the enabled set but not loaded). Device-idle and layoutReady are already awaited, so this is the narrow residual race: the harness retries the enable + load-verification this many times with exponential backoff (see pluginEnableRetryDelayInMilliseconds), forcing a genuine reload each attempt. A captured plugin load error is treated as a deterministic bug and is **not** retried. Set 0 to disable retry (a single attempt). |
| pluginEnableRetryDelayInMilliseconds? | number | Base delay in milliseconds between plugin-enable attempts (see pluginEnableRetryCount).The delay grows exponentially per retry: the first retry waits this long, the second twice as long, the third four times, and so on — giving a still-settling cold guest progressively more time to become ready. |
| sessionConnectionRetryTimeoutInMilliseconds? | number | Timeout in milliseconds for establishing the Appium session (WebDriverIO remote() — UiAutomator2 server install + app launch).This is the largest and most load-sensitive step of the Android setup: on a cold or contended emulator it dominates startup and can take a few minutes. Raise it if session establishment times out under load. |
| sessionId? | string | An existing Appium session ID to reattach to. Populated automatically by the global setup and provided to test workers via the framework's context mechanism (e.g. Vitest provide/inject). When present, the transport factory uses WebDriverIO's attach() instead of creating a new session, avoiding duplicate Appium/ADB connections. |
| shouldAutoInstallAppiumDependencies? | boolean | Whether to automatically install missing Appium dependencies (the uiautomator2 driver, and Appium itself) before auto-starting the server.When true (the default) and the harness is about to auto-start the Appium server (shouldAutoStartAppium), the factory first ensures Appium is installed (globally, via npm install -g appium) and that the uiautomator2 driver is installed (appium driver install uiautomator2), installing whichever is missing. Ignored when attaching to an already-running server (nothing is auto-started, so nothing is installed) or when shouldAutoStartAppium is false. Set it to false to manage the Appium toolchain yourself and skip the machine-mutating global install. |
| shouldAutoStartAppium? | boolean | Whether to automatically start the Appium server if it is not reachable. When true (the default), the transport factory spawns npx appium as a background process when the preflight check fails, and kills it on transport disposal. |
| shouldSweepLeftovers? | boolean | Whether the harness removes the temporary directories earlier runs leaked. When true (the default), each run sweeps at start **and** at end: on the device, every temp-vault-* directory under vaultBasePath (plus the stale vault registrations in Obsidian Mobile's localStorage); on the host, the leftover temp-vault-* and owned userdata-* directories older than leftoverMaxAgeInMilliseconds.A run that dies cannot clean up after itself — its teardown goes through the WebView, and a dead WebView is what most Android failures are — so the residue accumulates and slows the next run's startup enumeration until it misses the WebView-readiness budget. The start sweep is the half that breaks that loop, because it runs before anything that can die. |
| type | 'obsidian-android-appium' | Discriminant for the transport type. |
| vaultBasePath? | string | Base path on the device where Obsidian stores vaults. Defaults: - Android: /sdcard/Documents/ - iOS: @md.obsidian:documents/ |
| webviewTimeoutInMilliseconds? | number | Timeout in milliseconds for waiting for the WebView context to become available. On slow emulators, the ChromeDriver proxy that handles WebView commands may not be ready immediately after the Appium session starts. This timeout controls how long to poll before giving up. |
Links to this page: