@vostride/agent-qa-ios 0.0.1 → 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/session.ts"],"sourcesContent":["export { IOSPlatformAdapter } from './adapter.js'\nexport type { IOSAdapterConfig } from './types.js'\nexport { createIOSSession } from './session.js'\n","import type { PlatformAdapter, PlatformConfig, ScreenState, Action, ActionResult, ObserveOptions, ConsoleLogEntry } from '@vostride/agent-qa-core'\nimport { MobileSetupError, parseMobileSource, MobileElementResolver, KEY_MAP, computeSwipe, computePinch, computeFingerPositions, alignToWindow, warnIfOutOfBounds } from '@vostride/agent-qa-core'\nimport type { MobileRefMap } from '@vostride/agent-qa-core'\nimport { createIOSSession } from './session.js'\nimport type { IOSAdapterConfig } from './types.js'\n\nconst IOS_FILLABLE_ROLES = new Set(['textbox', 'searchbox', 'textfield', 'securetextfield', 'searchfield', 'combobox'])\nconst IOS_NATIVE_SELECT_TYPES = new Set([\n 'XCUIElementTypePickerWheel',\n 'XCUIElementTypePicker',\n 'XCUIElementTypeDatePicker',\n 'XCUIElementTypePopUpButton',\n 'XCUIElementTypeComboBox',\n])\nconst IOS_NATIVE_SELECT_ROLES = new Set(['pickerwheel', 'spinbutton', 'combobox'])\n\n// WebDriverIO's action().perform() calls DELETE /session/{id}/actions (releaseActions)\n// after performing. BrowserStack iOS doesn't support this endpoint and throws\n// \"resource not found\" errors. This wrapper swallows that specific error.\nasync function safePerform(chain: { perform: () => Promise<void> }): Promise<void> {\n try {\n await chain.perform()\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('actions') && msg.includes('DELETE')) return\n throw err\n }\n}\n\nconst IOS_SYSLOG_REGEX = /^.*?\\s+(\\S+)\\[(\\d+)\\].*?:\\s+(.*)/\nconst IOS_APPIUM_LOG_REGEX = /^\\S+\\s+\\S+\\s+\\[(\\w+)\\]\\s+\\[(\\S+)\\]\\s+(.*)/\n\nconst IOS_LEVEL_MAP: Record<string, string> = {\n Debug: 'debug',\n Info: 'info',\n Warning: 'warn',\n Warn: 'warn',\n Error: 'error',\n Fault: 'error',\n Notice: 'info',\n}\n\nfunction firstNonEmpty(...values: Array<string | null | undefined>): string | undefined {\n for (const value of values) {\n const trimmed = typeof value === 'string' ? value.trim() : ''\n if (trimmed) return trimmed\n }\n return undefined\n}\n\nfunction isIOSNativeSelectTarget(refData: MobileRefMap[string] | undefined): boolean {\n const role = refData?.role?.toLowerCase()\n return Boolean(\n (role && IOS_NATIVE_SELECT_ROLES.has(role))\n || (refData?.nativeType && IOS_NATIVE_SELECT_TYPES.has(refData.nativeType))\n )\n}\n\nfunction normalizePickerValue(value: string): string {\n return value.trim().replace(/\\s+/g, ' ').toLowerCase()\n}\n\nasync function getElementValue(el: any): Promise<string | undefined> {\n for (const getter of [\n () => el.getValue?.(),\n () => el.getText?.(),\n () => el.getAttribute?.('value'),\n ]) {\n try {\n const value = await getter()\n if (typeof value === 'string' && value.trim()) return value\n } catch {\n // Try the next value source.\n }\n }\n return undefined\n}\n\nasync function findIOSPickerWheels(\n driver: WebdriverIO.Browser,\n refs: MobileRefMap,\n targetRef: string,\n refData: MobileRefMap[string] | undefined,\n): Promise<any[]> {\n const wheelSelector = '-ios class chain:**/XCUIElementTypePickerWheel'\n if (refData?.nativeType === 'XCUIElementTypePickerWheel') {\n try {\n const observedWheelRefs = Object.entries(refs)\n .filter(([, data]) => data.nativeType === 'XCUIElementTypePickerWheel')\n .map(([ref]) => ref)\n const targetIndex = observedWheelRefs.indexOf(targetRef)\n const wheels = Array.from(await driver.$$(wheelSelector) as unknown as any[])\n if (targetIndex >= 0 && wheels[targetIndex]) return [wheels[targetIndex]]\n if (targetIndex <= 0 && wheels.length === 1) return [wheels[0]]\n } catch {\n // Fall back to a direct lookup below for drivers/tests without $$ support.\n }\n try {\n const wheel = await driver.$(wheelSelector)\n return await wheel.isExisting() ? [wheel] : []\n } catch {\n return []\n }\n }\n\n try {\n const wheels = await driver.$$(wheelSelector)\n return Array.from(wheels as unknown as any[])\n } catch {\n return []\n }\n}\n\nfunction matchesIOSApp(processName: string, bundleId: string): boolean {\n const appName = bundleId.split('.').pop() ?? bundleId\n return processName === appName || processName.includes(appName)\n}\n\nfunction parseIOSSyslogLine(message: string, timestamp: number, bundleId: string | null): ConsoleLogEntry | null {\n const appiumMatch = message.match(IOS_APPIUM_LOG_REGEX)\n if (appiumMatch) {\n const [, levelStr, processName, text] = appiumMatch\n if (bundleId && !matchesIOSApp(processName, bundleId)) return null\n return {\n level: IOS_LEVEL_MAP[levelStr] ?? 'info',\n text: text.trim(),\n timestamp,\n }\n }\n\n const syslogMatch = message.match(IOS_SYSLOG_REGEX)\n if (syslogMatch) {\n const [, processName, , text] = syslogMatch\n if (bundleId && !matchesIOSApp(processName, bundleId)) return null\n return {\n level: 'info',\n text: text.trim(),\n timestamp,\n }\n }\n\n return null\n}\n\nexport class IOSPlatformAdapter implements PlatformAdapter {\n readonly platform = 'ios' as const\n\n private driver: WebdriverIO.Browser | null = null\n private lastRefs: MobileRefMap = {}\n private config: IOSAdapterConfig | null = null\n // Web context detected from getContexts() (e.g. 'WEBVIEW_12345').\n // Used for URL extraction in observe() and JS scroll in execute().\n private activeWebContext: string | null = null\n private webContextChecked = false\n private currentContext: string | null = null\n private consoleLogs: ConsoleLogEntry[] = []\n private consoleDrainIndex = 0\n private captureConsole = true\n private bundleId: string | null = null\n\n async setup(config: PlatformConfig): Promise<void> {\n this.config = config as IOSAdapterConfig\n this.captureConsole = config.logCapture?.console !== false\n this.bundleId = this.config.bundleId ?? (config.device?.match?.bundleId as string | undefined) ?? null\n\n this.driver = await createIOSSession(this.config, config.farmSession)\n\n const bundleId = this.bundleId\n if (bundleId) {\n try {\n await this.driver.activateApp(bundleId)\n } catch (err) {\n throw new MobileSetupError({\n category: 'app-launch',\n message: `Failed to launch iOS app \"${bundleId}\": ${err instanceof Error ? err.message : String(err)}`,\n platform: 'ios',\n deviceName: config.device?.name,\n appId: bundleId,\n cause: err,\n })\n }\n }\n }\n\n async cleanup(): Promise<void> {\n try {\n if (this.driver) {\n await this.driver.deleteSession()\n }\n } catch {\n // session may already be closed\n }\n this.driver = null\n this.lastRefs = {}\n this.config = null\n this.consoleLogs = []\n this.bundleId = null\n this.activeWebContext = null\n this.webContextChecked = false\n this.currentContext = null\n }\n\n async observe(_options?: ObserveOptions): Promise<ScreenState> {\n if (!this.driver) {\n throw new Error('IOSPlatformAdapter not initialized — call setup() first')\n }\n\n // Ensure native context for XCUITest observation (which CAN see into WebViews on iOS)\n await this.ensureContext('NATIVE_APP')\n\n const [xml, viewport] = await Promise.all([\n this.driver.getPageSource(),\n this.driver.getWindowSize(),\n ])\n const parsed = parseMobileSource(xml, 'ios', viewport)\n this.lastRefs = parsed.refs\n\n // Try to get the current URL from web context (if available).\n // This gives the LLM verifier critical evidence about which page we're on.\n let url: string | undefined\n const webCtx = await this.getWebContext()\n if (webCtx) {\n try {\n await this.ensureContext(webCtx)\n url = await this.driver.getUrl()\n await this.ensureContext('NATIVE_APP')\n } catch {\n try { await this.ensureContext('NATIVE_APP') } catch { /* best-effort */ }\n }\n }\n\n return {\n tree: parsed.tree,\n elements: parsed.elements,\n url,\n timestamp: Date.now(),\n metadata: { coordSpace: 'viewport' as const, viewportWidth: viewport.width, viewportHeight: viewport.height, refMap: parsed.refs },\n }\n }\n\n async execute(action: Action): Promise<ActionResult> {\n if (!this.driver) {\n throw new Error('IOSPlatformAdapter not initialized — call setup() first')\n }\n\n try {\n return await this.executeAction(action)\n } catch (err) {\n let screenshot: Buffer | undefined\n try {\n screenshot = await this.captureScreenshot()\n } catch {\n // ignore screenshot failure\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n screenshot,\n }\n }\n }\n\n async screenshot(): Promise<Buffer | undefined> {\n try { await this.ensureContext('NATIVE_APP') } catch { /* best-effort */ }\n const raw = await this.captureScreenshot()\n if (!raw || !this.driver) return raw\n\n // Stage 2 (D-02, D-05): resize physical pixels → logical points.\n // iOS takeScreenshot returns physical pixels (e.g., 1179×2556 on iPhone 15 Pro)\n // while getWindowSize, XML bounds, and W3C pointer actions use logical points (393×852).\n // Re-read getWindowSize every call per Pitfall 8 (handles rotation — no caching).\n try {\n const { width, height } = await this.driver.getWindowSize()\n return await alignToWindow(raw, { width, height })\n } catch {\n // Alignment failure is best-effort — return raw buffer rather than crashing capture.\n return raw\n }\n }\n\n // ---------------------------------------------------------------------------\n // Device log capture\n // ---------------------------------------------------------------------------\n\n async pollDeviceLogs(): Promise<void> {\n if (!this.captureConsole) return\n if (!this.driver) return\n try {\n const logs = await this.driver.getLogs('syslog') as { message: string; timestamp?: number; level?: string }[]\n for (const entry of logs) {\n const parsed = parseIOSSyslogLine(entry.message, entry.timestamp ?? Date.now(), this.bundleId)\n if (parsed) {\n this.consoleLogs.push(parsed)\n continue\n }\n // Fallback: if regex didn't match, use the raw message with Appium-provided level\n if (entry.message?.trim()) {\n this.consoleLogs.push({\n level: IOS_LEVEL_MAP[entry.level ?? ''] ?? 'info',\n text: entry.message.trim(),\n timestamp: entry.timestamp ?? Date.now(),\n })\n }\n }\n if (this.consoleLogs.length > 1000) {\n this.consoleLogs = this.consoleLogs.slice(-500)\n }\n } catch {\n // getLogs may fail in some Appium configurations\n }\n }\n\n drainConsoleLogs(level?: string): ConsoleLogEntry[] {\n const newLogs = this.consoleLogs.slice(this.consoleDrainIndex)\n this.consoleDrainIndex = this.consoleLogs.length\n if (!level) return newLogs\n return newLogs.filter(e => e.level === level)\n }\n\n // ---------------------------------------------------------------------------\n // Web context helpers\n // ---------------------------------------------------------------------------\n\n /** Lazily detect the WEBVIEW context. Cached after first lookup. */\n private async getWebContext(): Promise<string | null> {\n if (!this.webContextChecked) {\n this.webContextChecked = true\n try {\n const contexts = await this.driver!.getContexts() as string[]\n this.activeWebContext = contexts.find(c =>\n typeof c === 'string' && c.includes('WEBVIEW')\n ) ?? null\n } catch {\n this.activeWebContext = null\n }\n }\n return this.activeWebContext\n }\n\n /** Invalidate the cached web context so next getWebContext() re-queries. */\n private invalidateWebContext(): void {\n this.webContextChecked = false\n this.activeWebContext = null\n }\n\n private async ensureContext(target: string): Promise<void> {\n if (this.currentContext === target) return\n try {\n await this.driver!.switchContext(target)\n this.currentContext = target\n } catch {\n this.currentContext = null\n }\n }\n\n // ---------------------------------------------------------------------------\n // Screenshots\n // ---------------------------------------------------------------------------\n\n private async captureScreenshot(): Promise<Buffer | undefined> {\n try {\n if (this.driver) {\n const base64 = await this.driver.takeScreenshot()\n return Buffer.from(base64, 'base64')\n }\n return undefined\n } catch {\n return undefined\n }\n }\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n\n private async executeAction(action: Action): Promise<ActionResult> {\n const driver = this.driver!\n const resolver = new MobileElementResolver(this.lastRefs)\n\n // Ensure we're in native context for touch gestures\n await this.ensureContext('NATIVE_APP')\n\n switch (action.type) {\n case 'tap':\n case 'click': {\n const { center, bounds } = resolver.resolve(action.ref)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n\n case 'fill': {\n const { center, bounds } = resolver.resolve(action.ref)\n const refData = this.lastRefs[action.ref]\n const role = refData?.role?.toLowerCase()\n if (role && !IOS_FILLABLE_ROLES.has(role)) {\n return {\n success: false,\n error: `Element ${action.ref} is not fillable (role: ${role}). Use a textbox or input element instead.`,\n }\n }\n // Tap to focus\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n // Find the input element — try focused first, then any matching type\n const selectors = [\n // Focused element (most precise)\n '-ios class chain:**/XCUIElementTypeTextField[`hasFocus == 1`]',\n '-ios class chain:**/XCUIElementTypeSecureTextField[`hasFocus == 1`]',\n '-ios class chain:**/XCUIElementTypeSearchField[`hasFocus == 1`]',\n // Any visible element of the type (fallback — some apps don't report hasFocus)\n '-ios class chain:**/XCUIElementTypeSearchField',\n '-ios class chain:**/XCUIElementTypeTextField',\n '-ios class chain:**/XCUIElementTypeSecureTextField',\n ]\n for (const sel of selectors) {\n try {\n const el = await driver.$(sel)\n if (await el.isExisting()) {\n await el.setValue(action.value)\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n } catch { /* try next */ }\n }\n // Last resort — type via keyboard (pass whole string, not split chars)\n await driver.keys([action.value])\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n\n case 'select': {\n const { center, bounds } = resolver.resolve(action.ref)\n return {\n success: false,\n error: 'select is for HTML dropdowns. Use nativeSelect for iOS native picker wheels, or tap/swipe/tapCoordinate for custom controls.',\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n case 'nativeSelect': {\n const { center, bounds } = resolver.resolve(action.ref)\n const refData = this.lastRefs[action.ref]\n if (!isIOSNativeSelectTarget(refData)) {\n return {\n success: false,\n error: 'nativeSelect only supports native iOS picker wheels and picker controls. Use tap, swipe, or tapCoordinate for custom controls.',\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n const wheels = await findIOSPickerWheels(driver, this.lastRefs, action.ref, refData)\n if (wheels.length === 0) {\n return {\n success: false,\n error: 'Could not find an iOS picker wheel for nativeSelect. Use tap, swipe, or tapCoordinate for custom controls.',\n coordinates: center,\n boundingBox: bounds,\n }\n }\n if (wheels.length > 1) {\n return {\n success: false,\n error: 'Found multiple iOS picker wheels for nativeSelect. Do not guess which wheel to change; target a specific picker wheel or use tap/swipe/tapCoordinate.',\n coordinates: center,\n boundingBox: bounds,\n }\n }\n\n const wheel = wheels[0]\n await wheel.setValue(action.value)\n const selectedValue = await getElementValue(wheel)\n let matchStrategy: 'exact' | 'normalized' | 'setValue-accepted' = 'setValue-accepted'\n if (selectedValue === action.value) {\n matchStrategy = 'exact'\n } else if (selectedValue && normalizePickerValue(selectedValue) === normalizePickerValue(action.value)) {\n matchStrategy = 'normalized'\n } else if (selectedValue) {\n return {\n success: false,\n error: `iOS picker wheel value is \"${selectedValue}\" after nativeSelect, expected \"${action.value}\".`,\n coordinates: center,\n boundingBox: bounds,\n data: { requestedValue: action.value, matchedValue: selectedValue },\n }\n }\n\n return {\n success: true,\n coordinates: center,\n boundingBox: bounds,\n data: {\n requestedValue: action.value,\n matchedValue: selectedValue ?? action.value,\n matchStrategy,\n },\n }\n }\n\n case 'scroll': {\n // Try JS scroll in web context first (more reliable, no direction inversion)\n const webCtx = await this.getWebContext()\n if (webCtx) {\n try {\n await this.ensureContext(webCtx)\n const dx = action.scrollType === 'horizontal' ? action.value : 0\n const dy = action.scrollType === 'vertical' ? action.value : 0\n await driver.execute(\n 'window.scrollBy(arguments[0], arguments[1]);',\n dx, dy,\n )\n await this.ensureContext('NATIVE_APP')\n return { success: true }\n } catch {\n try { await this.ensureContext('NATIVE_APP') } catch { /* best-effort */ }\n }\n }\n\n // Fall back to native touch gesture scroll\n const { width, height } = await driver.getWindowSize()\n const centerX = Math.round(width / 2)\n const centerY = Math.round(height / 2)\n // Invert value for native touch: positive value = scroll down = finger swipes UP\n const scrollStartX = centerX\n const scrollStartY = centerY\n const scrollEndX = action.scrollType === 'horizontal' ? centerX - action.value : centerX\n const scrollEndY = action.scrollType === 'vertical' ? centerY - action.value : centerY\n const scrollDuration = action.duration ?? 300\n\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: scrollStartX, y: scrollStartY })\n .down({ button: 0 })\n .move({ x: scrollEndX, y: scrollEndY, duration: scrollDuration })\n .up({ button: 0 })\n )\n return { success: true }\n }\n\n case 'swipe': {\n const { width, height } = await driver.getWindowSize()\n let sx = Math.round(width / 2)\n let sy = Math.round(height / 2)\n\n if (action.ref) {\n const { center } = resolver.resolve(action.ref)\n sx = Math.round(center.x)\n sy = Math.round(center.y)\n }\n\n const distance = Math.round(height * 0.6)\n const pts = (action.startX !== undefined && action.startY !== undefined &&\n action.endX !== undefined && action.endY !== undefined)\n ? { startX: action.startX, startY: action.startY,\n endX: action.endX, endY: action.endY }\n : computeSwipe(sx, sy, action.direction, distance)\n warnIfOutOfBounds({ x: pts.startX, y: pts.startY }, { width, height }, 'swipe')\n warnIfOutOfBounds({ x: pts.endX, y: pts.endY }, { width, height }, 'swipe')\n const swipeDuration = action.duration ?? 300\n\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: pts.startX, y: pts.startY })\n .down({ button: 0 })\n .move({ x: pts.endX, y: pts.endY, duration: swipeDuration })\n .up({ button: 0 })\n )\n return {\n success: true,\n startCoordinates: { x: pts.startX, y: pts.startY },\n endCoordinates: { x: pts.endX, y: pts.endY },\n }\n }\n\n case 'pinch': {\n const { width: pinchW, height: pinchH } = await driver.getWindowSize()\n let pcx = Math.round(pinchW / 2)\n let pcy = Math.round(pinchH / 2)\n\n if (action.ref) {\n const { center } = resolver.resolve(action.ref)\n pcx = Math.round(center.x)\n pcy = Math.round(center.y)\n }\n if (action.x !== undefined) pcx = action.x\n if (action.y !== undefined) pcy = action.y\n warnIfOutOfBounds({ x: pcx, y: pcy }, { width: pinchW, height: pinchH }, 'pinch')\n\n const { finger1Start, finger1End, finger2Start, finger2End } = computePinch(pcx, pcy, action.scale)\n const pinchDuration = 500\n\n await driver.actions([\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(finger1Start.x), y: Math.round(finger1Start.y) })\n .down({ button: 0 })\n .move({ x: Math.round(finger1End.x), y: Math.round(finger1End.y), duration: pinchDuration })\n .up({ button: 0 }),\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(finger2Start.x), y: Math.round(finger2Start.y) })\n .down({ button: 0 })\n .move({ x: Math.round(finger2End.x), y: Math.round(finger2End.y), duration: pinchDuration })\n .up({ button: 0 }),\n ])\n return { success: true, coordinates: { x: pcx, y: pcy } }\n }\n\n case 'multiTap': {\n const { width: mtW, height: mtH } = await driver.getWindowSize()\n let mtcx = Math.round(mtW / 2)\n let mtcy = Math.round(mtH / 2)\n\n if (action.ref) {\n const { center } = resolver.resolve(action.ref)\n mtcx = Math.round(center.x)\n mtcy = Math.round(center.y)\n }\n if (action.x !== undefined) mtcx = action.x\n if (action.y !== undefined) mtcy = action.y\n warnIfOutOfBounds({ x: mtcx, y: mtcy }, { width: mtW, height: mtH }, 'multiTap')\n\n const positions = computeFingerPositions(mtcx, mtcy, action.fingers)\n await driver.actions(\n positions.map(pos =>\n driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(pos.x), y: Math.round(pos.y) })\n .down({ button: 0 })\n .pause(100)\n .up({ button: 0 })\n )\n )\n return { success: true }\n }\n\n case 'longpress': {\n const { center } = resolver.resolve(action.ref)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .pause(action.duration ?? 1000)\n .up({ button: 0 })\n )\n return { success: true }\n }\n\n case 'waitFor': {\n // Use timeout as a deadline, not a blind sleep — the agent loop will\n // re-observe after this returns and check the condition at a higher level.\n await driver.pause(action.timeout ?? 2000)\n return { success: true }\n }\n\n case 'delay': {\n await driver.pause(action.ms)\n return { success: true }\n }\n\n case 'keypress': {\n // convertPlatformKeys is a no-op on mobile (no Meta/Control distinction in Appium key codes per D-13)\n for (const rawKey of action.keys) {\n const mapped = KEY_MAP[rawKey] ?? rawKey\n await driver.keys([mapped])\n }\n return { success: true }\n }\n\n case 'navigate': {\n try {\n await driver.url(action.url)\n this.invalidateWebContext()\n return { success: true }\n } catch {\n return { success: false, error: 'navigate is not supported for this app. Use tap/fill on UI elements to navigate.' }\n }\n }\n\n case 'hover': {\n return { success: false, error: 'hover is a web-only action. Use tap or longpress instead.' }\n }\n\n case 'assert': {\n return { success: true }\n }\n\n // --- New actions ---\n\n case 'hideKeyboard': {\n try {\n await driver.hideKeyboard()\n } catch {\n // Keyboard may already be hidden\n }\n return { success: true }\n }\n\n case 'clearText': {\n const { center, bounds } = resolver.resolve(action.ref)\n const clearRefData = this.lastRefs[action.ref]\n const clearRole = clearRefData?.role?.toLowerCase()\n if (clearRole && !IOS_FILLABLE_ROLES.has(clearRole)) {\n return {\n success: false,\n error: `Element ${action.ref} is not fillable (role: ${clearRole}). clearText only works on text inputs. Use a textbox or input element instead.`,\n }\n }\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(center.x), y: Math.round(center.y) })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n const clearSelectors = [\n '-ios class chain:**/XCUIElementTypeTextField[`hasFocus == 1`]',\n '-ios class chain:**/XCUIElementTypeSecureTextField[`hasFocus == 1`]',\n '-ios class chain:**/XCUIElementTypeSearchField[`hasFocus == 1`]',\n '-ios class chain:**/XCUIElementTypeSearchField',\n '-ios class chain:**/XCUIElementTypeTextField',\n '-ios class chain:**/XCUIElementTypeSecureTextField',\n ]\n for (const sel of clearSelectors) {\n try {\n const el = await driver.$(sel)\n if (await el.isExisting()) {\n await el.clearValue()\n break\n }\n } catch { /* try next */ }\n }\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n\n case 'openLink': {\n const bundleId = firstNonEmpty(action.appId, action.bundleId, this.bundleId)\n const isWebUrl = /^https?:\\/\\//i.test(action.url)\n if (!bundleId && !isWebUrl) {\n return { success: false, error: `Missing iOS bundle id for native deep link: ${action.url}` }\n }\n try {\n if (bundleId) {\n const deepLink = (driver as any).deepLink as undefined | ((url: string, appId: string, waitForLaunch?: boolean) => Promise<void>)\n if (typeof deepLink === 'function') {\n await deepLink.call(driver, action.url, bundleId, action.waitForLaunch ?? true)\n } else {\n await driver.execute('mobile: deepLink', { url: action.url, bundleId })\n }\n } else {\n await driver.url(action.url)\n }\n this.invalidateWebContext()\n return { success: true }\n } catch (err) {\n return { success: false, error: `Failed to open link ${action.url}${bundleId ? ` in iOS app ${bundleId}` : ''}: ${err instanceof Error ? err.message : String(err)}` }\n }\n }\n\n case 'drag': {\n const from = resolver.resolve(action.fromRef)\n const to = resolver.resolve(action.toRef)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x: Math.round(from.center.x), y: Math.round(from.center.y) })\n .down({ button: 0 })\n .pause(300)\n .move({ x: Math.round(to.center.x), y: Math.round(to.center.y), duration: 500 })\n .up({ button: 0 })\n )\n return { success: true }\n }\n\n case 'doubleTap': {\n const { center, bounds } = resolver.resolve(action.ref)\n const x = Math.round(center.x)\n const y = Math.round(center.y)\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x, y })\n .down({ button: 0 })\n .up({ button: 0 })\n .pause(50)\n .down({ button: 0 })\n .up({ button: 0 })\n )\n return { success: true, coordinates: center, boundingBox: bounds }\n }\n\n case 'launchApp': {\n await driver.activateApp(action.bundleId)\n return { success: true }\n }\n\n case 'stopApp': {\n await driver.terminateApp(action.bundleId)\n return { success: true }\n }\n\n case 'setOrientation': {\n await driver.setOrientation(action.orientation === 'landscape' ? 'LANDSCAPE' : 'PORTRAIT')\n return { success: true }\n }\n\n case 'executeScript': {\n const result = await driver.execute(action.command, action.args ?? {})\n return { success: true, data: result }\n }\n\n case 'tapCoordinate': {\n const x = action.x\n const y = action.y\n const tcVp = await driver.getWindowSize()\n warnIfOutOfBounds({ x, y }, { width: tcVp.width, height: tcVp.height }, 'tapCoordinate')\n await safePerform(driver.action('pointer', { parameters: { pointerType: 'touch' } })\n .move({ x, y })\n .down({ button: 0 })\n .up({ button: 0 })\n )\n return { success: true, coordinates: { x, y } }\n }\n\n case 'readConsoleLogs': {\n await this.pollDeviceLogs()\n const all = [...this.consoleLogs]\n const entries = action.level ? all.filter(e => e.level === action.level) : all\n return { success: true, data: entries }\n }\n\n default: {\n return { success: false, error: `Unknown action type: ${(action as any).type}` }\n }\n }\n }\n}\n","import { remote } from 'webdriverio'\nimport type { IOSAdapterConfig } from './types.js'\n\nexport async function createIOSSession(\n config: IOSAdapterConfig,\n farmSession?: { hostname: string; port: number; path: string; capabilities: Record<string, unknown> },\n) {\n const match = config.device?.match ?? {}\n const appiumUrl = process.env.AGENT_QA_APPIUM_URL ?? config.appiumUrl ?? 'http://localhost:4723'\n const url = new URL(appiumUrl)\n const browserName = typeof match.browserName === 'string' && match.browserName.trim().length > 0\n ? match.browserName.trim()\n : undefined\n const appStateNoReset =\n config.appState === 'preserve' ? true :\n config.appState === 'reset' ? false :\n undefined\n\n const capabilities: Record<string, unknown> = {\n platformName: 'iOS',\n 'appium:automationName': (match.automationName as string) ?? 'XCUITest',\n 'appium:deviceName': config.device?.name ?? 'iPhone Simulator',\n 'appium:showIOSLog': true,\n 'appium:newCommandTimeout': config.timeouts?.test ? Math.ceil(config.timeouts.test / 1000) : 300,\n }\n\n if (!browserName && appStateNoReset !== undefined) capabilities['appium:noReset'] = appStateNoReset\n\n if (match.platformVersion) capabilities['appium:platformVersion'] = match.platformVersion\n if (match.bundleId) capabilities['appium:bundleId'] = match.bundleId\n if (config.bundleId) capabilities['appium:bundleId'] = config.bundleId\n if (config.appPath) capabilities['appium:app'] = config.appPath\n if (match.udid) capabilities['appium:udid'] = match.udid\n if (config.udid) capabilities['appium:udid'] = config.udid\n\n // Strip undefined values\n for (const key of Object.keys(capabilities)) {\n if (capabilities[key] === undefined) {\n delete capabilities[key]\n }\n }\n\n if (farmSession) {\n Object.assign(capabilities, farmSession.capabilities)\n return remote({\n protocol: 'https',\n hostname: farmSession.hostname,\n port: farmSession.port,\n path: farmSession.path,\n logLevel: config.verbose ? 'info' : 'silent',\n capabilities: capabilities as WebdriverIO.Capabilities,\n })\n }\n\n return remote({\n hostname: url.hostname,\n port: parseInt(url.port || '4723', 10),\n path: url.pathname === '/' ? '/' : url.pathname,\n logLevel: config.verbose ? 'info' : 'silent',\n capabilities: capabilities as WebdriverIO.Capabilities,\n })\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,44 @@
1
+ import { PlatformAdapter, PlatformConfig, ObserveOptions, ScreenState, Action, ActionResult, ConsoleLogEntry } from '@vostride/agent-qa-core';
2
+
3
+ declare class IOSPlatformAdapter implements PlatformAdapter {
4
+ readonly platform: "ios";
5
+ private driver;
6
+ private lastRefs;
7
+ private config;
8
+ private activeWebContext;
9
+ private webContextChecked;
10
+ private currentContext;
11
+ private consoleLogs;
12
+ private consoleDrainIndex;
13
+ private captureConsole;
14
+ private bundleId;
15
+ setup(config: PlatformConfig): Promise<void>;
16
+ cleanup(): Promise<void>;
17
+ observe(_options?: ObserveOptions): Promise<ScreenState>;
18
+ execute(action: Action): Promise<ActionResult>;
19
+ screenshot(): Promise<Buffer | undefined>;
20
+ pollDeviceLogs(): Promise<void>;
21
+ drainConsoleLogs(level?: string): ConsoleLogEntry[];
22
+ /** Lazily detect the WEBVIEW context. Cached after first lookup. */
23
+ private getWebContext;
24
+ /** Invalidate the cached web context so next getWebContext() re-queries. */
25
+ private invalidateWebContext;
26
+ private ensureContext;
27
+ private captureScreenshot;
28
+ private executeAction;
29
+ }
30
+
31
+ interface IOSAdapterConfig extends PlatformConfig {
32
+ appiumUrl?: string;
33
+ bundleId?: string;
34
+ udid?: string;
35
+ }
36
+
37
+ declare function createIOSSession(config: IOSAdapterConfig, farmSession?: {
38
+ hostname: string;
39
+ port: number;
40
+ path: string;
41
+ capabilities: Record<string, unknown>;
42
+ }): Promise<WebdriverIO.Browser>;
43
+
44
+ export { type IOSAdapterConfig, IOSPlatformAdapter, createIOSSession };
@@ -0,0 +1,44 @@
1
+ import { PlatformAdapter, PlatformConfig, ObserveOptions, ScreenState, Action, ActionResult, ConsoleLogEntry } from '@vostride/agent-qa-core';
2
+
3
+ declare class IOSPlatformAdapter implements PlatformAdapter {
4
+ readonly platform: "ios";
5
+ private driver;
6
+ private lastRefs;
7
+ private config;
8
+ private activeWebContext;
9
+ private webContextChecked;
10
+ private currentContext;
11
+ private consoleLogs;
12
+ private consoleDrainIndex;
13
+ private captureConsole;
14
+ private bundleId;
15
+ setup(config: PlatformConfig): Promise<void>;
16
+ cleanup(): Promise<void>;
17
+ observe(_options?: ObserveOptions): Promise<ScreenState>;
18
+ execute(action: Action): Promise<ActionResult>;
19
+ screenshot(): Promise<Buffer | undefined>;
20
+ pollDeviceLogs(): Promise<void>;
21
+ drainConsoleLogs(level?: string): ConsoleLogEntry[];
22
+ /** Lazily detect the WEBVIEW context. Cached after first lookup. */
23
+ private getWebContext;
24
+ /** Invalidate the cached web context so next getWebContext() re-queries. */
25
+ private invalidateWebContext;
26
+ private ensureContext;
27
+ private captureScreenshot;
28
+ private executeAction;
29
+ }
30
+
31
+ interface IOSAdapterConfig extends PlatformConfig {
32
+ appiumUrl?: string;
33
+ bundleId?: string;
34
+ udid?: string;
35
+ }
36
+
37
+ declare function createIOSSession(config: IOSAdapterConfig, farmSession?: {
38
+ hostname: string;
39
+ port: number;
40
+ path: string;
41
+ capabilities: Record<string, unknown>;
42
+ }): Promise<WebdriverIO.Browser>;
43
+
44
+ export { type IOSAdapterConfig, IOSPlatformAdapter, createIOSSession };