Skip to content

Commit 8912c86

Browse files
Merge pull request #179 from tech-sushant/qodo-fix
refactor: update device handling in automation tools
2 parents cc2a6a2 + 6bf095c commit 8912c86

File tree

6 files changed

+90
-102
lines changed

6 files changed

+90
-102
lines changed

src/tools/appautomate-utils/appium-sdk/constants.ts

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
AppSDKSupportedFrameworkEnum,
44
AppSDKSupportedTestingFrameworkEnum,
55
AppSDKSupportedLanguageEnum,
6-
AppSDKSupportedPlatformEnum,
76
} from "./index.js";
87

98
// App Automate specific device configurations
@@ -26,6 +25,18 @@ export const STEP_DELIMITER = "---STEP---";
2625
// Default app path for examples
2726
export const DEFAULT_APP_PATH = "bs://sample.app";
2827

28+
export const MobileDeviceSchema = z.object({
29+
platform: z
30+
.enum(["android", "ios"])
31+
.describe("Platform name: 'android' or 'ios'"),
32+
deviceName: z
33+
.string()
34+
.describe(
35+
"Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8', 'iPhone 15', 'iPhone 14 Pro'",
36+
),
37+
osVersion: z.string().describe("OS version, e.g. '14', '16', '17', 'latest'"),
38+
});
39+
2940
// Tool description and schema for setupBrowserStackAppAutomateTests
3041
export const SETUP_APP_AUTOMATE_DESCRIPTION =
3142
"Set up BrowserStack App Automate SDK integration for Appium-based mobile app testing. ONLY for Appium based framework . This tool configures SDK for various languages with appium. For pre-built Espresso or XCUITest test suites, use 'runAppTestsOnBrowserStack' instead.";
@@ -50,30 +61,7 @@ export const SETUP_APP_AUTOMATE_SCHEMA = {
5061
),
5162

5263
devices: z
53-
.array(
54-
z.union([
55-
// Android: [android, deviceName, osVersion]
56-
z.tuple([
57-
z
58-
.literal(AppSDKSupportedPlatformEnum.android)
59-
.describe("Platform identifier: 'android'"),
60-
z
61-
.string()
62-
.describe(
63-
"Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'",
64-
),
65-
z.string().describe("Android version, e.g. '14', '16', 'latest'"),
66-
]),
67-
// iOS: [ios, deviceName, osVersion]
68-
z.tuple([
69-
z
70-
.literal(AppSDKSupportedPlatformEnum.ios)
71-
.describe("Platform identifier: 'ios'"),
72-
z.string().describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"),
73-
z.string().describe("iOS version, e.g. '17', '16', 'latest'"),
74-
]),
75-
]),
76-
)
64+
.array(MobileDeviceSchema)
7765
.max(3)
7866
.default([])
7967
.describe(

src/tools/appautomate-utils/appium-sdk/handler.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,12 @@ export async function setupAppAutomateHandler(
3838
const testingFramework =
3939
input.detectedTestingFramework as AppSDKSupportedTestingFramework;
4040
const language = input.detectedLanguage as AppSDKSupportedLanguage;
41-
const inputDevices = (input.devices as Array<Array<string>>) ?? [];
41+
const inputDevices: Array<Array<string>> =
42+
input.devices?.map((device) => [
43+
device.platform,
44+
device.deviceName,
45+
device.osVersion,
46+
]) ?? [];
4247
const appPath = input.appPath as string;
4348
const framework = input.detectedFramework as SupportedFramework;
4449

src/tools/appautomate-utils/native-execution/constants.ts

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import { z } from "zod";
22
import { AppTestPlatform } from "./types.js";
3-
import { AppSDKSupportedPlatformEnum } from "../appium-sdk/types.js";
43

54
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.`;
65

6+
export const MobileDeviceSchema = z.object({
7+
platform: z
8+
.enum(["android", "ios"])
9+
.describe("Platform name: 'android' or 'ios'"),
10+
deviceName: z
11+
.string()
12+
.describe(
13+
"Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8', 'iPhone 15', 'iPhone 14 Pro'",
14+
),
15+
osVersion: z.string().describe("OS version, e.g. '14', '16', '17', 'latest'"),
16+
});
17+
718
export const RUN_APP_AUTOMATE_SCHEMA = {
819
appPath: z
920
.string()
@@ -30,30 +41,7 @@ export const RUN_APP_AUTOMATE_SCHEMA = {
3041
"If in other directory, provide existing test file path",
3142
),
3243
devices: z
33-
.array(
34-
z.union([
35-
// Android: [android, deviceName, osVersion]
36-
z.tuple([
37-
z
38-
.literal(AppSDKSupportedPlatformEnum.android)
39-
.describe("Platform identifier: 'android'"),
40-
z
41-
.string()
42-
.describe(
43-
"Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'",
44-
),
45-
z.string().describe("Android version, e.g. '14', '16', 'latest'"),
46-
]),
47-
// iOS: [ios, deviceName, osVersion]
48-
z.tuple([
49-
z
50-
.literal(AppSDKSupportedPlatformEnum.ios)
51-
.describe("Platform identifier: 'ios'"),
52-
z.string().describe("Device name, e.g. 'iPhone 15', 'iPhone 14 Pro'"),
53-
z.string().describe("iOS version, e.g. '17', '16', 'latest'"),
54-
]),
55-
]),
56-
)
44+
.array(MobileDeviceSchema)
5745
.max(3)
5846
.default([])
5947
.describe(

src/tools/appautomate.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,13 @@ export default function addAppAutomationTools(
378378
undefined,
379379
config,
380380
);
381-
return await runAppTestsOnBrowserStack(args, config);
381+
const devicesAsArrays: Array<Array<string>> = args.devices.map(
382+
(device) => [device.platform, device.deviceName, device.osVersion],
383+
);
384+
return await runAppTestsOnBrowserStack(
385+
{ ...args, devices: devicesAsArrays },
386+
config,
387+
);
382388
} catch (error) {
383389
trackMCP(
384390
"runAppTestsOnBrowserStack",

src/tools/sdk-utils/bstack/sdkHandler.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,30 @@ export async function runBstackSDKOnly(
2222
const authString = getBrowserStackAuth(config);
2323
const [username, accessKey] = authString.split(":");
2424

25-
// Validate devices against real BrowserStack device data
26-
const tupleTargets = (input as any).devices as
27-
| Array<Array<string>>
28-
| undefined;
25+
const tupleTargets: Array<Array<string>> =
26+
input.devices?.map((device) => {
27+
const platform = device.platform.toLowerCase();
28+
if (platform === "windows" || platform === "macos") {
29+
// Desktop: ["platform", "osVersion", "browser", "browserVersion"]
30+
return [
31+
platform,
32+
device.osVersion || "latest",
33+
device.browser || "",
34+
device.browserVersion || "latest",
35+
];
36+
} else {
37+
// Mobile: ["platform", "deviceName", "osVersion", "browser"]
38+
return [
39+
platform,
40+
device.deviceName || "",
41+
device.osVersion || "latest",
42+
device.browser || "",
43+
];
44+
}
45+
}) || [];
2946

3047
const validatedEnvironments = await validateDevices(
31-
tupleTargets || [],
48+
tupleTargets,
3249
input.detectedBrowserAutomationFramework,
3350
);
3451

src/tools/sdk-utils/common/schema.ts

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,33 @@ export const SetUpPercyParamsShape = {
4848
),
4949
};
5050

51+
// Device schema for BrowserStack Automate (supports desktop and mobile)
52+
const DeviceSchema = z
53+
.object({
54+
platform: z
55+
.enum(["windows", "macos", "android", "ios"])
56+
.describe("Platform name, e.g. 'windows', 'macos', 'android', 'ios'"),
57+
deviceName: z
58+
.string()
59+
.optional()
60+
.describe(
61+
"Device name for mobile platforms, e.g. 'iPhone 15', 'Samsung Galaxy S24'",
62+
),
63+
osVersion: z
64+
.string()
65+
.describe("OS version, e.g. '11', 'Sequoia', '14', '17', 'latest'"),
66+
browser: z
67+
.string()
68+
.optional()
69+
.describe("Browser name, e.g. 'chrome', 'safari', 'edge', 'firefox'"),
70+
browserVersion: z
71+
.string()
72+
.optional()
73+
.describe(
74+
"Browser version for desktop platforms only (windows, macos), e.g. '132', 'latest', 'oldest'. Not used for mobile devices (android, ios).",
75+
),
76+
});
77+
5178
export const RunTestsOnBrowserStackParamsShape = {
5279
projectName: z
5380
.string()
@@ -58,54 +85,11 @@ export const RunTestsOnBrowserStackParamsShape = {
5885
),
5986
detectedTestingFramework: z.nativeEnum(SDKSupportedTestingFrameworkEnum),
6087
devices: z
61-
.array(
62-
z.union([
63-
// Windows: [windows, osVersion, browser, browserVersion]
64-
z.tuple([
65-
z
66-
.nativeEnum(WindowsPlatformEnum)
67-
.describe("Platform identifier: 'windows'"),
68-
z.string().describe("Windows version, e.g. '10', '11'"),
69-
z.string().describe("Browser name, e.g. 'chrome', 'firefox', 'edge'"),
70-
z
71-
.string()
72-
.describe("Browser version, e.g. '132', 'latest', 'oldest'"),
73-
]),
74-
// Android: [android, name, model, osVersion, browser]
75-
z.tuple([
76-
z
77-
.literal(PlatformEnum.ANDROID)
78-
.describe("Platform identifier: 'android'"),
79-
z
80-
.string()
81-
.describe(
82-
"Device name, e.g. 'Samsung Galaxy S24', 'Google Pixel 8'",
83-
),
84-
z.string().describe("Android version, e.g. '14', '16', 'latest'"),
85-
z.string().describe("Browser name, e.g. 'chrome', 'samsung browser'"),
86-
]),
87-
// iOS: [ios, name, model, osVersion, browser]
88-
z.tuple([
89-
z.literal(PlatformEnum.IOS).describe("Platform identifier: 'ios'"),
90-
z.string().describe("Device name, e.g. 'iPhone 12 Pro'"),
91-
z.string().describe("iOS version, e.g. '17', 'latest'"),
92-
z.string().describe("Browser name, typically 'safari'"),
93-
]),
94-
// macOS: [mac|macos, name, model, browser, browserVersion]
95-
z.tuple([
96-
z
97-
.nativeEnum(MacOSPlatformEnum)
98-
.describe("Platform identifier: 'mac' or 'macos'"),
99-
z.string().describe("macOS version name, e.g. 'Sequoia', 'Ventura'"),
100-
z.string().describe("Browser name, e.g. 'safari', 'chrome'"),
101-
z.string().describe("Browser version, e.g. 'latest'"),
102-
]),
103-
]),
104-
)
88+
.array(DeviceSchema)
10589
.max(3)
10690
.default([])
10791
.describe(
108-
"Preferred tuples of target devices.Add device only when user asks explicitly for it. Defaults to [] . Example: [['windows', '11', 'chrome', 'latest']]",
92+
"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' }].",
10993
),
11094
};
11195

0 commit comments

Comments
 (0)