From b8b0ce09ae899ad1a36651754560ec804befd7d8 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 18 Apr 2024 11:01:30 +0200 Subject: [PATCH] feat: Use public API to run application using the path to it (#294) --- README.md | 2 +- .../Commands/FBSessionCommands.m | 22 +++++++++++++------ .../PrivateHeaders/XCTest/XCUIApplication.h | 12 ---------- .../project.pbxproj | 4 ---- package.json | 9 -------- 5 files changed, 16 insertions(+), 33 deletions(-) delete mode 100644 WebDriverAgentMac/WebDriverAgentLib/PrivateHeaders/XCTest/XCUIApplication.h diff --git a/README.md b/README.md index a76c880..f08ce00 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ appium:skipAppKill | Whether to skip the termination of the application under te appium:prerun | An object containing either `script` or `command` key. The value of each key must be a valid AppleScript script or command to be executed prior to the Mac2Driver session startup. See [AppleScript commands execution](#applescript-commands-execution) for more details. Example: `{command: 'do shell script "echo hello"'}` appium:postrun | An object containing either `script` or `command` key. The value of each key must be a valid AppleScript script or command to be executed after Mac2Driver session is stopped. See [AppleScript commands execution](#applescript-commands-execution) for more details. appium:noReset | Whether to restart the app whose bundle identifier was passed to capabilities as `bundleId` value if it was already running on the session startup (`false`, the default value) or just pick it up without changing the app state (`true`). Note that neither of `arguments` or `environment` capabilities will take effect if the app did not restart. -appium:appPath | The path to the application to automate, for example `/Applications/MyAppName.app`. This is an optional capability, but it requires `bundleId` to be present. If `bundleId` is empty, `appPath` will be ignored. If the path is invalid or application is damaged/incomplete then an error will be thrown on session startup. This capability could be useful when you have multiple builds of the same application with the same bundleId on your machine (for example one production build in /Applications/ and several dev builds). If you provide bundleId only, the operating system could open any of these builds. By providing `appPath` you have a guarantee that the specified .app will be launched, rather than a random one. +appium:appPath | The path to the application to automate, for example `/Applications/MyAppName.app`. This is an optional capability, but it requires `bundleId` to be present until mac2 driver v1.13.0. In earlier versions if `bundleId` is empty, `appPath` would be ignored. If the path is invalid or application is damaged/incomplete then an error will be thrown on session startup. This capability could be useful when you have multiple builds of the same application with the same bundleId on your machine (for example one production build in /Applications/ and several dev builds). If you provide bundleId only, the operating system could open any of these builds. By providing `appPath` you have a guarantee that the specified .app will be launched, rather than a random one. appium:appLocale | A dictionary with the following possible entries: `locale` (application locale name, for example `uk_UA`), `language` (application language name, for example `de`), `useMetricUnits` (whether to use metric units for the app, if `false` then imperial units are used), `measurementUnits` (the name of measurement units to use in the app, for example `Inches`). This capability only changes the locale for the app under test, it does not modify the system locale. You can achieve the same effect by providing custom values to reserved app command line arguments like `-AppleLanguages` or `-AppleLocale` using the `appium:arguments` capability. Example: use `appLocale = {locale: "de", language: "de_DE"}` to start the app in German language (if no German resources are defined in the destination app bundle then the app is started with the default locale, usually en_US). diff --git a/WebDriverAgentMac/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentMac/WebDriverAgentLib/Commands/FBSessionCommands.m index 0fd4e5d..4d4f10b 100644 --- a/WebDriverAgentMac/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentMac/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -17,7 +17,6 @@ #import "FBRouteRequest.h" #import "FBSession.h" #import "FBRuntimeUtils.h" -#import "XCUIApplication.h" #import "XCUIApplication+AMHelpers.h" #import "XCUIApplication+AMUIInterruptions.h" @@ -83,15 +82,15 @@ + (NSArray *)routes } NSString *bundleID = requirements[AM_BUNDLE_ID_CAPABILITY]; + NSString *appPath = requirements[AM_APP_PATH_CAPABILITY]; BOOL noReset = [requirements[AM_NO_RESET_CAPABILITY] boolValue]; FBSession *session; - if (nil == bundleID) { + if (nil == bundleID && nil == appPath) { session = [FBSession initWithApplication:nil]; } else { - NSString *appPath = requirements[AM_APP_PATH_CAPABILITY]; - XCUIApplication *app = appPath == nil ? - [[XCUIApplication alloc] initWithBundleIdentifier:bundleID] : - [[XCUIApplication alloc] initPrivateWithPath:appPath bundleID:bundleID]; + XCUIApplication *app = nil != appPath + ? [[XCUIApplication alloc] initWithURL:[NSURL fileURLWithPath:appPath]] + : [[XCUIApplication alloc] initWithBundleIdentifier:bundleID]; session = [FBSession initWithApplication:app]; if (noReset && app.state > XCUIApplicationStateNotRunning) { [app activate]; @@ -107,7 +106,16 @@ + (NSArray *)routes app.launchEnvironment = (NSDictionary *)requirements[AM_APP_ENVIRONMENT_CAPABILITY] ?: @{}; [app launch]; if (app.state <= XCUIApplicationStateNotRunning) { - NSString *message = [NSString stringWithFormat:@"Failed to launch '%@' application", bundleID]; + NSString *message = [NSString stringWithFormat:@"Failed to launch '%@' application", appPath ?: bundleID]; + return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:message + traceback:nil]); + } + } + if (nil != bundleID && nil != appPath) { + NSString *realBundleID = app.am_bundleID; + if (![realBundleID isEqualToString:bundleID]) { + NSString *message = [NSString stringWithFormat:@"The bundle identifier %@ of the '%@' does not match to the one provided in capabilities: %@", + realBundleID, appPath, bundleID]; return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:message traceback:nil]); } diff --git a/WebDriverAgentMac/WebDriverAgentLib/PrivateHeaders/XCTest/XCUIApplication.h b/WebDriverAgentMac/WebDriverAgentLib/PrivateHeaders/XCTest/XCUIApplication.h deleted file mode 100644 index 589578c..0000000 --- a/WebDriverAgentMac/WebDriverAgentLib/PrivateHeaders/XCTest/XCUIApplication.h +++ /dev/null @@ -1,12 +0,0 @@ - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface XCUIApplication (InitPrivateWithPath) - -- (id)initPrivateWithPath:(id)path bundleID:(id)bundleId; - -@end - -NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentMac/WebDriverAgentMac.xcodeproj/project.pbxproj b/WebDriverAgentMac/WebDriverAgentMac.xcodeproj/project.pbxproj index ac71391..bf32353 100644 --- a/WebDriverAgentMac/WebDriverAgentMac.xcodeproj/project.pbxproj +++ b/WebDriverAgentMac/WebDriverAgentMac.xcodeproj/project.pbxproj @@ -190,7 +190,6 @@ 71B8B68126726369009CE50C /* AMSwipeHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B8B67F26726369009CE50C /* AMSwipeHelpers.h */; }; 71B8B68226726369009CE50C /* AMSwipeHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B8B68026726369009CE50C /* AMSwipeHelpers.m */; }; 71B8B684267265D7009CE50C /* AMVariousElementTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B8B683267265D7009CE50C /* AMVariousElementTests.m */; }; - C68B934B2AA892CF009F00F2 /* XCUIApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = C68B934A2AA892CF009F00F2 /* XCUIApplication.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -425,7 +424,6 @@ 71B8B67F26726369009CE50C /* AMSwipeHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AMSwipeHelpers.h; sourceTree = ""; }; 71B8B68026726369009CE50C /* AMSwipeHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AMSwipeHelpers.m; sourceTree = ""; }; 71B8B683267265D7009CE50C /* AMVariousElementTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AMVariousElementTests.m; sourceTree = ""; }; - C68B934A2AA892CF009F00F2 /* XCUIApplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCUIApplication.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -768,7 +766,6 @@ 7180C1E6257A94F3008FA870 /* XCPointerEventPath.h */, 7180C1EC257A95C2008FA870 /* XCSynthesizedEventRecord.h */, 7180C1F6257A9896008FA870 /* XCUIEventSynthesizing-Protocol.h */, - C68B934A2AA892CF009F00F2 /* XCUIApplication.h */, ); path = XCTest; sourceTree = ""; @@ -878,7 +875,6 @@ 7109C0532565B5EA006BFD13 /* HTTPErrorResponse.h in Headers */, 7180C1E9257A94F4008FA870 /* XCPointerEvent.h in Headers */, 712FA091288BD68100976DA8 /* AMWindowCommands.h in Headers */, - C68B934B2AA892CF009F00F2 /* XCUIApplication.h in Headers */, 7180C1ED257A95C2008FA870 /* XCSynthesizedEventRecord.h in Headers */, 718D2C322567FED3005F533B /* AMSessionCapabilities.h in Headers */, 7109BFE02565B536006BFD13 /* FBCommandHandler.h in Headers */, diff --git a/package.json b/package.json index f3d42d6..b5ccff0 100644 --- a/package.json +++ b/package.json @@ -65,16 +65,10 @@ "dev": "npm run build -- --watch", "lint": "eslint .", "lint:fix": "npm run lint -- --fix", - "precommit-msg": "echo 'Pre-commit checks...' && exit 0", - "precommit-lint": "lint-staged", "prepare": "npm run rebuild", "test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.js\"", "e2e-test": "mocha --exit --timeout 10m \"./test/functional/**/*-specs.js\"" }, - "pre-commit": [ - "precommit-msg", - "precommit-lint" - ], "peerDependencies": { "appium": "^2.4.1" }, @@ -94,8 +88,6 @@ "@types/sinon": "^17.0.0", "@types/sinon-chai": "^3.2.9", "@types/teen_process": "^2.0.2", - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", "chai": "^4.1.2", "chai-as-promised": "^7.1.1", "conventional-changelog-conventionalcommits": "^7.0.1", @@ -107,7 +99,6 @@ "eslint-plugin-promise": "^6.1.1", "lint-staged": "^15.0.2", "mocha": "^10.0.0", - "pre-commit": "^1.1.3", "semantic-release": "^23.0.0", "sinon": "^17.0.0", "ts-node": "^10.9.1",