From 10ace7edc6d8c22a89c59fbf930bd3fc61726547 Mon Sep 17 00:00:00 2001 From: tech-sushant Date: Sun, 9 Nov 2025 03:40:38 +0530 Subject: [PATCH 1/4] refactor: update device handling in App Automate tools to use object format and improve validation --- .../appautomate-utils/appium-sdk/constants.ts | 28 +----- .../appautomate-utils/appium-sdk/handler.ts | 13 ++- .../native-execution/constants.ts | 29 +----- src/tools/appautomate.ts | 15 ++- src/tools/sdk-utils/bstack/sdkHandler.ts | 41 +++++++- .../sdk-utils/common/device-validator.ts | 32 ++++++- src/tools/sdk-utils/common/schema.ts | 93 +++++++++---------- 7 files changed, 137 insertions(+), 114 deletions(-) diff --git a/src/tools/appautomate-utils/appium-sdk/constants.ts b/src/tools/appautomate-utils/appium-sdk/constants.ts index 5b9a249..828956f 100644 --- a/src/tools/appautomate-utils/appium-sdk/constants.ts +++ b/src/tools/appautomate-utils/appium-sdk/constants.ts @@ -5,6 +5,7 @@ import { AppSDKSupportedLanguageEnum, AppSDKSupportedPlatformEnum, } from "./index.js"; +import { MobileDeviceSchema } from "../../sdk-utils/common/schema.js"; // App Automate specific device configurations export const APP_DEVICE_CONFIGS = { @@ -50,34 +51,11 @@ export const SETUP_APP_AUTOMATE_SCHEMA = { ), devices: z - .array( - z.union([ - // Android: [android, deviceName, osVersion] - z.tuple([ - z - .literal(AppSDKSupportedPlatformEnum.android) - .describe("Platform identifier: 'android'"), - z - .string() - .describe( - "Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'", - ), - z.string().describe("Android version, e.g. '14', '16', 'latest'"), - ]), - // iOS: [ios, deviceName, osVersion] - z.tuple([ - z - .literal(AppSDKSupportedPlatformEnum.ios) - .describe("Platform identifier: 'ios'"), - z.string().describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"), - z.string().describe("iOS version, e.g. '17', '16', 'latest'"), - ]), - ]), - ) + .array(MobileDeviceSchema) .max(3) .default([]) .describe( - "Tuples describing target mobile devices. Add device only when user asks explicitly for it. Defaults to [] . Example: [['android', 'Samsung Galaxy S24', '14'], ['ios', 'iPhone 15', '17']]", + "Mobile device objects array. Use the object format directly - no transformation needed. Add only when user explicitly requests devices. Examples: [{ platform: 'android', deviceName: 'Samsung Galaxy S24', osVersion: '14' }] or [{ platform: 'ios', deviceName: 'iPhone 15', osVersion: '17' }].", ), appPath: z diff --git a/src/tools/appautomate-utils/appium-sdk/handler.ts b/src/tools/appautomate-utils/appium-sdk/handler.ts index 0a24358..bce31c7 100644 --- a/src/tools/appautomate-utils/appium-sdk/handler.ts +++ b/src/tools/appautomate-utils/appium-sdk/handler.ts @@ -2,7 +2,10 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { BrowserStackConfig } from "../../../lib/types.js"; import { getBrowserStackAuth } from "../../../lib/get-auth.js"; -import { validateAppAutomateDevices } from "../../sdk-utils/common/device-validator.js"; +import { + validateAppAutomateDevices, + convertMobileDevicesToTuples, +} from "../../sdk-utils/common/device-validator.js"; import { getAppUploadInstruction, @@ -38,18 +41,18 @@ export async function setupAppAutomateHandler( const testingFramework = input.detectedTestingFramework as AppSDKSupportedTestingFramework; const language = input.detectedLanguage as AppSDKSupportedLanguage; - const inputDevices = (input.devices as Array>) ?? []; const appPath = input.appPath as string; const framework = input.detectedFramework as SupportedFramework; //Validating if supported framework or not validateSupportforAppAutomate(framework, language, testingFramework); - // Use default mobile devices when array is empty - const devices = + // Convert device objects to tuples for validator + const inputDevices = input.devices || []; + const devices: Array> = inputDevices.length === 0 ? [["android", "Samsung Galaxy S24", "latest"]] - : inputDevices; + : convertMobileDevicesToTuples(inputDevices); // Validate devices against real BrowserStack device data const validatedEnvironments = await validateAppAutomateDevices(devices); diff --git a/src/tools/appautomate-utils/native-execution/constants.ts b/src/tools/appautomate-utils/native-execution/constants.ts index 9239a43..595cd98 100644 --- a/src/tools/appautomate-utils/native-execution/constants.ts +++ b/src/tools/appautomate-utils/native-execution/constants.ts @@ -1,6 +1,6 @@ import { z } from "zod"; import { AppTestPlatform } from "./types.js"; -import { AppSDKSupportedPlatformEnum } from "../appium-sdk/types.js"; +import { MobileDeviceSchema } from "../../sdk-utils/common/schema.js"; export const RUN_APP_AUTOMATE_DESCRIPTION = `Execute pre-built native mobile test suites (Espresso for Android, XCUITest for iOS) by direct upload to BrowserStack. ONLY for compiled .apk/.ipa test files. This is NOT for SDK integration or Appium tests. For Appium-based testing with SDK setup, use 'setupBrowserStackAppAutomateTests' instead.`; @@ -30,34 +30,11 @@ export const RUN_APP_AUTOMATE_SCHEMA = { "If in other directory, provide existing test file path", ), devices: z - .array( - z.union([ - // Android: [android, deviceName, osVersion] - z.tuple([ - z - .literal(AppSDKSupportedPlatformEnum.android) - .describe("Platform identifier: 'android'"), - z - .string() - .describe( - "Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'", - ), - z.string().describe("Android version, e.g. '14', '16', 'latest'"), - ]), - // iOS: [ios, deviceName, osVersion] - z.tuple([ - z - .literal(AppSDKSupportedPlatformEnum.ios) - .describe("Platform identifier: 'ios'"), - z.string().describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"), - z.string().describe("iOS version, e.g. '17', '16', 'latest'"), - ]), - ]), - ) + .array(MobileDeviceSchema) .max(3) .default([]) .describe( - "Tuples describing target mobile devices. Add device only when user asks explicitly for it. Defaults to [] . Example: [['android', 'Samsung Galaxy S24', '14'], ['ios', 'iPhone 15', '17']]", + "Mobile device objects array. Use the object format directly - no transformation needed. Add only when user explicitly requests devices. Examples: [{ platform: 'android', deviceName: 'Samsung Galaxy S24', osVersion: '14' }] or [{ platform: 'ios', deviceName: 'iPhone 15', osVersion: '17' }].", ), project: z .string() diff --git a/src/tools/appautomate.ts b/src/tools/appautomate.ts index 29a7d57..23a7a69 100644 --- a/src/tools/appautomate.ts +++ b/src/tools/appautomate.ts @@ -9,7 +9,10 @@ import { maybeCompressBase64 } from "../lib/utils.js"; import { remote } from "webdriverio"; import { AppTestPlatform } from "./appautomate-utils/native-execution/types.js"; import { setupAppAutomateHandler } from "./appautomate-utils/appium-sdk/handler.js"; -import { validateAppAutomateDevices } from "./sdk-utils/common/device-validator.js"; +import { + validateAppAutomateDevices, + convertMobileDevicesToTuples, +} from "./sdk-utils/common/device-validator.js"; import { SETUP_APP_AUTOMATE_DESCRIPTION, @@ -378,7 +381,15 @@ export default function addAppAutomationTools( undefined, config, ); - return await runAppTestsOnBrowserStack(args, config); + // Convert device objects to tuples for the handler + const devices: Array> = + (args.devices || []).length === 0 + ? [["android", "Samsung Galaxy S24", "latest"]] + : convertMobileDevicesToTuples(args.devices || []); + return await runAppTestsOnBrowserStack( + { ...args, devices }, + config, + ); } catch (error) { trackMCP( "runAppTestsOnBrowserStack", diff --git a/src/tools/sdk-utils/bstack/sdkHandler.ts b/src/tools/sdk-utils/bstack/sdkHandler.ts index 54171d4..e5edeaa 100644 --- a/src/tools/sdk-utils/bstack/sdkHandler.ts +++ b/src/tools/sdk-utils/bstack/sdkHandler.ts @@ -22,13 +22,44 @@ export async function runBstackSDKOnly( const authString = getBrowserStackAuth(config); const [username, accessKey] = authString.split(":"); - // Validate devices against real BrowserStack device data - const tupleTargets = (input as any).devices as - | Array> - | undefined; + // Convert device objects to tuples for validator + const devices = input.devices || []; + const tupleTargets: Array> = devices.map((device) => { + if (device.platform === "windows") { + return [ + "windows", + device.osVersion, + device.browser, + device.browserVersion || "latest", + ]; + } else if (device.platform === "mac" || device.platform === "macos") { + return [ + "macos", + device.osVersion, + device.browser, + device.browserVersion || "latest", + ]; + } else if (device.platform === "android") { + return [ + "android", + device.deviceName, + device.osVersion, + device.browser || "chrome", + ]; + } else if (device.platform === "ios") { + return [ + "ios", + device.deviceName, + device.osVersion, + device.browser || "safari", + ]; + } else { + throw new Error(`Unsupported platform: ${device.platform}`); + } + }); const validatedEnvironments = await validateDevices( - tupleTargets || [], + tupleTargets, input.detectedBrowserAutomationFramework, ); diff --git a/src/tools/sdk-utils/common/device-validator.ts b/src/tools/sdk-utils/common/device-validator.ts index d2047b2..10e4191 100644 --- a/src/tools/sdk-utils/common/device-validator.ts +++ b/src/tools/sdk-utils/common/device-validator.ts @@ -230,10 +230,19 @@ export async function validateDevices( } // Determine what data we need to fetch - const needsDesktop = devices.some((env) => + // Normalize "mac" to "macos" for consistency + const normalizedDevices = devices.map((env) => { + const platform = (env[0] || "").toLowerCase(); + if (platform === "mac") { + return ["macos", ...env.slice(1)]; + } + return env; + }); + + const needsDesktop = normalizedDevices.some((env) => ["windows", "macos"].includes((env[0] || "").toLowerCase()), ); - const needsMobile = devices.some((env) => + const needsMobile = normalizedDevices.some((env) => ["android", "ios"].includes((env[0] || "").toLowerCase()), ); @@ -275,7 +284,7 @@ export async function validateDevices( iosIndex = createMobileIndex(iosEntries); } - for (const env of devices) { + for (const env of normalizedDevices) { const discriminator = (env[0] || "").toLowerCase(); let validatedEnv: ValidatedEnvironment; @@ -621,6 +630,23 @@ export async function validateAppAutomateDevices( // SHARED UTILITY FUNCTIONS // ============================================================================ +/** + * Convert mobile device objects to tuples for validators + * @param devices Array of device objects with platform, deviceName, osVersion + * @returns Array of tuples [platform, deviceName, osVersion] + */ +export function convertMobileDevicesToTuples( + devices: Array<{ platform: string; deviceName: string; osVersion: string }>, +): Array> { + return devices.map((device) => { + if (device.platform === "android" || device.platform === "ios") { + return [device.platform, device.deviceName, device.osVersion]; + } else { + throw new Error(`Unsupported platform: ${device.platform}`); + } + }); +} + // Exact browser validation (preferred for structured fields) function validateBrowserExact( requestedBrowser: string, diff --git a/src/tools/sdk-utils/common/schema.ts b/src/tools/sdk-utils/common/schema.ts index 39c5cb4..337f07f 100644 --- a/src/tools/sdk-utils/common/schema.ts +++ b/src/tools/sdk-utils/common/schema.ts @@ -48,67 +48,64 @@ export const SetUpPercyParamsShape = { ), }; +// Shared mobile device schema for App Automate (no browser field) +export const MobileDeviceSchema = z.discriminatedUnion("platform", [ + z.object({ + platform: z.literal("android"), + deviceName: z.string().describe("Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'"), + osVersion: z.string().describe("Android version, e.g. '14', '16', 'latest'"), + }), + z.object({ + platform: z.literal("ios"), + deviceName: z.string().describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"), + osVersion: z.string().describe("iOS version, e.g. '17', '16', 'latest'"), + }), +]); + +const DeviceSchema = z.discriminatedUnion("platform", [ + z.object({ + platform: z.literal("windows"), + osVersion: z.string().describe("Windows version, e.g. '10', '11'"), + browser: z.string().describe("Browser name, e.g. 'chrome', 'firefox', 'edge'"), + browserVersion: z.string().describe("Browser version, e.g. '132', 'latest', 'oldest'"), + }), + z.object({ + platform: z.literal("android"), + deviceName: z.string().describe("Device name, e.g. 'Samsung Galaxy S24'"), + osVersion: z.string().describe("Android version, e.g. '14', '16', 'latest'"), + browser: z.string().describe("Browser name, e.g. 'chrome', 'samsung browser'"), + }), + z.object({ + platform: z.literal("ios"), + deviceName: z.string().describe("Device name, e.g. 'iPhone 12 Pro'"), + osVersion: z.string().describe("iOS version, e.g. '17', 'latest'"), + browser: z.string().describe("Browser name, typically 'safari'"), + }), + z.object({ + platform: z.enum(["mac", "macos"]), + osVersion: z.string().describe("macOS version name, e.g. 'Sequoia', 'Ventura'"), + browser: z.string().describe("Browser name, e.g. 'safari', 'chrome'"), + browserVersion: z.string().describe("Browser version, e.g. 'latest'"), + }), +]); + export const RunTestsOnBrowserStackParamsShape = { projectName: z .string() .describe("A single name for your project to organize all your tests."), detectedLanguage: z.nativeEnum(SDKSupportedLanguageEnum), - detectedBrowserAutomationFramework: z.nativeEnum( - SDKSupportedBrowserAutomationFrameworkEnum, - ), + detectedBrowserAutomationFramework: z.nativeEnum(SDKSupportedBrowserAutomationFrameworkEnum), detectedTestingFramework: z.nativeEnum(SDKSupportedTestingFrameworkEnum), devices: z - .array( - z.union([ - // Windows: [windows, osVersion, browser, browserVersion] - z.tuple([ - z - .nativeEnum(WindowsPlatformEnum) - .describe("Platform identifier: 'windows'"), - z.string().describe("Windows version, e.g. '10', '11'"), - z.string().describe("Browser name, e.g. 'chrome', 'firefox', 'edge'"), - z - .string() - .describe("Browser version, e.g. '132', 'latest', 'oldest'"), - ]), - // Android: [android, name, model, osVersion, browser] - z.tuple([ - z - .literal(PlatformEnum.ANDROID) - .describe("Platform identifier: 'android'"), - z - .string() - .describe( - "Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'", - ), - z.string().describe("Android version, e.g. '14', '16', 'latest'"), - z.string().describe("Browser name, e.g. 'chrome', 'samsung browser'"), - ]), - // iOS: [ios, name, model, osVersion, browser] - z.tuple([ - z.literal(PlatformEnum.IOS).describe("Platform identifier: 'ios'"), - z.string().describe("Device name, e.g. 'iPhone 12 Pro'"), - z.string().describe("iOS version, e.g. '17', 'latest'"), - z.string().describe("Browser name, typically 'safari'"), - ]), - // macOS: [mac|macos, name, model, browser, browserVersion] - z.tuple([ - z - .nativeEnum(MacOSPlatformEnum) - .describe("Platform identifier: 'mac' or 'macos'"), - z.string().describe("macOS version name, e.g. 'Sequoia', 'Ventura'"), - z.string().describe("Browser name, e.g. 'safari', 'chrome'"), - z.string().describe("Browser version, e.g. 'latest'"), - ]), - ]), - ) + .array(DeviceSchema) .max(3) .default([]) .describe( - "Preferred tuples of target devices.Add device only when user asks explicitly for it. Defaults to [] . Example: [['windows', '11', 'chrome', 'latest']]", + "Device objects array. Use the object format directly - no transformation needed. Add only when user explicitly requests devices. Examples: [{ platform: 'windows', osVersion: '11', browser: 'chrome', browserVersion: 'latest' }] or [{ platform: 'android', deviceName: 'Samsung Galaxy S24', osVersion: '14', browser: 'chrome' }].", ), }; + export const SetUpPercySchema = z.object(SetUpPercyParamsShape); export const RunTestsOnBrowserStackSchema = z.object( From ff9a638cd757ef683526e35bcec35e79e00f07f5 Mon Sep 17 00:00:00 2001 From: tech-sushant Date: Sun, 9 Nov 2025 21:49:24 +0530 Subject: [PATCH 2/4] refactor: standardize platform naming and improve device validation logic --- src/tools/sdk-utils/bstack/sdkHandler.ts | 2 +- .../sdk-utils/common/device-validator.ts | 15 ++-------- src/tools/sdk-utils/common/schema.ts | 30 ++++++++++++++----- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/tools/sdk-utils/bstack/sdkHandler.ts b/src/tools/sdk-utils/bstack/sdkHandler.ts index e5edeaa..59819c4 100644 --- a/src/tools/sdk-utils/bstack/sdkHandler.ts +++ b/src/tools/sdk-utils/bstack/sdkHandler.ts @@ -32,7 +32,7 @@ export async function runBstackSDKOnly( device.browser, device.browserVersion || "latest", ]; - } else if (device.platform === "mac" || device.platform === "macos") { + } else if (device.platform === "macos") { return [ "macos", device.osVersion, diff --git a/src/tools/sdk-utils/common/device-validator.ts b/src/tools/sdk-utils/common/device-validator.ts index 10e4191..0b5637e 100644 --- a/src/tools/sdk-utils/common/device-validator.ts +++ b/src/tools/sdk-utils/common/device-validator.ts @@ -230,19 +230,10 @@ export async function validateDevices( } // Determine what data we need to fetch - // Normalize "mac" to "macos" for consistency - const normalizedDevices = devices.map((env) => { - const platform = (env[0] || "").toLowerCase(); - if (platform === "mac") { - return ["macos", ...env.slice(1)]; - } - return env; - }); - - const needsDesktop = normalizedDevices.some((env) => + const needsDesktop = devices.some((env) => ["windows", "macos"].includes((env[0] || "").toLowerCase()), ); - const needsMobile = normalizedDevices.some((env) => + const needsMobile = devices.some((env) => ["android", "ios"].includes((env[0] || "").toLowerCase()), ); @@ -284,7 +275,7 @@ export async function validateDevices( iosIndex = createMobileIndex(iosEntries); } - for (const env of normalizedDevices) { + for (const env of devices) { const discriminator = (env[0] || "").toLowerCase(); let validatedEnv: ValidatedEnvironment; diff --git a/src/tools/sdk-utils/common/schema.ts b/src/tools/sdk-utils/common/schema.ts index 337f07f..7da40c3 100644 --- a/src/tools/sdk-utils/common/schema.ts +++ b/src/tools/sdk-utils/common/schema.ts @@ -67,25 +67,41 @@ const DeviceSchema = z.discriminatedUnion("platform", [ platform: z.literal("windows"), osVersion: z.string().describe("Windows version, e.g. '10', '11'"), browser: z.string().describe("Browser name, e.g. 'chrome', 'firefox', 'edge'"), - browserVersion: z.string().describe("Browser version, e.g. '132', 'latest', 'oldest'"), + browserVersion: z + .string() + .optional() + .describe("Browser version, e.g. '132', 'latest', 'oldest'"), }), z.object({ platform: z.literal("android"), - deviceName: z.string().describe("Device name, e.g. 'Samsung Galaxy S24'"), + deviceName: z + .string() + .describe("Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'"), osVersion: z.string().describe("Android version, e.g. '14', '16', 'latest'"), - browser: z.string().describe("Browser name, e.g. 'chrome', 'samsung browser'"), + browser: z + .string() + .optional() + .describe("Browser name, e.g. 'chrome', 'samsung browser'"), }), z.object({ platform: z.literal("ios"), - deviceName: z.string().describe("Device name, e.g. 'iPhone 12 Pro'"), + deviceName: z + .string() + .describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"), osVersion: z.string().describe("iOS version, e.g. '17', 'latest'"), - browser: z.string().describe("Browser name, typically 'safari'"), + browser: z + .string() + .optional() + .describe("Browser name, typically 'safari'"), }), z.object({ - platform: z.enum(["mac", "macos"]), + platform: z.literal("macos"), osVersion: z.string().describe("macOS version name, e.g. 'Sequoia', 'Ventura'"), browser: z.string().describe("Browser name, e.g. 'safari', 'chrome'"), - browserVersion: z.string().describe("Browser version, e.g. 'latest'"), + browserVersion: z + .string() + .optional() + .describe("Browser version, e.g. 'latest'"), }), ]); From da2cb9f6b7ae23834bbd6de60996e6f9447cecd8 Mon Sep 17 00:00:00 2001 From: tech-sushant Date: Sun, 9 Nov 2025 22:06:44 +0530 Subject: [PATCH 3/4] refactor: introduce DEFAULT_MOBILE_DEVICE for improved device handling in App Automate tools --- src/tools/appautomate-utils/appium-sdk/handler.ts | 8 ++++---- src/tools/appautomate.ts | 7 ++++--- src/tools/sdk-utils/common/device-validator.ts | 5 +++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/tools/appautomate-utils/appium-sdk/handler.ts b/src/tools/appautomate-utils/appium-sdk/handler.ts index bce31c7..80492c6 100644 --- a/src/tools/appautomate-utils/appium-sdk/handler.ts +++ b/src/tools/appautomate-utils/appium-sdk/handler.ts @@ -5,6 +5,7 @@ import { getBrowserStackAuth } from "../../../lib/get-auth.js"; import { validateAppAutomateDevices, convertMobileDevicesToTuples, + DEFAULT_MOBILE_DEVICE, } from "../../sdk-utils/common/device-validator.js"; import { @@ -48,11 +49,10 @@ export async function setupAppAutomateHandler( validateSupportforAppAutomate(framework, language, testingFramework); // Convert device objects to tuples for validator - const inputDevices = input.devices || []; const devices: Array> = - inputDevices.length === 0 - ? [["android", "Samsung Galaxy S24", "latest"]] - : convertMobileDevicesToTuples(inputDevices); + input.devices.length === 0 + ? DEFAULT_MOBILE_DEVICE + : convertMobileDevicesToTuples(input.devices); // Validate devices against real BrowserStack device data const validatedEnvironments = await validateAppAutomateDevices(devices); diff --git a/src/tools/appautomate.ts b/src/tools/appautomate.ts index 23a7a69..3a3e350 100644 --- a/src/tools/appautomate.ts +++ b/src/tools/appautomate.ts @@ -12,6 +12,7 @@ import { setupAppAutomateHandler } from "./appautomate-utils/appium-sdk/handler. import { validateAppAutomateDevices, convertMobileDevicesToTuples, + DEFAULT_MOBILE_DEVICE, } from "./sdk-utils/common/device-validator.js"; import { @@ -383,9 +384,9 @@ export default function addAppAutomationTools( ); // Convert device objects to tuples for the handler const devices: Array> = - (args.devices || []).length === 0 - ? [["android", "Samsung Galaxy S24", "latest"]] - : convertMobileDevicesToTuples(args.devices || []); + args.devices.length === 0 + ? DEFAULT_MOBILE_DEVICE + : convertMobileDevicesToTuples(args.devices); return await runAppTestsOnBrowserStack( { ...args, devices }, config, diff --git a/src/tools/sdk-utils/common/device-validator.ts b/src/tools/sdk-utils/common/device-validator.ts index 0b5637e..1bdae28 100644 --- a/src/tools/sdk-utils/common/device-validator.ts +++ b/src/tools/sdk-utils/common/device-validator.ts @@ -72,6 +72,11 @@ const DEFAULTS = { ios: { device: "iPhone 15", browser: "safari" }, } as const; +// Default mobile device tuple for App Automate when no devices are provided +export const DEFAULT_MOBILE_DEVICE: Array> = [ + ["android", "Samsung Galaxy S24", "latest"], +]; + // Performance optimization: Indexed maps for faster lookups interface DesktopIndex { byOS: Map; From ada7046947b9e2255047196218f0843ac5d48ad2 Mon Sep 17 00:00:00 2001 From: tech-sushant Date: Mon, 10 Nov 2025 01:59:39 +0530 Subject: [PATCH 4/4] linting ++ --- .../appautomate-utils/appium-sdk/constants.ts | 1 - src/tools/appautomate.ts | 5 +-- src/tools/sdk-utils/bstack/sdkHandler.ts | 11 +++--- src/tools/sdk-utils/common/schema.ts | 34 ++++++++++++------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/tools/appautomate-utils/appium-sdk/constants.ts b/src/tools/appautomate-utils/appium-sdk/constants.ts index 828956f..c132800 100644 --- a/src/tools/appautomate-utils/appium-sdk/constants.ts +++ b/src/tools/appautomate-utils/appium-sdk/constants.ts @@ -3,7 +3,6 @@ import { AppSDKSupportedFrameworkEnum, AppSDKSupportedTestingFrameworkEnum, AppSDKSupportedLanguageEnum, - AppSDKSupportedPlatformEnum, } from "./index.js"; import { MobileDeviceSchema } from "../../sdk-utils/common/schema.js"; diff --git a/src/tools/appautomate.ts b/src/tools/appautomate.ts index 3a3e350..502acd0 100644 --- a/src/tools/appautomate.ts +++ b/src/tools/appautomate.ts @@ -387,10 +387,7 @@ export default function addAppAutomationTools( args.devices.length === 0 ? DEFAULT_MOBILE_DEVICE : convertMobileDevicesToTuples(args.devices); - return await runAppTestsOnBrowserStack( - { ...args, devices }, - config, - ); + return await runAppTestsOnBrowserStack({ ...args, devices }, config); } catch (error) { trackMCP( "runAppTestsOnBrowserStack", diff --git a/src/tools/sdk-utils/bstack/sdkHandler.ts b/src/tools/sdk-utils/bstack/sdkHandler.ts index 59819c4..312acd4 100644 --- a/src/tools/sdk-utils/bstack/sdkHandler.ts +++ b/src/tools/sdk-utils/bstack/sdkHandler.ts @@ -25,28 +25,29 @@ export async function runBstackSDKOnly( // Convert device objects to tuples for validator const devices = input.devices || []; const tupleTargets: Array> = devices.map((device) => { - if (device.platform === "windows") { + const platform = device.platform; + if (platform === "windows") { return [ "windows", device.osVersion, device.browser, device.browserVersion || "latest", ]; - } else if (device.platform === "macos") { + } else if (platform === "macos") { return [ "macos", device.osVersion, device.browser, device.browserVersion || "latest", ]; - } else if (device.platform === "android") { + } else if (platform === "android") { return [ "android", device.deviceName, device.osVersion, device.browser || "chrome", ]; - } else if (device.platform === "ios") { + } else if (platform === "ios") { return [ "ios", device.deviceName, @@ -54,7 +55,7 @@ export async function runBstackSDKOnly( device.browser || "safari", ]; } else { - throw new Error(`Unsupported platform: ${device.platform}`); + throw new Error(`Unsupported platform: ${platform}`); } }); diff --git a/src/tools/sdk-utils/common/schema.ts b/src/tools/sdk-utils/common/schema.ts index 7da40c3..351ed27 100644 --- a/src/tools/sdk-utils/common/schema.ts +++ b/src/tools/sdk-utils/common/schema.ts @@ -52,12 +52,18 @@ export const SetUpPercyParamsShape = { export const MobileDeviceSchema = z.discriminatedUnion("platform", [ z.object({ platform: z.literal("android"), - deviceName: z.string().describe("Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'"), - osVersion: z.string().describe("Android version, e.g. '14', '16', 'latest'"), + deviceName: z + .string() + .describe("Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'"), + osVersion: z + .string() + .describe("Android version, e.g. '14', '16', 'latest'"), }), z.object({ platform: z.literal("ios"), - deviceName: z.string().describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"), + deviceName: z + .string() + .describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"), osVersion: z.string().describe("iOS version, e.g. '17', '16', 'latest'"), }), ]); @@ -66,7 +72,9 @@ const DeviceSchema = z.discriminatedUnion("platform", [ z.object({ platform: z.literal("windows"), osVersion: z.string().describe("Windows version, e.g. '10', '11'"), - browser: z.string().describe("Browser name, e.g. 'chrome', 'firefox', 'edge'"), + browser: z + .string() + .describe("Browser name, e.g. 'chrome', 'firefox', 'edge'"), browserVersion: z .string() .optional() @@ -77,7 +85,9 @@ const DeviceSchema = z.discriminatedUnion("platform", [ deviceName: z .string() .describe("Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'"), - osVersion: z.string().describe("Android version, e.g. '14', '16', 'latest'"), + osVersion: z + .string() + .describe("Android version, e.g. '14', '16', 'latest'"), browser: z .string() .optional() @@ -89,14 +99,13 @@ const DeviceSchema = z.discriminatedUnion("platform", [ .string() .describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"), osVersion: z.string().describe("iOS version, e.g. '17', 'latest'"), - browser: z - .string() - .optional() - .describe("Browser name, typically 'safari'"), + browser: z.string().optional().describe("Browser name, typically 'safari'"), }), z.object({ platform: z.literal("macos"), - osVersion: z.string().describe("macOS version name, e.g. 'Sequoia', 'Ventura'"), + osVersion: z + .string() + .describe("macOS version name, e.g. 'Sequoia', 'Ventura'"), browser: z.string().describe("Browser name, e.g. 'safari', 'chrome'"), browserVersion: z .string() @@ -110,7 +119,9 @@ export const RunTestsOnBrowserStackParamsShape = { .string() .describe("A single name for your project to organize all your tests."), detectedLanguage: z.nativeEnum(SDKSupportedLanguageEnum), - detectedBrowserAutomationFramework: z.nativeEnum(SDKSupportedBrowserAutomationFrameworkEnum), + detectedBrowserAutomationFramework: z.nativeEnum( + SDKSupportedBrowserAutomationFrameworkEnum, + ), detectedTestingFramework: z.nativeEnum(SDKSupportedTestingFrameworkEnum), devices: z .array(DeviceSchema) @@ -121,7 +132,6 @@ export const RunTestsOnBrowserStackParamsShape = { ), }; - export const SetUpPercySchema = z.object(SetUpPercyParamsShape); export const RunTestsOnBrowserStackSchema = z.object(