From 3e0b1914f87585ed69ba20d960502eabb058941c Mon Sep 17 00:00:00 2001 From: Dan Maor Date: Tue, 4 Apr 2023 22:57:17 +0300 Subject: [PATCH 001/133] fix: Fixed Xpath lookup for Xcode 14.3 (#681) --- .../Categories/XCUIElement+FBUID.m | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUID.m b/WebDriverAgentLib/Categories/XCUIElement+FBUID.m index 06979a4cf..765b410c1 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUID.m @@ -12,6 +12,7 @@ #import "XCUIElement+FBUID.h" #import "FBElementUtils.h" +#import "FBLogger.h" #import "XCUIApplication.h" #import "XCUIElement+FBUtilities.h" @@ -35,6 +36,10 @@ - (NSString *)fb_uid @implementation FBXCElementSnapshotWrapper (FBUID) +static void swizzled_validatePredicateWithExpressionsAllowed(id self, SEL _cmd, id predicate, BOOL withExpressionsAllowed) +{ +} + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" + (void)load @@ -43,6 +48,19 @@ + (void)load NSAssert(XCElementSnapshotCls != nil, @"Could not locate XCElementSnapshot class"); Method uidMethod = class_getInstanceMethod(self.class, @selector(fb_uid)); class_addMethod(XCElementSnapshotCls, @selector(fb_uid), method_getImplementation(uidMethod), method_getTypeEncoding(uidMethod)); + + // Support for Xcode 14.3 requires disabling the new predicate validator, see https://github.com/appium/appium/issues/18444 + Class XCTElementQueryTransformerPredicateValidatorCls = objc_lookUpClass("XCTElementQueryTransformerPredicateValidator"); + if (XCTElementQueryTransformerPredicateValidatorCls == nil) { + return; + } + Method validatePredicateMethod = class_getClassMethod(XCTElementQueryTransformerPredicateValidatorCls, NSSelectorFromString(@"validatePredicate:withExpressionsAllowed:")); + if (validatePredicateMethod == nil) { + [FBLogger log:@"Could not find method +[XCTElementQueryTransformerPredicateValidator validatePredicate:withExpressionsAllowed:]"]; + return; + } + IMP swizzledImp = (IMP)swizzled_validatePredicateWithExpressionsAllowed; + method_setImplementation(validatePredicateMethod, swizzledImp); } #pragma diagnostic pop From eb8c5e4f45092548781c6917c70b46856301d1b4 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 4 Apr 2023 20:11:24 +0000 Subject: [PATCH 002/133] chore(release): 4.13.1 [skip ci] ## [4.13.1](https://github.com/appium/WebDriverAgent/compare/v4.13.0...v4.13.1) (2023-04-04) ### Bug Fixes * Fixed Xpath lookup for Xcode 14.3 ([#681](https://github.com/appium/WebDriverAgent/issues/681)) ([3e0b191](https://github.com/appium/WebDriverAgent/commit/3e0b1914f87585ed69ba20d960502eabb058941c)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a46339c1e..42680f5c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [4.13.1](https://github.com/appium/WebDriverAgent/compare/v4.13.0...v4.13.1) (2023-04-04) + + +### Bug Fixes + +* Fixed Xpath lookup for Xcode 14.3 ([#681](https://github.com/appium/WebDriverAgent/issues/681)) ([3e0b191](https://github.com/appium/WebDriverAgent/commit/3e0b1914f87585ed69ba20d960502eabb058941c)) + ## [4.13.0](https://github.com/appium/WebDriverAgent/compare/v4.12.2...v4.13.0) (2023-02-23) diff --git a/package.json b/package.json index e97383446..7d2ec051c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "4.13.0", + "version": "4.13.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From edcbf9e6af903c6f490ca90ff915497ad53bb8b5 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 28 Apr 2023 16:21:40 -0700 Subject: [PATCH 003/133] chore: add withoutSession for pasteboard for debug (#688) --- WebDriverAgentLib/Commands/FBCustomCommands.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index 6fd41d6a4..1ad36c57d 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -52,7 +52,9 @@ + (NSArray *)routes [[FBRoute GET:@"/wda/activeAppInfo"].withoutSession respondWithTarget:self action:@selector(handleActiveAppInfo:)], #if !TARGET_OS_TV // tvOS does not provide relevant APIs [[FBRoute POST:@"/wda/setPasteboard"] respondWithTarget:self action:@selector(handleSetPasteboard:)], + [[FBRoute POST:@"/wda/setPasteboard"].withoutSession respondWithTarget:self action:@selector(handleSetPasteboard:)], [[FBRoute POST:@"/wda/getPasteboard"] respondWithTarget:self action:@selector(handleGetPasteboard:)], + [[FBRoute POST:@"/wda/getPasteboard"].withoutSession respondWithTarget:self action:@selector(handleGetPasteboard:)], [[FBRoute GET:@"/wda/batteryInfo"] respondWithTarget:self action:@selector(handleGetBatteryInfo:)], #endif [[FBRoute POST:@"/wda/pressButton"] respondWithTarget:self action:@selector(handlePressButtonCommand:)], From 215a7c97fff7ada1f3ef4ba0b69c13c63ec46a77 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 28 Apr 2023 23:30:45 +0000 Subject: [PATCH 004/133] chore(release): 4.13.2 [skip ci] ## [4.13.2](https://github.com/appium/WebDriverAgent/compare/v4.13.1...v4.13.2) (2023-04-28) ### Miscellaneous Chores * add withoutSession for pasteboard for debug ([#688](https://github.com/appium/WebDriverAgent/issues/688)) ([edcbf9e](https://github.com/appium/WebDriverAgent/commit/edcbf9e6af903c6f490ca90ff915497ad53bb8b5)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42680f5c6..5027151d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [4.13.2](https://github.com/appium/WebDriverAgent/compare/v4.13.1...v4.13.2) (2023-04-28) + + +### Miscellaneous Chores + +* add withoutSession for pasteboard for debug ([#688](https://github.com/appium/WebDriverAgent/issues/688)) ([edcbf9e](https://github.com/appium/WebDriverAgent/commit/edcbf9e6af903c6f490ca90ff915497ad53bb8b5)) + ## [4.13.1](https://github.com/appium/WebDriverAgent/compare/v4.13.0...v4.13.1) (2023-04-04) diff --git a/package.json b/package.json index 7d2ec051c..a5b994186 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "4.13.1", + "version": "4.13.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From e1c0f836a68ad2efbedfc77343794d0d97ef6090 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 1 May 2023 23:48:16 -0700 Subject: [PATCH 005/133] feat: start wda process via Xctest in a real device (#687) * move some implementation to wda * tune * Update webdriveragent.js * update review * refactor: set started=true after getStatus * chore: use WDA_RUNNER_BUNDLE_ID * refactor: rename * chore: refer to updatedWDABundleId to build xctrunner * add fixme to not create xcodebuild instance for webDriverAgentUrl * return a bit early * refactor: fix review * refactor: fix review --- lib/constants.js | 4 +- lib/webdriveragent.js | 122 +++++++++++++++++++++++++++++++----------- package.json | 1 + 3 files changed, 96 insertions(+), 31 deletions(-) diff --git a/lib/constants.js b/lib/constants.js index caea65cec..82f005d1c 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,6 +1,7 @@ import path from 'path'; const WDA_RUNNER_BUNDLE_ID = 'com.facebook.WebDriverAgentRunner'; +const WDA_RUNNER_BUNDLE_ID_FOR_XCTEST = `${WDA_RUNNER_BUNDLE_ID}.xctrunner`; const WDA_RUNNER_APP = 'WebDriverAgentRunner-Runner.app'; const WDA_SCHEME = 'WebDriverAgentRunner'; const PROJECT_FILE = 'project.pbxproj'; @@ -17,5 +18,6 @@ const WDA_UPGRADE_TIMESTAMP_PATH = path.join('.appium', 'webdriveragent', 'upgra export { WDA_RUNNER_BUNDLE_ID, WDA_RUNNER_APP, PROJECT_FILE, WDA_SCHEME, PLATFORM_NAME_TVOS, PLATFORM_NAME_IOS, - SDK_SIMULATOR, SDK_DEVICE, WDA_BASE_URL, WDA_UPGRADE_TIMESTAMP_PATH + SDK_SIMULATOR, SDK_DEVICE, WDA_BASE_URL, WDA_UPGRADE_TIMESTAMP_PATH, + WDA_RUNNER_BUNDLE_ID_FOR_XCTEST }; diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 93898047b..2424a95aa 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -14,8 +14,10 @@ import AsyncLock from 'async-lock'; import { exec } from 'teen_process'; import { bundleWDASim } from './check-dependencies'; import { - WDA_RUNNER_BUNDLE_ID, WDA_RUNNER_APP, WDA_BASE_URL, WDA_UPGRADE_TIMESTAMP_PATH, + WDA_RUNNER_BUNDLE_ID, WDA_RUNNER_BUNDLE_ID_FOR_XCTEST, WDA_RUNNER_APP, + WDA_BASE_URL, WDA_UPGRADE_TIMESTAMP_PATH, } from './constants'; +import {Xctest} from 'appium-ios-device'; const WDA_LAUNCH_TIMEOUT = 60 * 1000; const WDA_AGENT_PORT = 8100; @@ -59,31 +61,47 @@ class WebDriverAgent { this.updatedWDABundleId = args.updatedWDABundleId; - this.xcodebuild = new XcodeBuild(this.xcodeVersion, this.device, { - platformVersion: this.platformVersion, - platformName: this.platformName, - iosSdkVersion: this.iosSdkVersion, - agentPath: this.agentPath, - bootstrapPath: this.bootstrapPath, - realDevice: this.isRealDevice, - showXcodeLog: args.showXcodeLog, - xcodeConfigFile: args.xcodeConfigFile, - xcodeOrgId: args.xcodeOrgId, - xcodeSigningId: args.xcodeSigningId, - keychainPath: args.keychainPath, - keychainPassword: args.keychainPassword, - useSimpleBuildTest: args.useSimpleBuildTest, - usePrebuiltWDA: args.usePrebuiltWDA, - updatedWDABundleId: this.updatedWDABundleId, - launchTimeout: args.wdaLaunchTimeout || WDA_LAUNCH_TIMEOUT, - wdaRemotePort: this.wdaRemotePort, - useXctestrunFile: this.useXctestrunFile, - derivedDataPath: args.derivedDataPath, - mjpegServerPort: this.mjpegServerPort, - allowProvisioningDeviceRegistration: args.allowProvisioningDeviceRegistration, - resultBundlePath: args.resultBundlePath, - resultBundleVersion: args.resultBundleVersion, - }, this.log); + this.usePreinstalledWDA = args.usePreinstalledWDA; + this.xctestApiClient = null; + + // FIXME: maybe 'this.webDriverAgentUrl' also can ignore + // the xcodebuild instance itself. + + this.xcodebuild = this.usePreinstalledWDA + ? null + : new XcodeBuild(this.xcodeVersion, this.device, { + platformVersion: this.platformVersion, + platformName: this.platformName, + iosSdkVersion: this.iosSdkVersion, + agentPath: this.agentPath, + bootstrapPath: this.bootstrapPath, + realDevice: this.isRealDevice, + showXcodeLog: args.showXcodeLog, + xcodeConfigFile: args.xcodeConfigFile, + xcodeOrgId: args.xcodeOrgId, + xcodeSigningId: args.xcodeSigningId, + keychainPath: args.keychainPath, + keychainPassword: args.keychainPassword, + useSimpleBuildTest: args.useSimpleBuildTest, + usePrebuiltWDA: args.usePrebuiltWDA, + updatedWDABundleId: this.updatedWDABundleId, + launchTimeout: args.wdaLaunchTimeout || WDA_LAUNCH_TIMEOUT, + wdaRemotePort: this.wdaRemotePort, + useXctestrunFile: this.useXctestrunFile, + derivedDataPath: args.derivedDataPath, + mjpegServerPort: this.mjpegServerPort, + allowProvisioningDeviceRegistration: args.allowProvisioningDeviceRegistration, + resultBundlePath: args.resultBundlePath, + resultBundleVersion: args.resultBundleVersion, + }, this.log); + } + + /** + * + * @returns {string} Bundle ID for Xctest. + */ + get bundleIdForXctest () { + return `${this.updatedWDABundleId}.xctrunner` || WDA_RUNNER_BUNDLE_ID_FOR_XCTEST; } setWDAPaths (bootstrapPath, agentPath) { @@ -248,6 +266,9 @@ class WebDriverAgent { return; } + if (this.usePreinstalledWDA) { + return; + } try { await this.xcodebuild.cleanProject(); } catch (e) { @@ -255,6 +276,30 @@ class WebDriverAgent { } } + /** + * Launch WDA with preinstalled package without xcodebuild. + * @param {string} sessionId Launch WDA and establish the session with this sessionId + * @return {?object} State Object + */ + async launchWithPreinstalledWDA(sessionId) { + const xctestEnv = { + USE_PORT: this.wdaLocalPort || WDA_AGENT_PORT, + WDA_PRODUCT_BUNDLE_IDENTIFIER: this.bundleIdForXctest + }; + if (this.mjpegServerPort) { + xctestEnv.MJPEG_SERVER_PORT = this.mjpegServerPort; + } + this.log.info('Launching WebDriverAgent on the device without xcodebuild'); + this.xctestApiClient = new Xctest(this.device.udid, this.bundleIdForXctest, null, {env: xctestEnv}); + + await this.xctestApiClient.start(); + + this.setupProxies(sessionId); + const status = await this.getStatus(); + this.started = true; + return status; + } + /** * Return current running WDA's status like below after launching WDA * { @@ -286,6 +331,13 @@ class WebDriverAgent { return await this.getStatus(); } + if (this.usePreinstalledWDA) { + if (this.isRealDevice) { + return await this.launchWithPreinstalledWDA(sessionId); + } + throw new Error('usePreinstalledWDA is available only for a real device.'); + } + this.log.info('Launching WebDriverAgent on the device'); this.setupProxies(sessionId); @@ -393,10 +445,17 @@ class WebDriverAgent { } async quit () { - this.log.info('Shutting down sub-processes'); - - await this.xcodebuild.quit(); - await this.xcodebuild.reset(); + if (this.usePreinstalledWDA) { + if (this.xctestApiClient) { + this.log.info('Stopping the XCTest session'); + this.xctestApiClient.stop(); + this.xctestApiClient = null; + } + } else { + this.log.info('Shutting down sub-processes'); + await this.xcodebuild.quit(); + await this.xcodebuild.reset(); + } if (this.jwproxy) { this.jwproxy.sessionId = null; @@ -437,6 +496,9 @@ class WebDriverAgent { } async retrieveDerivedDataPath () { + if (this.usePreinstalledWDA) { + return; + } return await this.xcodebuild.retrieveDerivedDataPath(); } diff --git a/package.json b/package.json index a5b994186..f8e7a711a 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "@appium/base-driver": "^9.0.0", "@appium/support": "^3.0.0", "@babel/runtime": "^7.0.0", + "appium-ios-device": "^2.5.0", "appium-ios-simulator": "^5.0.1", "async-lock": "^1.0.0", "asyncbox": "^2.5.3", From d280750a66d754032416eb865cb2fef8a75ce219 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 2 May 2023 06:57:24 +0000 Subject: [PATCH 006/133] chore(release): 4.14.0 [skip ci] ## [4.14.0](https://github.com/appium/WebDriverAgent/compare/v4.13.2...v4.14.0) (2023-05-02) ### Features * start wda process via Xctest in a real device ([#687](https://github.com/appium/WebDriverAgent/issues/687)) ([e1c0f83](https://github.com/appium/WebDriverAgent/commit/e1c0f836a68ad2efbedfc77343794d0d97ef6090)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5027151d0..d86cea08a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [4.14.0](https://github.com/appium/WebDriverAgent/compare/v4.13.2...v4.14.0) (2023-05-02) + + +### Features + +* start wda process via Xctest in a real device ([#687](https://github.com/appium/WebDriverAgent/issues/687)) ([e1c0f83](https://github.com/appium/WebDriverAgent/commit/e1c0f836a68ad2efbedfc77343794d0d97ef6090)) + ## [4.13.2](https://github.com/appium/WebDriverAgent/compare/v4.13.1...v4.13.2) (2023-04-28) diff --git a/package.json b/package.json index f8e7a711a..72215e98a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "4.13.2", + "version": "4.14.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 0ec74ce32c817a5884228ccb2ec31f0a5a4de9c3 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 4 May 2023 22:10:44 +0200 Subject: [PATCH 007/133] feat: Make isFocused attribute available for iOS elements (#692) * feat: Make isFocused attribute available for iOS elements * Extra line break --- WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m | 2 -- .../Categories/XCUIElement+FBWebDriverAttributes.m | 2 -- WebDriverAgentLib/Routing/FBElement.h | 2 -- 3 files changed, 6 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 022df5b9d..086643296 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -126,9 +126,7 @@ + (NSDictionary *)dictionaryForElement:(id)snapshot recursi info[@"isEnabled"] = [@([wrappedSnapshot isWDEnabled]) stringValue]; info[@"isVisible"] = [@([wrappedSnapshot isWDVisible]) stringValue]; info[@"isAccessible"] = [@([wrappedSnapshot isWDAccessible]) stringValue]; -#if TARGET_OS_TV info[@"isFocused"] = [@([wrappedSnapshot isWDFocused]) stringValue]; -#endif if (!recursive) { return info.copy; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m index cc2b46daf..2f2368180 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m @@ -154,12 +154,10 @@ - (BOOL)isWDVisible return self.fb_isVisible; } -#if TARGET_OS_TV - (BOOL)isWDFocused { return self.hasFocus; } -#endif - (BOOL)isWDAccessible { diff --git a/WebDriverAgentLib/Routing/FBElement.h b/WebDriverAgentLib/Routing/FBElement.h index 67e4593f9..277a4ccd2 100644 --- a/WebDriverAgentLib/Routing/FBElement.h +++ b/WebDriverAgentLib/Routing/FBElement.h @@ -53,10 +53,8 @@ NS_ASSUME_NONNULL_BEGIN /*! Whether element is an accessibility container (contains children of any depth that are accessible) */ @property (nonatomic, readonly, getter = isWDAccessibilityContainer) BOOL wdAccessibilityContainer; -#if TARGET_OS_TV /*! Whether element is focused */ @property (nonatomic, readonly, getter = isWDFocused) BOOL wdFocused; -#endif /*! Element's index relatively to its parent. Starts from zero */ @property (nonatomic, readonly) NSUInteger wdIndex; From 2ec5a4b8e2f1af70efd3e8fc572f7f503c0b7513 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 4 May 2023 20:18:10 +0000 Subject: [PATCH 008/133] chore(release): 4.15.0 [skip ci] ## [4.15.0](https://github.com/appium/WebDriverAgent/compare/v4.14.0...v4.15.0) (2023-05-04) ### Features * Make isFocused attribute available for iOS elements ([#692](https://github.com/appium/WebDriverAgent/issues/692)) ([0ec74ce](https://github.com/appium/WebDriverAgent/commit/0ec74ce32c817a5884228ccb2ec31f0a5a4de9c3)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d86cea08a..007d1a7aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [4.15.0](https://github.com/appium/WebDriverAgent/compare/v4.14.0...v4.15.0) (2023-05-04) + + +### Features + +* Make isFocused attribute available for iOS elements ([#692](https://github.com/appium/WebDriverAgent/issues/692)) ([0ec74ce](https://github.com/appium/WebDriverAgent/commit/0ec74ce32c817a5884228ccb2ec31f0a5a4de9c3)) + ## [4.14.0](https://github.com/appium/WebDriverAgent/compare/v4.13.2...v4.14.0) (2023-05-02) diff --git a/package.json b/package.json index 72215e98a..c23a5b31a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "4.14.0", + "version": "4.15.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 2f7f702805ad1e7f11e53e48dbde7783c732e7fb Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 5 May 2023 20:54:03 +0200 Subject: [PATCH 009/133] ci: Update node matrix generation --- .github/workflows/unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 6b44da0f0..665cf2e5d 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -13,7 +13,7 @@ jobs: id: generate-matrix run: | sudo apt-get install -y lynx - lynx -dump https://endoflife.date/nodejs | grep -E -o '[0-9]+ \(LTS\)' | grep -E -o '([0-9]+)' > eol.list + lynx -dump https://endoflife.date/nodejs | grep -E -o '[0-9]+[( a-zA-Z]+LTS\)' | grep -E -o '([0-9]+)' > eol.list cat eol.list lts1=$(cat eol.list | head -1) lts2=$(cat eol.list | head -2 | tail -1) From d8f1457b591b2dd00040f8336c1a7a728af871d2 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 5 May 2023 22:13:00 -0700 Subject: [PATCH 010/133] perf: tune webDriverAgentUrl case by skiping xcodebuild stuff (#691) * perf: tune webDriverAgentUrl case by skiping xcodebuild stuff * include a small fix * Update webdriveragent.js --- lib/webdriveragent.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 2424a95aa..ef6e8e766 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -48,6 +48,9 @@ class WebDriverAgent { this.prebuildWDA = args.prebuildWDA; + // this.args.webDriverAgentUrl guiarantees the capabilities acually + // gave 'appium:webDriverAgentUrl' but 'this.webDriverAgentUrl' + // could be used for caching WDA with xcodebuild. this.webDriverAgentUrl = args.webDriverAgentUrl; this.started = false; @@ -64,10 +67,7 @@ class WebDriverAgent { this.usePreinstalledWDA = args.usePreinstalledWDA; this.xctestApiClient = null; - // FIXME: maybe 'this.webDriverAgentUrl' also can ignore - // the xcodebuild instance itself. - - this.xcodebuild = this.usePreinstalledWDA + this.xcodebuild = this.canSkipXcodebuild ? null : new XcodeBuild(this.xcodeVersion, this.device, { platformVersion: this.platformVersion, @@ -96,12 +96,22 @@ class WebDriverAgent { }, this.log); } + /** + * Return true if the session does not need xcodebuild. + * @returns {boolean} Whether the session needs/has xcodebuild. + */ + get canSkipXcodebuild () { + // Use this.args.webDriverAgentUrl to guarantee + // the capabilities set gave the `appium:webDriverAgentUrl`. + return this.usePreinstalledWDA || this.args.webDriverAgentUrl; + } + /** * * @returns {string} Bundle ID for Xctest. */ get bundleIdForXctest () { - return `${this.updatedWDABundleId}.xctrunner` || WDA_RUNNER_BUNDLE_ID_FOR_XCTEST; + return this.updatedWDABundleId ? `${this.updatedWDABundleId}.xctrunner` : WDA_RUNNER_BUNDLE_ID_FOR_XCTEST; } setWDAPaths (bootstrapPath, agentPath) { @@ -266,7 +276,7 @@ class WebDriverAgent { return; } - if (this.usePreinstalledWDA) { + if (this.canSkipXcodebuild) { return; } try { @@ -451,10 +461,13 @@ class WebDriverAgent { this.xctestApiClient.stop(); this.xctestApiClient = null; } - } else { + } else if (!this.args.webDriverAgentUrl) { this.log.info('Shutting down sub-processes'); await this.xcodebuild.quit(); await this.xcodebuild.reset(); + } else { + this.log.debug('Do not stop xcodebuild nor XCTest session ' + + 'since the WDA session is managed by outside this driver.'); } if (this.jwproxy) { @@ -496,7 +509,7 @@ class WebDriverAgent { } async retrieveDerivedDataPath () { - if (this.usePreinstalledWDA) { + if (this.canSkipXcodebuild) { return; } return await this.xcodebuild.retrieveDerivedDataPath(); From 3b48b6cb0e47e8669892228053e318ba33698ce6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 6 May 2023 05:23:32 +0000 Subject: [PATCH 011/133] chore(release): 4.15.1 [skip ci] ## [4.15.1](https://github.com/appium/WebDriverAgent/compare/v4.15.0...v4.15.1) (2023-05-06) ### Performance Improvements * tune webDriverAgentUrl case by skiping xcodebuild stuff ([#691](https://github.com/appium/WebDriverAgent/issues/691)) ([d8f1457](https://github.com/appium/WebDriverAgent/commit/d8f1457b591b2dd00040f8336c1a7a728af871d2)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 007d1a7aa..0b57bd88c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [4.15.1](https://github.com/appium/WebDriverAgent/compare/v4.15.0...v4.15.1) (2023-05-06) + + +### Performance Improvements + +* tune webDriverAgentUrl case by skiping xcodebuild stuff ([#691](https://github.com/appium/WebDriverAgent/issues/691)) ([d8f1457](https://github.com/appium/WebDriverAgent/commit/d8f1457b591b2dd00040f8336c1a7a728af871d2)) + ## [4.15.0](https://github.com/appium/WebDriverAgent/compare/v4.14.0...v4.15.0) (2023-05-04) diff --git a/package.json b/package.json index c23a5b31a..4e54f3d4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "4.15.0", + "version": "4.15.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 9860a72b902a1c8340f3b1b29f2509e59077e86d Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 12 May 2023 09:36:31 -0700 Subject: [PATCH 012/133] ci: use Xcode 14.2 for release (#697) --- .github/workflows/publish.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.js.yml b/.github/workflows/publish.js.yml index 05420d48b..6d1915ca7 100644 --- a/.github/workflows/publish.js.yml +++ b/.github/workflows/publish.js.yml @@ -13,7 +13,7 @@ jobs: runs-on: macos-12 env: - XCODE_VERSION: 14.1 + XCODE_VERSION: 14.2 ZIP_PKG_NAME_IOS: "WebDriverAgentRunner-Runner.zip" PKG_PATH_IOS: "appium_wda_ios" ZIP_PKG_NAME_TVOS: "WebDriverAgentRunner_tvOS-Runner.zip" From bb562b96db6aad476970ef7bd352cb8df4f1e6c2 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 14 May 2023 13:16:36 +0200 Subject: [PATCH 013/133] refactor!: Drop workarounds for legacy iOS versions (#696) BREAKING CHANGE: The minimum supported xCode/iOS version is now 13/15.0 --- .../Categories/XCUIApplication+FBAlert.m | 29 ++++--------- .../Categories/XCUIDevice+FBHelpers.m | 6 +-- .../Categories/XCUIElement+FBTap.m | 43 +++---------------- WebDriverAgentLib/Commands/FBCustomCommands.m | 6 +-- .../Utilities/FBBaseActionsSynthesizer.m | 34 ++++----------- WebDriverAgentLib/Utilities/FBKeyboard.m | 3 +- WebDriverAgentLib/Utilities/FBScreen.m | 11 +---- WebDriverAgentLib/Utilities/FBScreenshot.m | 1 - .../Utilities/FBW3CActionsSynthesizer.m | 4 +- 9 files changed, 31 insertions(+), 106 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m b/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m index eb23ed6a7..38b6586ef 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m @@ -36,26 +36,15 @@ - (nullable XCUIElement *)fb_alertElementFromSafariWithScrollView:(XCUIElement * }]; NSPredicate *dstViewContainPredicate1 = [NSPredicate predicateWithFormat:@"elementType == %lu", XCUIElementTypeTextView]; NSPredicate *dstViewContainPredicate2 = [NSPredicate predicateWithFormat:@"elementType == %lu", XCUIElementTypeButton]; - XCUIElement *candidate = nil; - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0")) { - // Find the first XCUIElementTypeOther which is the grandchild of the web view - // and is horizontally aligned to the center of the screen - candidate = [[[[[[scrollView descendantsMatchingType:XCUIElementTypeAny] - matchingIdentifier:@"WebView"] - descendantsMatchingType:XCUIElementTypeOther] - matchingPredicate:dstViewMatchPredicate] - containingPredicate:dstViewContainPredicate1] - containingPredicate:dstViewContainPredicate2].allElementsBoundByIndex.firstObject; - } else { - NSPredicate *webViewPredicate = [NSPredicate predicateWithFormat:@"elementType == %lu", XCUIElementTypeWebView]; - // Find the first XCUIElementTypeOther which is the descendant of the scroll view - // and is horizontally aligned to the center of the screen - candidate = [[[[[scrollView.fb_query containingPredicate:webViewPredicate] - descendantsMatchingType:XCUIElementTypeOther] - matchingPredicate:dstViewMatchPredicate] - containingPredicate:dstViewContainPredicate1] - containingPredicate:dstViewContainPredicate2].allElementsBoundByIndex.firstObject; - } + // Find the first XCUIElementTypeOther which is the grandchild of the web view + // and is horizontally aligned to the center of the screen + XCUIElement *candidate = [[[[[[scrollView descendantsMatchingType:XCUIElementTypeAny] + matchingIdentifier:@"WebView"] + descendantsMatchingType:XCUIElementTypeOther] + matchingPredicate:dstViewMatchPredicate] + containingPredicate:dstViewContainPredicate1] + containingPredicate:dstViewContainPredicate2].allElementsBoundByIndex.firstObject; + if (nil == candidate) { return nil; } diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m index 1bc95a33e..5f138f381 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m @@ -86,11 +86,7 @@ - (BOOL)fb_unlockScreen:(NSError **)error [self pressButton:XCUIDeviceButtonHome]; [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:FBHomeButtonCoolOffTime]]; #if !TARGET_OS_TV - if (SYSTEM_VERSION_LESS_THAN(@"10.0")) { - [[FBApplication fb_activeApplication] swipeRight]; - } else { - [self pressButton:XCUIDeviceButtonHome]; - } + [self pressButton:XCUIDeviceButtonHome]; #else [self pressButton:XCUIDeviceButtonHome]; #endif diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTap.m b/WebDriverAgentLib/Categories/XCUIElement+FBTap.m index 311e13d8e..c3c4346ae 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTap.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTap.m @@ -9,52 +9,23 @@ #import "XCUIElement+FBTap.h" -#import "FBMacros.h" -#import "XCUIApplication+FBTouchAction.h" -#import "XCUIElement+FBUtilities.h" - #if !TARGET_OS_TV @implementation XCUIElement (FBTap) - (BOOL)fb_tapWithError:(NSError **)error { - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { - [self tap]; - return YES; - } - - NSArray *> *tapGesture = - @[ - @{@"action": @"tap", - @"options": @{@"element": self} - } - ]; - return [self.application fb_performAppiumTouchActions:tapGesture elementCache:nil error:error]; + [self tap]; + return YES; } - (BOOL)fb_tapCoordinate:(CGPoint)relativeCoordinate error:(NSError **)error { - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { - // Coordinates calculation issues have been fixed - // for different device orientations since Xcode 11 - XCUICoordinate *startCoordinate = [self coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; - CGVector offset = CGVectorMake(relativeCoordinate.x, relativeCoordinate.y); - XCUICoordinate *dstCoordinate = [startCoordinate coordinateWithOffset:offset]; - [dstCoordinate tap]; - return YES; - } - - NSArray *> *tapGesture = - @[ - @{@"action": @"tap", - @"options": @{@"element": self, - @"x": @(relativeCoordinate.x), - @"y": @(relativeCoordinate.y) - } - } - ]; - return [self.application fb_performAppiumTouchActions:tapGesture elementCache:nil error:error]; + XCUICoordinate *startCoordinate = [self coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; + CGVector offset = CGVectorMake(relativeCoordinate.x, relativeCoordinate.y); + XCUICoordinate *dstCoordinate = [startCoordinate coordinateWithOffset:offset]; + [dstCoordinate tap]; + return YES; } @end diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index 1ad36c57d..c2cde607e 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -423,10 +423,8 @@ + (NSDictionary *)processArguments:(XCUIApplication *)app #endif }]; - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"11.0")) { - // https://developer.apple.com/documentation/foundation/nsprocessinfothermalstate - deviceInfo[@"thermalState"] = @(NSProcessInfo.processInfo.thermalState); - } + // https://developer.apple.com/documentation/foundation/nsprocessinfothermalstate + deviceInfo[@"thermalState"] = @(NSProcessInfo.processInfo.thermalState); return FBResponseWithObject(deviceInfo); } diff --git a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m index 24cc054fa..04e492622 100644 --- a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m @@ -48,24 +48,8 @@ - (CGPoint)fixedHitPointWith:(CGPoint)hitPoint forSnapshot:(id> *ancestors = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_ancestors; - id parentWindow = ancestors.count > 1 ? [ancestors objectAtIndex:ancestors.count - 2] : nil; - CGRect parentWindowFrame = nil == parentWindow ? snapshot.frame : parentWindow.frame; - if ((appFrame.size.height > appFrame.size.width && parentWindowFrame.size.height < parentWindowFrame.size.width) || - (appFrame.size.height < appFrame.size.width && parentWindowFrame.size.height > parentWindowFrame.size.width)) { - /* - This is the indication of the fact that transformation is broken and coordinates should be - recalculated manually. - However, upside-down case cannot be covered this way, which is not important for Appium - */ - return FBInvertPointForApplication(hitPoint, appFrame.size, interfaceOrientation); - } - return hitPoint; + // For Xcode11+ it is always necessary to adjust the tap point coordinates + return FBInvertPointForApplication(hitPoint, self.application.frame.size, interfaceOrientation); } - (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element positionOffset:(nullable NSValue *)positionOffset error:(NSError **)error @@ -74,14 +58,12 @@ - (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element positi if (nil == element) { // Only absolute offset is defined hitPoint = [positionOffset CGPointValue]; - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) { - /* - Since iOS 10.0 XCTest has a bug when it always returns portrait coordinates for UI elements - even if the device is not in portait mode. That is why we need to recalculate them manually - based on the current orientation value - */ - hitPoint = FBInvertPointForApplication(hitPoint, self.application.frame.size, self.application.interfaceOrientation); - } + /* + Since iOS 10.0 XCTest has a bug when it always returns portrait coordinates for UI elements + even if the device is not in portait mode. That is why we need to recalculate them manually + based on the current orientation value + */ + hitPoint = FBInvertPointForApplication(hitPoint, self.application.frame.size, self.application.interfaceOrientation); } else { // The offset relative to the element is defined diff --git a/WebDriverAgentLib/Utilities/FBKeyboard.m b/WebDriverAgentLib/Utilities/FBKeyboard.m index 3f3a0b016..7d474ac02 100644 --- a/WebDriverAgentLib/Utilities/FBKeyboard.m +++ b/WebDriverAgentLib/Utilities/FBKeyboard.m @@ -63,8 +63,7 @@ + (BOOL)waitUntilVisibleForApplication:(XCUIApplication *)app timeout:(NSTimeInt }]; XCUIElement *firstKey = [[app.keyboard descendantsMatchingType:XCUIElementTypeKey] matchingPredicate:keySearchPredicate].allElementsBoundByIndex.firstObject; - return firstKey.exists - && (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0") ? firstKey.hittable : firstKey.fb_isVisible); + return firstKey.exists && firstKey.hittable; }; NSString* errMessage = @"The on-screen keyboard must be present to send keys"; if (timeout <= 0) { diff --git a/WebDriverAgentLib/Utilities/FBScreen.m b/WebDriverAgentLib/Utilities/FBScreen.m index 81e7b930c..e2b25855b 100644 --- a/WebDriverAgentLib/Utilities/FBScreen.m +++ b/WebDriverAgentLib/Utilities/FBScreen.m @@ -22,17 +22,10 @@ + (double)scale + (CGSize)statusBarSizeForApplication:(XCUIApplication *)application { - XCUIApplication *app = application; - BOOL expectVisibleBar = YES; - + XCUIApplication *app = FBApplication.fb_systemApplication; // Since iOS 13 the status bar is no longer part of the application, it’s part of the SpringBoard - if (@available(iOS 13.0, *)) { - app = FBApplication.fb_systemApplication; - expectVisibleBar = NO; - } - XCUIElement *mainStatusBar = app.statusBars.allElementsBoundByIndex.firstObject; - if (!mainStatusBar || (expectVisibleBar && !mainStatusBar.fb_isVisible)) { + if (nil == mainStatusBar) { return CGSizeZero; } CGSize result = mainStatusBar.frame.size; diff --git a/WebDriverAgentLib/Utilities/FBScreenshot.m b/WebDriverAgentLib/Utilities/FBScreenshot.m index 60e467173..740048e66 100644 --- a/WebDriverAgentLib/Utilities/FBScreenshot.m +++ b/WebDriverAgentLib/Utilities/FBScreenshot.m @@ -228,7 +228,6 @@ + (nullable id)imageEncodingWithUniformTypeIdentifier:(NSString *)uti compressionQuality:(CGFloat)compressionQuality error:(NSError **)error { - // TODO: Use native accessors after we drop the support of Xcode 12.4 and below Class imageEncodingClass = NSClassFromString(@"XCTImageEncoding"); if (nil == imageEncodingClass) { [[[FBErrorBuilder builder] diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m index 33cb559b9..6696f26f0 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m @@ -297,9 +297,7 @@ - (nullable NSValue *)positionWithError:(NSError **)error } CGPoint recentPosition = self.previousItem.atPosition; CGPoint offsetRelativeToRecentPosition = (nil == x && nil == y) ? CGPointMake(0.0, 0.0) : CGPointMake(x.floatValue, y.floatValue); - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) { - offsetRelativeToRecentPosition = FBInvertOffsetForOrientation(offsetRelativeToRecentPosition, self.application.interfaceOrientation); - } + offsetRelativeToRecentPosition = FBInvertOffsetForOrientation(offsetRelativeToRecentPosition, self.application.interfaceOrientation); return [NSValue valueWithCGPoint:CGPointMake(recentPosition.x + offsetRelativeToRecentPosition.x, recentPosition.y + offsetRelativeToRecentPosition.y)]; } From 72fb12b7c08e698cb4eeac1ddada89a99b1619b2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 14 May 2023 11:24:40 +0000 Subject: [PATCH 014/133] chore(release): 5.0.0 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [5.0.0](https://github.com/appium/WebDriverAgent/compare/v4.15.1...v5.0.0) (2023-05-14) ### ⚠ BREAKING CHANGES * The minimum supported xCode/iOS version is now 13/15.0 ### Code Refactoring * Drop workarounds for legacy iOS versions ([#696](https://github.com/appium/WebDriverAgent/issues/696)) ([bb562b9](https://github.com/appium/WebDriverAgent/commit/bb562b96db6aad476970ef7bd352cb8df4f1e6c2)) --- CHANGELOG.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b57bd88c..c1b7cd70d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [5.0.0](https://github.com/appium/WebDriverAgent/compare/v4.15.1...v5.0.0) (2023-05-14) + + +### ⚠ BREAKING CHANGES + +* The minimum supported xCode/iOS version is now 13/15.0 + +### Code Refactoring + +* Drop workarounds for legacy iOS versions ([#696](https://github.com/appium/WebDriverAgent/issues/696)) ([bb562b9](https://github.com/appium/WebDriverAgent/commit/bb562b96db6aad476970ef7bd352cb8df4f1e6c2)) + ## [4.15.1](https://github.com/appium/WebDriverAgent/compare/v4.15.0...v4.15.1) (2023-05-06) diff --git a/package.json b/package.json index 4e54f3d4e..0aeff7451 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "4.15.1", + "version": "5.0.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 025b42c8a34ff0beba4379f4cb0c1d79d2b222ed Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 14 May 2023 13:27:41 +0200 Subject: [PATCH 015/133] refactor: Remove obsolete coordinate calculation workarounds needed for older xCode SDKs (#698) --- .azure-pipelines.yml | 20 ++-- WebDriverAgent.xcodeproj/project.pbxproj | 20 ---- .../Categories/XCUICoordinate+FBFix.h | 18 ---- .../Categories/XCUICoordinate+FBFix.m | 46 ---------- .../Categories/XCUIElement+FBIsVisible.m | 12 --- .../Categories/XCUIElement+FBPickerWheel.m | 16 +--- .../Categories/XCUIElement+FBScrolling.m | 44 ++------- .../Categories/XCUIElement+FBUtilities.h | 7 -- .../Categories/XCUIElement+FBUtilities.m | 49 ---------- .../Commands/FBElementCommands.m | 6 +- .../Utilities/FBAppiumActionsSynthesizer.m | 38 +++++--- .../Utilities/FBBaseActionsSynthesizer.h | 17 +--- .../Utilities/FBBaseActionsSynthesizer.m | 92 ++++++++----------- WebDriverAgentLib/Utilities/FBMathUtils.h | 6 -- WebDriverAgentLib/Utilities/FBMathUtils.m | 29 ------ .../Utilities/FBW3CActionsSynthesizer.m | 52 +++++------ .../Utilities/FBXCTestDaemonsProxy.h | 4 - .../Utilities/FBXCTestDaemonsProxy.m | 12 --- .../FBAppiumTouchActionsIntegrationTests.m | 16 ---- .../FBElementScreenshotTests.m | 52 ----------- .../FBW3CTouchActionsIntegrationTests.m | 19 ---- .../UnitTests/FBMathUtilsTests.m | 12 --- .../UnitTests/XCUICoordinateFix.m | 63 ------------- 23 files changed, 107 insertions(+), 543 deletions(-) delete mode 100644 WebDriverAgentLib/Categories/XCUICoordinate+FBFix.h delete mode 100644 WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m delete mode 100644 WebDriverAgentTests/IntegrationTests/FBElementScreenshotTests.m delete mode 100644 WebDriverAgentTests/UnitTests/XCUICoordinateFix.m diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 03ad02e58..864c786f0 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -1,20 +1,20 @@ # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml variables: - MIN_VM_IMAGE: macOS-11 - MIN_XCODE_VERSION: 12.4 - MIN_PLATFORM_VERSION: 14.4 - MIN_TV_PLATFORM_VERSION: 14.3 - MIN_TV_DEVICE_NAME: Apple TV 4K + MIN_VM_IMAGE: macOS-12 + MIN_XCODE_VERSION: 13.1 + MIN_PLATFORM_VERSION: 15.0 + MIN_TV_PLATFORM_VERSION: 15.0 + MIN_TV_DEVICE_NAME: Apple TV 4K (2nd generation) MIN_IPHONE_DEVICE_NAME: iPhone 11 - MIN_IPAD_DEVICE_NAME: iPad Pro (11-inch) (2nd generation) + MIN_IPAD_DEVICE_NAME: iPad Pro (11-inch) (3rd generation) MAX_VM_IMAGE: macOS-12 - MAX_XCODE_VERSION: 13.4 - MAX_PLATFORM_VERSION: 15.5 - MAX_PLATFORM_VERSION_TV: 15.4 + MAX_XCODE_VERSION: 14.2 + MAX_PLATFORM_VERSION: 16.2 + MAX_PLATFORM_VERSION_TV: 16.1 MAX_IPHONE_DEVICE_NAME: iPhone 13 MAX_TV_DEVICE_NAME: Apple TV 4K (2nd generation) MAX_IPAD_DEVICE_NAME: iPad Pro (11-inch) (3rd generation) - DEFAULT_NODE_VERSION: "16.x" + DEFAULT_NODE_VERSION: "18.x" pool: diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index 7b8cf620e..b719df35b 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -86,7 +86,6 @@ 641EE6042240C5CA00173FCB /* NSString+FBXMLSafeString.m in Sources */ = {isa = PBXBuildFile; fileRef = 716E0BCD1E917E810087A825 /* NSString+FBXMLSafeString.m */; }; 641EE6052240C5CA00173FCB /* FBUnknownCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7651CAEDF0C008C271F /* FBUnknownCommands.m */; }; 641EE6062240C5CA00173FCB /* FBOrientationCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB75D1CAEDF0C008C271F /* FBOrientationCommands.m */; }; - 641EE6072240C5CA00173FCB /* XCUICoordinate+FBFix.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */; }; 641EE6082240C5CA00173FCB /* FBRuntimeUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7921CAEDF0C008C271F /* FBRuntimeUtils.m */; }; 641EE6092240C5CA00173FCB /* XCUIElement+FBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE376401D59F81400ED88DD /* XCUIElement+FBUtilities.m */; }; 641EE60A2240C5CA00173FCB /* FBLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9B76A41CF7A43900275851 /* FBLogger.m */; }; @@ -160,7 +159,6 @@ 641EE65B2240C5CA00173FCB /* XCUIElementHitPointCoordinate.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35AD011E3B77D600A02D78 /* XCUIElementHitPointCoordinate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE65C2240C5CA00173FCB /* XCTDarwinNotificationExpectation.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACCE1E3B77D600A02D78 /* XCTDarwinNotificationExpectation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE65D2240C5CA00173FCB /* XCTRunnerAutomationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACEE1E3B77D600A02D78 /* XCTRunnerAutomationSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 641EE65E2240C5CA00173FCB /* XCUICoordinate+FBFix.h in Headers */ = {isa = PBXBuildFile; fileRef = EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */; }; 641EE65F2240C5CA00173FCB /* XCSourceCodeTreeNodeEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACC61E3B77D600A02D78 /* XCSourceCodeTreeNodeEnumerator.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6602240C5CA00173FCB /* XCUIElement+FBIsVisible.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7471CAEDF0C008C271F /* XCUIElement+FBIsVisible.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6612240C5CA00173FCB /* XCUIElement+FBTap.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB74B1CAEDF0C008C271F /* XCUIElement+FBTap.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -456,7 +454,6 @@ 71A7EAF91E224648001DA4F2 /* FBClassChainQueryParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A7EAF71E224648001DA4F2 /* FBClassChainQueryParser.h */; }; 71A7EAFA1E224648001DA4F2 /* FBClassChainQueryParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A7EAF81E224648001DA4F2 /* FBClassChainQueryParser.m */; }; 71A7EAFC1E229302001DA4F2 /* FBClassChainTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A7EAFB1E229302001DA4F2 /* FBClassChainTests.m */; }; - 71AB82B21FDAE8C000D1D7C3 /* FBElementScreenshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71AB82B11FDAE8C000D1D7C3 /* FBElementScreenshotTests.m */; }; 71ACF5B8242F2FDC00F0AAD4 /* FBSafariAlertTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71ACF5B7242F2FDC00F0AAD4 /* FBSafariAlertTests.m */; }; 71B155DA23070ECF00646AFB /* FBHTTPStatusCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155D923070ECF00646AFB /* FBHTTPStatusCodes.h */; settings = {ATTRIBUTES = (Public, ); }; }; 71B155DC230711E900646AFB /* FBCommandStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B155DB230711E900646AFB /* FBCommandStatus.m */; }; @@ -785,9 +782,6 @@ EE9B76AA1CF7A43900275851 /* FBMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9B76A51CF7A43900275851 /* FBMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; EEBBD48B1D47746D00656A81 /* XCUIElement+FBFind.h in Headers */ = {isa = PBXBuildFile; fileRef = EEBBD4891D47746D00656A81 /* XCUIElement+FBFind.h */; settings = {ATTRIBUTES = (Public, ); }; }; EEBBD48C1D47746D00656A81 /* XCUIElement+FBFind.m in Sources */ = {isa = PBXBuildFile; fileRef = EEBBD48A1D47746D00656A81 /* XCUIElement+FBFind.m */; }; - EEC9EED620064FAA00BC0D5B /* XCUICoordinate+FBFix.h in Headers */ = {isa = PBXBuildFile; fileRef = EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */; }; - EEC9EED720064FAA00BC0D5B /* XCUICoordinate+FBFix.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */; }; - EEC9EED920077D8E00BC0D5B /* XCUICoordinateFix.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC9EED820077D8E00BC0D5B /* XCUICoordinateFix.m */; }; EEDFE1211D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = EEDFE11F1D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h */; settings = {ATTRIBUTES = (Public, ); }; }; EEDFE1221D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDFE1201D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.m */; }; EEE16E971D33A25500172525 /* FBConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE16E961D33A25500172525 /* FBConfigurationTests.m */; }; @@ -1043,7 +1037,6 @@ 71A7EAF71E224648001DA4F2 /* FBClassChainQueryParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBClassChainQueryParser.h; sourceTree = ""; }; 71A7EAF81E224648001DA4F2 /* FBClassChainQueryParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBClassChainQueryParser.m; sourceTree = ""; }; 71A7EAFB1E229302001DA4F2 /* FBClassChainTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBClassChainTests.m; sourceTree = ""; }; - 71AB82B11FDAE8C000D1D7C3 /* FBElementScreenshotTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBElementScreenshotTests.m; sourceTree = ""; }; 71ACF5B7242F2FDC00F0AAD4 /* FBSafariAlertTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSafariAlertTests.m; sourceTree = ""; }; 71B155D923070ECF00646AFB /* FBHTTPStatusCodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBHTTPStatusCodes.h; sourceTree = ""; }; 71B155DB230711E900646AFB /* FBCommandStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBCommandStatus.m; sourceTree = ""; }; @@ -1353,9 +1346,6 @@ EEC088E41CB56AC000B65968 /* FBElementCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBElementCache.m; sourceTree = ""; }; EEC088E61CB56DA400B65968 /* FBExceptionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBExceptionHandler.h; sourceTree = ""; }; EEC088E71CB56DA400B65968 /* FBExceptionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBExceptionHandler.m; sourceTree = ""; }; - EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUICoordinate+FBFix.h"; sourceTree = ""; }; - EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUICoordinate+FBFix.m"; sourceTree = ""; }; - EEC9EED820077D8E00BC0D5B /* XCUICoordinateFix.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XCUICoordinateFix.m; sourceTree = ""; }; EEDBEBBA1CB2681900A790A2 /* WebDriverAgent.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = WebDriverAgent.bundle; sourceTree = ""; }; EEDFE11F1D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIDevice+FBHealthCheck.h"; sourceTree = ""; }; EEDFE1201D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIDevice+FBHealthCheck.m"; sourceTree = ""; }; @@ -1737,8 +1727,6 @@ 716C9DFF27315EFF005AD475 /* XCUIApplication+FBUIInterruptions.m */, 71D475C02538F5A8008D9401 /* XCUIApplicationProcess+FBQuiescence.h */, 71D475C12538F5A8008D9401 /* XCUIApplicationProcess+FBQuiescence.m */, - EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */, - EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */, 719CD8FA2126C88B00C7D0C2 /* XCUIApplication+FBAlert.h */, 719CD8FB2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m */, 71BD20711F86116100B36EC2 /* XCUIApplication+FBTouchAction.h */, @@ -1985,7 +1973,6 @@ 719A97AB1F88E7370063B4BD /* FBAppiumMultiTouchActionsIntegrationTests.m */, 719CD8FE2126C90200C7D0C2 /* FBAutoAlertsHandlerTests.m */, EE26409C1D0EBA25009BE6B0 /* FBElementAttributeTests.m */, - 71AB82B11FDAE8C000D1D7C3 /* FBElementScreenshotTests.m */, 71F5BE33252E5B2200EE9EBA /* FBElementSwipingTests.m */, EE006EAC1EB99B15006900A4 /* FBElementVisibilityTests.m */, EE6A89361D0B35920083E92B /* FBFailureProofTestCaseTests.m */, @@ -2045,7 +2032,6 @@ EE9B76581CF7987300275851 /* Info.plist */, 7139145B1DF01A12005896C2 /* NSExpressionFBFormatTests.m */, 71A224E71DE326C500844D55 /* NSPredicateFBFormatTests.m */, - EEC9EED820077D8E00BC0D5B /* XCUICoordinateFix.m */, 713914591DF01989005896C2 /* XCUIElementHelpersTests.m */, ); path = UnitTests; @@ -2311,7 +2297,6 @@ 641EE65B2240C5CA00173FCB /* XCUIElementHitPointCoordinate.h in Headers */, 641EE65C2240C5CA00173FCB /* XCTDarwinNotificationExpectation.h in Headers */, 641EE65D2240C5CA00173FCB /* XCTRunnerAutomationSession.h in Headers */, - 641EE65E2240C5CA00173FCB /* XCUICoordinate+FBFix.h in Headers */, 641EE65F2240C5CA00173FCB /* XCSourceCodeTreeNodeEnumerator.h in Headers */, 641EE6602240C5CA00173FCB /* XCUIElement+FBIsVisible.h in Headers */, 641EE6612240C5CA00173FCB /* XCUIElement+FBTap.h in Headers */, @@ -2548,7 +2533,6 @@ EE35AD3F1E3B77D600A02D78 /* XCTDarwinNotificationExpectation.h in Headers */, EE35AD5F1E3B77D600A02D78 /* XCTRunnerAutomationSession.h in Headers */, 71C9EAAC25E8415A00470CD8 /* FBScreenshot.h in Headers */, - EEC9EED620064FAA00BC0D5B /* XCUICoordinate+FBFix.h in Headers */, EE35AD371E3B77D600A02D78 /* XCSourceCodeTreeNodeEnumerator.h in Headers */, EE158AB01CBD456F00A3E3F0 /* XCUIElement+FBIsVisible.h in Headers */, 71414ED42670A1EE003A8C5D /* LRUCache.h in Headers */, @@ -3141,7 +3125,6 @@ 641EE6052240C5CA00173FCB /* FBUnknownCommands.m in Sources */, 641EE6062240C5CA00173FCB /* FBOrientationCommands.m in Sources */, 641EE7092240CDEB00173FCB /* XCUIElement+FBTVFocuse.m in Sources */, - 641EE6072240C5CA00173FCB /* XCUICoordinate+FBFix.m in Sources */, 641EE6082240C5CA00173FCB /* FBRuntimeUtils.m in Sources */, 641EE6092240C5CA00173FCB /* XCUIElement+FBUtilities.m in Sources */, 641EE60A2240C5CA00173FCB /* FBLogger.m in Sources */, @@ -3259,7 +3242,6 @@ EE158AC51CBD456F00A3E3F0 /* FBOrientationCommands.m in Sources */, 71D475C42538F5A8008D9401 /* XCUIApplicationProcess+FBQuiescence.m in Sources */, 641EE7082240CDEB00173FCB /* XCUIElement+FBTVFocuse.m in Sources */, - EEC9EED720064FAA00BC0D5B /* XCUICoordinate+FBFix.m in Sources */, 71E75E6F254824230099FC87 /* XCUIElementQuery+FBHelpers.m in Sources */, 71D04DCA25356C43008A052C /* XCUIElement+FBCaching.m in Sources */, EE158AEB1CBD456F00A3E3F0 /* FBRuntimeUtils.m in Sources */, @@ -3330,7 +3312,6 @@ 715AFAC41FFA2AAF0053896D /* FBScreenTests.m in Sources */, EE22021E1ECC618900A29571 /* FBTapTest.m in Sources */, 71930C472066434000D3AFEC /* FBPasteboardTests.m in Sources */, - 71AB82B21FDAE8C000D1D7C3 /* FBElementScreenshotTests.m in Sources */, 7150FFF722476B3A00B2EE28 /* FBForceTouchTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3382,7 +3363,6 @@ ADBC39981D07842800327304 /* XCUIElementDouble.m in Sources */, 7139145A1DF01989005896C2 /* XCUIElementHelpersTests.m in Sources */, EE6A89261D0B19E60083E92B /* FBSessionTests.m in Sources */, - EEC9EED920077D8E00BC0D5B /* XCUICoordinateFix.m in Sources */, 71A7EAFC1E229302001DA4F2 /* FBClassChainTests.m in Sources */, EE18883D1DA663EB00307AA8 /* FBMathUtilsTests.m in Sources */, ); diff --git a/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.h b/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.h deleted file mode 100644 index 14c8750eb..000000000 --- a/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#if !TARGET_OS_TV -@interface XCUICoordinate (FBFix) - -- (CGPoint)fb_screenPoint; - -@end -#endif diff --git a/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m b/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m deleted file mode 100644 index 3313cda64..000000000 --- a/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "XCUICoordinate+FBFix.h" - -#import "XCUICoordinate.h" -#import "XCUIElement+FBUtilities.h" - -# if !TARGET_OS_TV -@implementation XCUICoordinate (FBFix) - -- (CGPoint)fb_screenPoint -{ - CGPoint referencePoint = CGPointMake(0, 0); - NSValue *referencedElementFrame = nil; - if (self.element) { - CGRect elementFrame = self.element.frame; - if (self.referencedElement == self.element) { - referencedElementFrame = [NSValue valueWithCGRect:elementFrame]; - } - referencePoint = CGPointMake( - CGRectGetMinX(elementFrame) + CGRectGetWidth(elementFrame) * self.normalizedOffset.dx, - CGRectGetMinY(elementFrame) + CGRectGetHeight(elementFrame) * self.normalizedOffset.dy); - } else if (self.coordinate) { - referencePoint = self.coordinate.fb_screenPoint; - } - - CGPoint screenPoint = CGPointMake( - referencePoint.x + self.pointsOffset.dx, - referencePoint.y + self.pointsOffset.dy); - if (nil == referencedElementFrame) { - referencedElementFrame = [NSValue valueWithCGRect:self.referencedElement.frame]; - } - return CGPointMake( - MIN(CGRectGetMaxX(referencedElementFrame.CGRectValue), screenPoint.x), - MIN(CGRectGetMaxY(referencedElementFrame.CGRectValue), screenPoint.y)); -} - -@end -#endif diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m index c667a48c8..87841fc38 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m @@ -186,18 +186,6 @@ - (BOOL)fb_isVisible } CGPoint midPoint = CGPointMake(visibleRect.origin.x + visibleRect.size.width / 2, visibleRect.origin.y + visibleRect.size.height / 2); -#if !TARGET_OS_TV // TV has no orientation, so it does not need to coordinate - id appElement = ancestors.count > 0 ? [ancestors lastObject] : self; - CGRect appFrame = appElement.frame; - CGRect windowFrame = nil == parentWindow ? selfFrame : parentWindow.frame; - if ((appFrame.size.height > appFrame.size.width && windowFrame.size.height < windowFrame.size.width) || - (appFrame.size.height < appFrame.size.width && windowFrame.size.height > windowFrame.size.width)) { - // This is the indication of the fact that transformation is broken and coordinates should be - // recalculated manually. - // However, upside-down case cannot be covered this way, which is not important for Appium - midPoint = FBInvertPointForApplication(midPoint, appFrame.size, FBApplication.fb_activeApplication.interfaceOrientation); - } -#endif id hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint]; if (nil != hitElement) { if (FBIsAXElementEqualToOther(self.accessibilityElement, hitElement)) { diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m index adce016ff..5aeed18e6 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m @@ -12,9 +12,7 @@ #import "FBRunLoopSpinner.h" #import "FBXCElementSnapshot.h" #import "FBXCodeCompatibility.h" -#import "XCUIApplication+FBTouchAction.h" #import "XCUICoordinate.h" -#import "XCUICoordinate+FBFix.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBResolve.h" @@ -31,16 +29,7 @@ - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)erro NSString *previousValue = snapshot.value; XCUICoordinate *startCoord = [self coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)]; XCUICoordinate *endCoord = [startCoord coordinateWithOffset:CGVectorMake(0.0, relativeHeightOffset * snapshot.frame.size.height)]; - CGPoint tapPoint = endCoord.fb_screenPoint; - NSArray *> *gesture = - @[@{ - @"action": @"tap", - @"options": @{ - @"x": @(tapPoint.x), - @"y": @(tapPoint.y), - } - } - ]; + [endCoord tap]; // If picker value is reflected in its accessiblity id // then fetching of the next snapshot may fail with StaleElementReferenceError // because we bound elements by their accessbility ids by default. @@ -48,9 +37,6 @@ - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)erro // unique element identifier (UID), so it could be found next time even if its // id is different from the initial one. See https://github.com/appium/appium/issues/17569 XCUIElement *stableInstance = self.fb_stableInstance; - if (![self.application fb_performAppiumTouchActions:gesture elementCache:nil error:error]) { - return NO; - } return [[[[FBRunLoopSpinner new] timeout:VALUE_CHANGE_TIMEOUT] timeoutErrorMessage:[NSString stringWithFormat:@"Picker wheel value has not been changed after %@ seconds timeout", @(VALUE_CHANGE_TIMEOUT)]] diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m index f9582b52a..52be1a557 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m @@ -16,11 +16,9 @@ #import "FBXCodeCompatibility.h" #import "FBXCElementSnapshotWrapper.h" #import "FBXCElementSnapshotWrapper+Helpers.h" -#import "XCUIApplication+FBTouchAction.h" #import "XCUIElement+FBCaching.h" #import "XCUIApplication.h" #import "XCUICoordinate.h" -#import "XCUICoordinate+FBFix.h" #import "XCUIElement+FBIsVisible.h" #import "XCUIElement.h" #import "XCUIElement+FBUtilities.h" @@ -28,7 +26,8 @@ const CGFloat FBFuzzyPointThreshold = 20.f; //Smallest determined value that is not interpreted as touch const CGFloat FBScrollToVisibleNormalizedDistance = .5f; -const CGFloat FBTouchEventDelay = 1.f; +const CGFloat FBTouchEventDelay = 0.5f; +const CGFloat FBTouchVelocity = 300; // pixels per sec const CGFloat FBScrollTouchProportion = 0.75f; #if !TARGET_OS_TV @@ -321,45 +320,16 @@ - (BOOL)fb_scrollAncestorScrollViewByVectorWithinScrollViewFrame:(CGVector)vecto XCUICoordinate *appCoordinate = [[XCUICoordinate alloc] initWithElement:application normalizedOffset:CGVectorMake(0.0, 0.0)]; XCUICoordinate *startCoordinate = [[XCUICoordinate alloc] initWithCoordinate:appCoordinate pointsOffset:hitpointOffset]; - CGPoint startPoint = startCoordinate.fb_screenPoint; XCUICoordinate *endCoordinate = [[XCUICoordinate alloc] initWithCoordinate:startCoordinate pointsOffset:vector]; - CGPoint endPoint = endCoordinate.fb_screenPoint; - if (FBPointFuzzyEqualToPoint(startPoint, endPoint, FBFuzzyPointThreshold)) { + if (FBPointFuzzyEqualToPoint(startCoordinate.screenPoint, endCoordinate.screenPoint, FBFuzzyPointThreshold)) { return YES; } - NSArray *> *gesture = - @[@{ - @"action": @"press", - @"options": @{ - @"x": @(startPoint.x), - @"y": @(startPoint.y), - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @(FBTouchEventDelay * 1000), - } - }, - @{ - @"action": @"moveTo", - @"options": @{ - @"x": @(endPoint.x), - @"y": @(endPoint.y), - } - }, - @{ - @"action": @"release" - } - ]; - if (![application fb_performAppiumTouchActions:gesture - elementCache:nil - error:error]) { - return NO; - } - + [startCoordinate pressForDuration:FBTouchEventDelay + thenDragToCoordinate:endCoordinate + withVelocity:FBTouchVelocity + thenHoldForDuration:FBTouchEventDelay]; return YES; } diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h index de79e563c..66b9ee2c9 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h @@ -98,13 +98,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)fb_waitUntilStableWithTimeout:(NSTimeInterval)timeout; -/** - Returns screenshot of the particular element - @param error If there is an error, upon return contains an NSError object that describes the problem. - @return Element screenshot as PNG-encoded data or nil in case of failure - */ -- (nullable NSData *)fb_screenshotWithError:(NSError*__autoreleasing*)error; - @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m index d78cfd99e..b5a072c06 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m @@ -197,53 +197,4 @@ - (void)fb_waitUntilStableWithTimeout:(NSTimeInterval)timeout FBConfiguration.waitForIdleTimeout = previousTimeout; } -- (NSData *)fb_screenshotWithError:(NSError **)error -{ - id selfSnapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; - if (CGRectIsEmpty(selfSnapshot.frame)) { - if (error) { - *error = [[FBErrorBuilder.builder withDescription:@"Cannot get a screenshot of zero-sized element"] build]; - } - return nil; - } - - CGRect elementRect = selfSnapshot.frame; -#if !TARGET_OS_TV - UIInterfaceOrientation orientation = self.application.interfaceOrientation; - if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) { - // Workaround XCTest bug when element frame is returned as in portrait mode even if the screenshot is rotated - NSArray> *ancestors = [FBXCElementSnapshotWrapper ensureWrapped:selfSnapshot].fb_ancestors; - id parentWindow = nil; - if (1 == ancestors.count) { - parentWindow = selfSnapshot; - } else if (ancestors.count > 1) { - parentWindow = [ancestors objectAtIndex:ancestors.count - 2]; - } - if (nil != parentWindow) { - CGRect appFrame = ancestors.lastObject.frame; - CGRect parentWindowFrame = parentWindow.frame; - if (CGRectEqualToRect(appFrame, parentWindowFrame) - || (appFrame.size.width > appFrame.size.height && parentWindowFrame.size.width > parentWindowFrame.size.height) - || (appFrame.size.width < appFrame.size.height && parentWindowFrame.size.width < parentWindowFrame.size.height)) { - CGPoint fixedOrigin = orientation == UIInterfaceOrientationLandscapeLeft ? - CGPointMake(appFrame.size.height - elementRect.origin.y - elementRect.size.height, elementRect.origin.x) : - CGPointMake(elementRect.origin.y, appFrame.size.width - elementRect.origin.x - elementRect.size.width); - elementRect = CGRectMake(fixedOrigin.x, fixedOrigin.y, elementRect.size.height, elementRect.size.width); - } - } - } -#endif - - // adjust element rect for the actual screen scale - XCUIScreen *mainScreen = XCUIScreen.mainScreen; - elementRect = CGRectMake(elementRect.origin.x * mainScreen.scale, elementRect.origin.y * mainScreen.scale, - elementRect.size.width * mainScreen.scale, elementRect.size.height * mainScreen.scale); - - return [FBScreenshot takeInOriginalResolutionWithQuality:FBConfiguration.screenshotQuality - rect:elementRect - error:error]; -} - @end diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index d5feca45e..6734714c6 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -594,10 +594,10 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - NSError *error; - NSData *screenshotData = [element fb_screenshotWithError:&error]; + NSData *screenshotData = [element.screenshot PNGRepresentation]; if (nil == screenshotData) { - return FBResponseWithStatus([FBCommandStatus unableToCaptureScreenErrorWithMessage:error.description + NSString *errMsg = [NSString stringWithFormat:@"Cannot take a screenshot of %@", element.description]; + return FBResponseWithStatus([FBCommandStatus unableToCaptureScreenErrorWithMessage:errMsg traceback:nil]); } NSString *screenshot = [screenshotData base64EncodedStringWithOptions:0]; diff --git a/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m index 7aec01b08..235d97e63 100644 --- a/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m @@ -80,7 +80,7 @@ @implementation FBAppiumGestureItem - (nullable instancetype)initWithActionItem:(NSDictionary *)item application:(XCUIApplication *)application - atPosition:(nullable NSValue *)atPosition + atPosition:(nullable XCUICoordinate *)atPosition offset:(double)offset error:(NSError **)error { @@ -90,14 +90,14 @@ - (nullable instancetype)initWithActionItem:(NSDictionary *)item self.application = application; self.offset = offset; id options = [item objectForKey:FB_OPTIONS_KEY]; - if (atPosition) { - self.atPosition = [atPosition CGPointValue]; + if (nil != atPosition) { + self.atPosition = (id) atPosition; } else { - NSValue *result = [self coordinatesWithOptions:options error:error]; + XCUICoordinate *result = [self coordinatesWithOptions:options error:error]; if (nil == result) { return nil; } - self.atPosition = [result CGPointValue]; + self.atPosition = result; } self.duration = [self durationWithOptions:options]; if (self.duration < 0) { @@ -124,7 +124,8 @@ - (double)durationWithOptions:(nullable NSDictionary *)options 0.0; } -- (nullable NSValue *)coordinatesWithOptions:(nullable NSDictionary *)options error:(NSError **)error +- (nullable XCUICoordinate *)coordinatesWithOptions:(nullable NSDictionary *)options + error:(NSError **)error { if (![options isKindOfClass:NSDictionary.class]) { NSString *description = [NSString stringWithFormat:@"'%@' key is mandatory for '%@' action", FB_OPTIONS_KEY, self.class.actionName]; @@ -169,7 +170,7 @@ + (BOOL)hasAbsolutePositioning NSTimeInterval currentOffset = FBMillisToSeconds(self.offset); NSMutableArray *result = [NSMutableArray array]; XCPointerEventPath *currentPath = [[XCPointerEventPath alloc] - initForTouchAtPoint:self.atPosition + initForTouchAtPoint:self.atPosition.screenPoint offset:currentOffset]; [result addObject:currentPath]; currentOffset += FBMillisToSeconds(FB_TAP_DURATION_MS); @@ -180,7 +181,8 @@ + (BOOL)hasAbsolutePositioning NSNumber *tapCount = [options objectForKey:FB_OPTION_COUNT] ?: @1; for (NSInteger times = 1; times < tapCount.integerValue; ++times) { currentOffset += FBMillisToSeconds(FB_INTERTAP_MIN_DURATION_MS); - XCPointerEventPath *nextPath = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:currentOffset]; + XCPointerEventPath *nextPath = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint + offset:currentOffset]; [result addObject:nextPath]; currentOffset += FBMillisToSeconds(FB_TAP_DURATION_MS); [nextPath liftUpAtOffset:currentOffset]; @@ -204,7 +206,7 @@ @implementation FBPressItem - (nullable instancetype)initWithActionItem:(NSDictionary *)item application:(XCUIApplication *)application - atPosition:(nullable NSValue *)atPosition + atPosition:(nullable XCUICoordinate *)atPosition offset:(double)offset error:(NSError **)error { @@ -239,7 +241,7 @@ + (BOOL)hasAbsolutePositioning error:(NSError **)error { XCPointerEventPath *result = [[XCPointerEventPath alloc] - initForTouchAtPoint:self.atPosition + initForTouchAtPoint:self.atPosition.screenPoint offset:FBMillisToSeconds(self.offset)]; if (nil != self.pressure && nil != result.pointerEvents.lastObject) { XCPointerEvent *pointerEvent = (XCPointerEvent *)result.pointerEvents.lastObject; @@ -272,7 +274,7 @@ + (BOOL)hasAbsolutePositioning currentItemIndex:(NSUInteger)currentItemIndex error:(NSError **)error { - return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition + return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint offset:FBMillisToSeconds(self.offset)]]; } @@ -312,7 +314,8 @@ + (BOOL)hasAbsolutePositioning } } NSTimeInterval currentOffset = FBMillisToSeconds(self.offset + self.duration); - XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:currentOffset]; + XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint + offset:currentOffset]; if (currentItemIndex == allItems.count - 1) { [result liftUpAtOffset:currentOffset]; } @@ -353,7 +356,8 @@ + (BOOL)hasAbsolutePositioning return nil; } - [eventPath moveToPoint:self.atPosition atOffset:FBMillisToSeconds(self.offset)]; + [eventPath moveToPoint:self.atPosition.screenPoint + atOffset:FBMillisToSeconds(self.offset)]; return @[]; } @@ -509,7 +513,11 @@ @implementation FBAppiumActionsSynthesizer return nil; } FBAppiumGestureItem *lastItem = [chain.items lastObject]; - gestureItem = [[gestureItemClass alloc] initWithActionItem:actionItem application:self.application atPosition:[NSValue valueWithCGPoint:lastItem.atPosition] offset:chain.durationOffset error:error]; + gestureItem = [[gestureItemClass alloc] initWithActionItem:actionItem + application:self.application + atPosition:lastItem.atPosition + offset:chain.durationOffset + error:error]; } if (nil == gestureItem) { return nil; @@ -527,7 +535,7 @@ - (nullable XCSynthesizedEventRecord *)synthesizeWithError:(NSError **)error BOOL isMultiTouch = [self.actions.firstObject isKindOfClass:NSArray.class]; eventRecord = [[XCSynthesizedEventRecord alloc] initWithName:(isMultiTouch ? @"Multi-Finger Touch Action" : @"Single-Finger Touch Action") - interfaceOrientation:[FBXCTestDaemonsProxy orientationWithApplication:self.application]]; + interfaceOrientation:self.application.interfaceOrientation]; for (NSArray *> *action in (isMultiTouch ? self.actions : @[self.actions])) { NSArray *> *preprocessedAction = [self preprocessAction:action]; NSArray *eventPaths = [self eventPathsWithAction:preprocessedAction error:error]; diff --git a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h index d50408215..5f779194f 100644 --- a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +++ b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h @@ -51,19 +51,10 @@ NS_ASSUME_NONNULL_BEGIN @interface FBBaseGestureItem : FBBaseActionItem /*! Absolute position on the screen where the gesure should be performed */ -@property (nonatomic) CGPoint atPosition; +@property (nonatomic) XCUICoordinate *atPosition; /*! Gesture duration in milliseconds */ @property (nonatomic) double duration; -/** - Returns fixed hit point coordinates for the case when XCTest fails to transform element snaapshot properly on screen rotation. - - @param hitPoint The initial hitpoint coordinates - @param snapshot Element's snapshot instance - @return The fixed hit point coordinates, if there is a need to fix them, or the unchanged hit point value - */ -- (CGPoint)fixedHitPointWith:(CGPoint)hitPoint forSnapshot:(id)snapshot; - /** Calculate absolute gesture position on the screen based on provided element and positionOffset values. @@ -72,9 +63,9 @@ NS_ASSUME_NONNULL_BEGIN @param error If there is an error, upon return contains an NSError object that describes the problem @return Adbsolute gesture position on the screen or nil if the calculation fails (for example, the element is invisible) */ -- (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element - positionOffset:(nullable NSValue *)positionOffset - error:(NSError **)error; +- (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element + positionOffset:(nullable NSValue *)positionOffset + error:(NSError **)error; @end diff --git a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m index 04e492622..6d4c046a5 100644 --- a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m @@ -31,7 +31,10 @@ + (NSString *)actionName return nil; } -- (NSArray *)addToEventPath:(XCPointerEventPath *)eventPath allItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex error:(NSError **)error +- (NSArray *)addToEventPath:(XCPointerEventPath *)eventPath + allItems:(NSArray *)allItems + currentItemIndex:(NSUInteger)currentItemIndex + error:(NSError **)error { @throw [[FBErrorBuilder.builder withDescription:@"Override this method in subclasses"] build]; return nil; @@ -41,66 +44,40 @@ + (NSString *)actionName @implementation FBBaseGestureItem -- (CGPoint)fixedHitPointWith:(CGPoint)hitPoint forSnapshot:(id)snapshot +- (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element + positionOffset:(nullable NSValue *)positionOffset + error:(NSError **)error { - UIInterfaceOrientation interfaceOrientation = self.application.interfaceOrientation; - if (interfaceOrientation == UIInterfaceOrientationPortrait) { - // There is no need to recalculate anything for portrait orientation - return hitPoint; - } - // For Xcode11+ it is always necessary to adjust the tap point coordinates - return FBInvertPointForApplication(hitPoint, self.application.frame.size, interfaceOrientation); -} - -- (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element positionOffset:(nullable NSValue *)positionOffset error:(NSError **)error -{ - CGPoint hitPoint; if (nil == element) { + CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y); // Only absolute offset is defined - hitPoint = [positionOffset CGPointValue]; - /* - Since iOS 10.0 XCTest has a bug when it always returns portrait coordinates for UI elements - even if the device is not in portait mode. That is why we need to recalculate them manually - based on the current orientation value - */ - hitPoint = FBInvertPointForApplication(hitPoint, self.application.frame.size, self.application.interfaceOrientation); - } else { - // The offset relative to the element is defined - - id snapshot = element.fb_isResolvedFromCache.boolValue - ? element.lastSnapshot - : element.fb_takeSnapshot; - if (nil == positionOffset) { - NSValue *hitPointValue = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_hitPoint; - if (nil != hitPointValue) { - // short circuit element hitpoint - return hitPointValue; - } - [FBLogger logFmt:@"Will use the frame of '%@' for hit point calculation instead", element.debugDescription]; - } - CGRect visibleFrame = snapshot.visibleFrame; - CGRect frame = CGRectIsEmpty(visibleFrame) ? element.frame : visibleFrame; - if (CGRectIsEmpty(frame)) { - [FBLogger log:self.application.fb_descriptionRepresentation]; - NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable", element.description]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; + return [[self.application coordinateWithNormalizedOffset:CGVectorMake(0, 0)] coordinateWithOffset:offset]; + } + + // The offset relative to the element is defined + if (nil == positionOffset) { + if (element.hittable) { + // short circuit element hitpoint + return element.hitPointCoordinate; } - if (nil == positionOffset) { - hitPoint = CGPointMake(frame.origin.x + frame.size.width / 2, - frame.origin.y + frame.size.height / 2); - } else { - CGPoint origin = frame.origin; - hitPoint = CGPointMake(origin.x, origin.y); - CGPoint offsetValue = [positionOffset CGPointValue]; - hitPoint = CGPointMake(hitPoint.x + offsetValue.x, hitPoint.y + offsetValue.y); - // TODO: Shall we throw an exception if hitPoint is out of the element frame? + [FBLogger logFmt:@"Will use the frame of '%@' for hit point calculation instead", element.debugDescription]; + } + if (CGRectIsEmpty(element.frame)) { + [FBLogger log:self.application.fb_descriptionRepresentation]; + NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable", + element.description]; + if (error) { + *error = [[FBErrorBuilder.builder withDescription:description] build]; } - hitPoint = [self fixedHitPointWith:hitPoint forSnapshot:snapshot]; + return nil; + } + if (nil == positionOffset) { + return [element coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)]; } - return [NSValue valueWithCGPoint:hitPoint]; + + CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y); + // TODO: Shall we throw an exception if hitPoint is out of the element frame? + return [[element coordinateWithNormalizedOffset:CGVectorMake(0, 0)] coordinateWithOffset:offset]; } @end @@ -161,7 +138,10 @@ - (void)addItem:(FBBaseActionItem *)item __attribute__((noreturn)) @implementation FBBaseActionsSynthesizer -- (instancetype)initWithActions:(NSArray *)actions forApplication:(XCUIApplication *)application elementCache:(nullable FBElementCache *)elementCache error:(NSError **)error +- (instancetype)initWithActions:(NSArray *)actions + forApplication:(XCUIApplication *)application + elementCache:(nullable FBElementCache *)elementCache + error:(NSError **)error { self = [super init]; if (self) { diff --git a/WebDriverAgentLib/Utilities/FBMathUtils.h b/WebDriverAgentLib/Utilities/FBMathUtils.h index 222a2ef67..2d52d3e6d 100644 --- a/WebDriverAgentLib/Utilities/FBMathUtils.h +++ b/WebDriverAgentLib/Utilities/FBMathUtils.h @@ -32,12 +32,6 @@ BOOL FBSizeFuzzyEqualToSize(CGSize size1, CGSize size2, CGFloat threshold); BOOL FBRectFuzzyEqualToRect(CGRect rect1, CGRect rect2, CGFloat threshold); #if !TARGET_OS_TV -/*! Inverts point if necessary to match location on screen */ -CGPoint FBInvertPointForApplication(CGPoint point, CGSize screenSize, UIInterfaceOrientation orientation); - -/*! Inverts offset if necessary to match screen orientation */ -CGPoint FBInvertOffsetForOrientation(CGPoint offset, UIInterfaceOrientation orientation); - /*! Inverts size if necessary to match current screen orientation */ CGSize FBAdjustDimensionsForApplication(CGSize actualSize, UIInterfaceOrientation orientation); #endif diff --git a/WebDriverAgentLib/Utilities/FBMathUtils.m b/WebDriverAgentLib/Utilities/FBMathUtils.m index 0cff32fcf..44ee257dc 100644 --- a/WebDriverAgentLib/Utilities/FBMathUtils.m +++ b/WebDriverAgentLib/Utilities/FBMathUtils.m @@ -46,35 +46,6 @@ BOOL FBRectFuzzyEqualToRect(CGRect rect1, CGRect rect2, CGFloat threshold) } #if !TARGET_OS_TV -CGPoint FBInvertPointForApplication(CGPoint point, CGSize screenSize, UIInterfaceOrientation orientation) -{ - switch (orientation) { - case UIInterfaceOrientationUnknown: - case UIInterfaceOrientationPortrait: - return point; - case UIInterfaceOrientationPortraitUpsideDown: - return CGPointMake(screenSize.width - point.x, screenSize.height - point.y); - case UIInterfaceOrientationLandscapeLeft: - return CGPointMake(point.y, MAX(screenSize.width, screenSize.height) - point.x); - case UIInterfaceOrientationLandscapeRight: - return CGPointMake(MIN(screenSize.width, screenSize.height) - point.y, point.x); - } -} - -CGPoint FBInvertOffsetForOrientation(CGPoint offset, UIInterfaceOrientation orientation) -{ - switch (orientation) { - case UIInterfaceOrientationUnknown: - case UIInterfaceOrientationPortrait: - return offset; - case UIInterfaceOrientationPortraitUpsideDown: - return CGPointMake(-offset.x, -offset.y); - case UIInterfaceOrientationLandscapeLeft: - return CGPointMake(offset.y, -offset.x); - case UIInterfaceOrientationLandscapeRight: - return CGPointMake(-offset.y, offset.x); - } -} CGSize FBAdjustDimensionsForApplication(CGSize actualSize, UIInterfaceOrientation orientation) { diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m index 6696f26f0..dc5060568 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m @@ -133,16 +133,16 @@ - (nullable instancetype)initWithActionItem:(NSDictionary *)acti return nil; } self.duration = durationObj.doubleValue; - NSValue *position = [self positionWithError:error]; + XCUICoordinate *position = [self positionWithError:error]; if (nil == position) { return nil; } - self.atPosition = [position CGPointValue]; + self.atPosition = position; } return self; } -- (nullable NSValue *)positionWithError:(NSError **)error +- (nullable XCUICoordinate *)positionWithError:(NSError **)error { if (nil == self.previousItem) { NSString *errorDescription = [NSString stringWithFormat:@"The '%@' action item must be preceded by %@ item", self.actionItem, FB_ACTION_ITEM_TYPE_POINTER_MOVE]; @@ -151,39 +151,32 @@ - (nullable NSValue *)positionWithError:(NSError **)error } return nil; } - return [NSValue valueWithCGPoint:self.previousItem.atPosition]; + return self.previousItem.atPosition; } -- (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element - positionOffset:(nullable NSValue *)positionOffset - error:(NSError **)error +- (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element + positionOffset:(nullable NSValue *)positionOffset + error:(NSError **)error { if (nil == element || nil == positionOffset) { return [super hitpointWithElement:element positionOffset:positionOffset error:error]; } // An offset relative to the element is defined - id snapshot = element.fb_isResolvedFromCache.boolValue - ? element.lastSnapshot - : element.fb_takeSnapshot; - CGRect frame = snapshot.frame; - if (CGRectIsEmpty(frame)) { + if (CGRectIsEmpty(element.frame)) { [FBLogger log:self.application.fb_descriptionRepresentation]; - NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable", [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_description]; + NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable", + element.description]; if (error) { *error = [[FBErrorBuilder.builder withDescription:description] build]; } return nil; } - CGRect visibleFrame = snapshot.visibleFrame; - frame = CGRectIsEmpty(visibleFrame) ? frame : visibleFrame; + // W3C standard requires that relative element coordinates start at the center of the element's rectangle - CGPoint hitPoint = CGPointMake(frame.origin.x + frame.size.width / 2, frame.origin.y + frame.size.height / 2); - CGPoint offsetValue = [positionOffset CGPointValue]; - hitPoint = CGPointMake(hitPoint.x + offsetValue.x, hitPoint.y + offsetValue.y); + CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y); // TODO: Shall we throw an exception if hitPoint is out of the element frame? - hitPoint = [self fixedHitPointWith:hitPoint forSnapshot:snapshot]; - return [NSValue valueWithCGPoint:hitPoint]; + return [[element coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)] coordinateWithOffset:offset]; } @end @@ -220,7 +213,7 @@ + (NSString *)actionName } } if (nil == self.pressure) { - XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition + XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint offset:FBMillisToSeconds(self.offset)]; return @[result]; } @@ -247,7 +240,7 @@ + (NSString *)actionName @implementation FBPointerMoveItem -- (nullable NSValue *)positionWithError:(NSError **)error +- (nullable XCUICoordinate *)positionWithError:(NSError **)error { static NSArray *supportedOriginTypes; static dispatch_once_t onceToken; @@ -295,10 +288,9 @@ - (nullable NSValue *)positionWithError:(NSError **)error } return nil; } - CGPoint recentPosition = self.previousItem.atPosition; - CGPoint offsetRelativeToRecentPosition = (nil == x && nil == y) ? CGPointMake(0.0, 0.0) : CGPointMake(x.floatValue, y.floatValue); - offsetRelativeToRecentPosition = FBInvertOffsetForOrientation(offsetRelativeToRecentPosition, self.application.interfaceOrientation); - return [NSValue valueWithCGPoint:CGPointMake(recentPosition.x + offsetRelativeToRecentPosition.x, recentPosition.y + offsetRelativeToRecentPosition.y)]; + XCUICoordinate *recentPosition = self.previousItem.atPosition; + CGVector offsetRelativeToRecentPosition = (nil == x && nil == y) ? CGVectorMake(0, 0) : CGVectorMake(x.floatValue, y.floatValue); + return [recentPosition coordinateWithOffset:offsetRelativeToRecentPosition]; } + (NSString *)actionName @@ -312,9 +304,11 @@ + (NSString *)actionName error:(NSError **)error { if (nil == eventPath) { - return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:FBMillisToSeconds(self.offset + self.duration)]]; + return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint + offset:FBMillisToSeconds(self.offset + self.duration)]]; } - [eventPath moveToPoint:self.atPosition atOffset:FBMillisToSeconds(self.offset + self.duration)]; + [eventPath moveToPoint:self.atPosition.screenPoint + atOffset:FBMillisToSeconds(self.offset + self.duration)]; return @[]; } @@ -888,7 +882,7 @@ - (nullable XCSynthesizedEventRecord *)synthesizeWithError:(NSError **)error { XCSynthesizedEventRecord *eventRecord = [[XCSynthesizedEventRecord alloc] initWithName:@"W3C Touch Action" - interfaceOrientation:[FBXCTestDaemonsProxy orientationWithApplication:self.application]]; + interfaceOrientation:self.application.interfaceOrientation]; NSMutableDictionary *> *actionsMapping = [NSMutableDictionary new]; NSMutableArray *actionIds = [NSMutableArray new]; for (NSDictionary *action in self.actions) { diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h index 8c795c5be..307edb40d 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h @@ -23,10 +23,6 @@ NS_ASSUME_NONNULL_BEGIN + (id)testRunnerProxy; -#if !TARGET_OS_TV -+ (UIInterfaceOrientation)orientationWithApplication:(XCUIApplication *)application; -#endif - + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSError *__autoreleasing*)error; diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m index f6ebcc42c..99b9d8ea9 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m @@ -30,7 +30,6 @@ @implementation FBXCTestDaemonsProxy + (void)load { - // XCTRunnerDaemonSession class is only available since Xcode 8.3 dispatch_once(&onceTestRunnerDaemonClass, ^{ FBXCTRunnerDaemonSessionClass = objc_lookUpClass("XCTRunnerDaemonSession"); }); @@ -60,17 +59,6 @@ + (void)load return ((XCTRunnerDaemonSession *)[FBXCTRunnerDaemonSessionClass sharedSession]).daemonProxy; } -#if !TARGET_OS_TV -+ (UIInterfaceOrientation)orientationWithApplication:(XCUIApplication *)application -{ - if (nil == FBXCTRunnerDaemonSessionClass || - [[FBXCTRunnerDaemonSessionClass sharedSession] useLegacyEventCoordinateTransformationPath]) { - return application.interfaceOrientation; - } - return UIInterfaceOrientationPortrait; -} -#endif - + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSError *__autoreleasing*)error { __block BOOL didSucceed = NO; diff --git a/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m index 161fc788b..d48b3da77 100644 --- a/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m @@ -194,14 +194,6 @@ - (void)testTapByCoordinates - (void)testDoubleTap { - if ([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPad && - SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) { - // "tap the element" does not work on iPadOS simulator after change the rotation in iOS 15 - // while selecting the element worked. (I confirmed with getting an element screenshot that - // the FBShowAlertButtonName was actually selected after changing the orientation.) - return; - } - NSArray *> *gesture = @[@{ @"action": @"tap", @@ -214,16 +206,8 @@ - (void)testDoubleTap [self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft]; } -// TODO: UIDeviceOrientationLandscapeRight is not so good in iOS 16? (Especially simulators) - (void)testPress { - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) { - // Does not work on iOS 15.0. - // The same action tap the FBShowAlertButtonName after rotating the screen - // worked with W3C actions. `.click` action did not work. - return; - } - NSArray *> *gesture = @[@{ @"action": @"press", diff --git a/WebDriverAgentTests/IntegrationTests/FBElementScreenshotTests.m b/WebDriverAgentTests/IntegrationTests/FBElementScreenshotTests.m deleted file mode 100644 index 08c6a9bcf..000000000 --- a/WebDriverAgentTests/IntegrationTests/FBElementScreenshotTests.m +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBMacros.h" -#import "FBIntegrationTestCase.h" -#import "XCUIDevice+FBRotation.h" -#import "XCUIElement+FBUtilities.h" -#import "XCUIScreen.h" - -@interface FBElementScreenshotTests : FBIntegrationTestCase -@end - -@implementation FBElementScreenshotTests - -- (void)setUp -{ - [super setUp]; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self launchApplication]; - [self goToAlertsPage]; - }); -} - -- (void)tearDown -{ - [self resetOrientation]; - [super tearDown]; -} - -- (void)testElementScreenshot -{ - [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:UIDeviceOrientationLandscapeLeft]; - XCUIElement *button = self.testedApplication.buttons[FBShowAlertButtonName]; - NSError *error = nil; - NSData *screenshotData = [button fb_screenshotWithError:&error]; - XCTAssertNotNil(screenshotData); - XCTAssertNil(error); - UIImage *image = [UIImage imageWithData:screenshotData]; - XCTAssertNotNil(image); - XCTAssertTrue(image.size.width > image.size.height); -} - -@end diff --git a/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m index ceaf3ed9c..8549d3016 100644 --- a/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m @@ -294,18 +294,8 @@ - (void)testTap [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait]; } -// TODO: UIDeviceOrientationLandscapeLeft did not work in iOS 16 simumlator. -// UIDeviceOrientationPortrait was ok. - (void)testDoubleTap { - if ([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPad && - SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) { - // "tap the element" does not work on iPadOS simulator after change the rotation in iOS 15 - // while selecting the element worked. (I confirmed with getting an element screenshot that - // the FBShowAlertButtonName was actually selected after changing the orientation.) - return; - } - NSArray *> *gesture = @[@{ @"type": @"pointer", @@ -326,17 +316,8 @@ - (void)testDoubleTap [self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft]; } -// TODO: UIDeviceOrientationLandscapeRight did not work in iOS 16 simumlator. -// UIDeviceOrientationPortrait was ok. - (void)testLongPressWithCombinedPause { - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) { - // Xcode 13 x iOS 14 also does not work while Xcode 12.5 x iOS 14 worked. - // Skip this test for iOS 15 since iOS 15 works with Xcode 13 at least. - return; - } - - NSArray *> *gesture = @[@{ @"type": @"pointer", diff --git a/WebDriverAgentTests/UnitTests/FBMathUtilsTests.m b/WebDriverAgentTests/UnitTests/FBMathUtilsTests.m index d586d8a59..14e71ebe1 100644 --- a/WebDriverAgentTests/UnitTests/FBMathUtilsTests.m +++ b/WebDriverAgentTests/UnitTests/FBMathUtilsTests.m @@ -98,18 +98,6 @@ - (void)testFuzzyEqualRectsSymmetry XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(-1, -1, 1, 1), 1)); } - -- (void)testPointInvertion -{ - const CGPoint testPoint = CGPointMake(1, 2); - const CGSize screenSize = CGSizeMake(10, 15); - const CGFloat t = FBDefaultFrameFuzzyThreshold; - XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(1, 2), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationPortrait), t)); - XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(9, 13), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationPortraitUpsideDown), t)); - XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(2, 14), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationLandscapeLeft), t)); - XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(8, 1), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationLandscapeRight), t)); -} - - (void)testSizeInversion { const CGSize screenSizePortrait = CGSizeMake(10, 15); diff --git a/WebDriverAgentTests/UnitTests/XCUICoordinateFix.m b/WebDriverAgentTests/UnitTests/XCUICoordinateFix.m deleted file mode 100644 index 562d1105b..000000000 --- a/WebDriverAgentTests/UnitTests/XCUICoordinateFix.m +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -#import "FBMathUtils.h" -#import "XCUICoordinate.h" -#import "XCUICoordinate+FBFix.h" -#import "XCUIElementDouble.h" - -@interface XCUICoordinateFix : XCTestCase -@property (nonatomic, strong, nullable) XCUIElement *mockElement; -@property (nonatomic, strong, nullable) XCUICoordinate *defaultCoordinate; -@end - -@implementation XCUICoordinateFix - -- (void)setUp -{ - [super setUp]; - XCUIElementDouble *element = [XCUIElementDouble new]; - element.frame = CGRectMake(1, 2, 9, 10); - self.mockElement = (XCUIElement *)element; - self.defaultCoordinate = [[XCUICoordinate alloc] initWithElement:self.mockElement normalizedOffset:CGVectorMake(0.0, 0.0)]; -} - -- (void)testCoordinateWithElement -{ - XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithElement:self.mockElement normalizedOffset:CGVectorMake(0.0, 0.0)]; - XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(1, 2), 0.1)); -} - -- (void)testCoordinateWithElementWithOffset -{ - XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithElement:self.mockElement normalizedOffset:CGVectorMake(0.5, 0.5)]; - XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(5.5, 7), 0.1)); -} - -- (void)testCoordinateWithCoordinate -{ - XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithCoordinate:self.defaultCoordinate pointsOffset:CGVectorMake(0, 0)]; - XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(1, 2), 0.1)); -} - -- (void)testCoordinateWithCoordinateWithOffset -{ - XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithCoordinate:self.defaultCoordinate pointsOffset:CGVectorMake(1, 2)]; - XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(2, 4), 0.1)); -} - -- (void)testCoordinateWithCoordinateWithOffsetOffBounds -{ - XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithCoordinate:self.defaultCoordinate pointsOffset:CGVectorMake(200, 200)]; - XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(10, 12), 0.1)); -} - -@end From fc76aeecb087429974b7b52b725173186e6f0246 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 14 May 2023 21:56:15 +0200 Subject: [PATCH 016/133] feat: Add a possibility to provide a target picker value (#699) --- .../Categories/XCUIElement+FBPickerWheel.m | 2 +- .../Commands/FBElementCommands.m | 50 +++++++++++++------ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m index 5aeed18e6..71ebaf652 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m @@ -29,7 +29,6 @@ - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)erro NSString *previousValue = snapshot.value; XCUICoordinate *startCoord = [self coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)]; XCUICoordinate *endCoord = [startCoord coordinateWithOffset:CGVectorMake(0.0, relativeHeightOffset * snapshot.frame.size.height)]; - [endCoord tap]; // If picker value is reflected in its accessiblity id // then fetching of the next snapshot may fail with StaleElementReferenceError // because we bound elements by their accessbility ids by default. @@ -37,6 +36,7 @@ - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)erro // unique element identifier (UID), so it could be found next time even if its // id is different from the initial one. See https://github.com/appium/appium/issues/17569 XCUIElement *stableInstance = self.fb_stableInstance; + [endCoord tap]; return [[[[FBRunLoopSpinner new] timeout:VALUE_CHANGE_TIMEOUT] timeoutErrorMessage:[NSString stringWithFormat:@"Picker wheel value has not been changed after %@ seconds timeout", @(VALUE_CHANGE_TIMEOUT)]] diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 6734714c6..004a66cfd 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -606,36 +606,54 @@ + (NSArray *)routes #if !TARGET_OS_TV -static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2; +static const CGFloat DEFAULT_PICKER_OFFSET = (CGFloat)0.2; +static const NSInteger DEFAULT_MAX_PICKER_ATTEMPTS = 25; + + (id)handleWheelSelect:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; if ([element.lastSnapshot elementType] != XCUIElementTypePickerWheel) { - return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:[NSString stringWithFormat:@"The element is expected to be a valid Picker Wheel control. '%@' was given instead", element.wdType] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]); + NSString *errMsg = [NSString stringWithFormat:@"The element is expected to be a valid Picker Wheel control. '%@' was given instead", element.wdType]; + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg + traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]); } NSString* order = [request.arguments[@"order"] lowercaseString]; - CGFloat offset = DEFAULT_OFFSET; + CGFloat offset = DEFAULT_PICKER_OFFSET; if (request.arguments[@"offset"]) { offset = (CGFloat)[request.arguments[@"offset"] doubleValue]; if (offset <= 0.0 || offset > 0.5) { - return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:[NSString stringWithFormat:@"'offset' value is expected to be in range (0.0, 0.5]. '%@' was given instead", request.arguments[@"offset"]] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]); + NSString *errMsg = [NSString stringWithFormat:@"'offset' value is expected to be in range (0.0, 0.5]. '%@' was given instead", request.arguments[@"offset"]]; + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg + traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]); } } - BOOL isSuccessful = false; - NSError *error; - if ([order isEqualToString:@"next"]) { - isSuccessful = [element fb_selectNextOptionWithOffset:offset error:&error]; - } else if ([order isEqualToString:@"previous"]) { - isSuccessful = [element fb_selectPreviousOptionWithOffset:offset error:&error]; - } else { - return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:[NSString stringWithFormat:@"Only 'previous' and 'next' order values are supported. '%@' was given instead", request.arguments[@"order"]] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]); - } - if (!isSuccessful) { - return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description traceback:nil]); + NSNumber *maxAttempts = request.arguments[@"maxAttempts"] ?: @(DEFAULT_MAX_PICKER_ATTEMPTS); + NSString *expectedValue = request.arguments[@"value"]; + NSInteger attempt = 0; + while (attempt < [maxAttempts integerValue]) { + BOOL isSuccessful = false; + NSError *error; + if ([order isEqualToString:@"next"]) { + isSuccessful = [element fb_selectNextOptionWithOffset:offset error:&error]; + } else if ([order isEqualToString:@"previous"]) { + isSuccessful = [element fb_selectPreviousOptionWithOffset:offset error:&error]; + } else { + NSString *errMsg = [NSString stringWithFormat:@"Only 'previous' and 'next' order values are supported. '%@' was given instead", request.arguments[@"order"]]; + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg + traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]); + } + if (!isSuccessful) { + return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description traceback:nil]); + } + if (nil == expectedValue || [element.wdValue isEqualToString:expectedValue]) { + return FBResponseWithOK(); + } + attempt++; } - return FBResponseWithOK(); + NSString *errMsg = [NSString stringWithFormat:@"Cannot select the expected picker wheel value '%@' after %ld attempts", expectedValue, attempt]; + return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:errMsg traceback:nil]); } #pragma mark - Helpers From 656f250f23c8f4b373416fafc896470472ebb61e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 14 May 2023 20:03:57 +0000 Subject: [PATCH 017/133] chore(release): 5.1.0 [skip ci] ## [5.1.0](https://github.com/appium/WebDriverAgent/compare/v5.0.0...v5.1.0) (2023-05-14) ### Features * Add a possibility to provide a target picker value ([#699](https://github.com/appium/WebDriverAgent/issues/699)) ([fc76aee](https://github.com/appium/WebDriverAgent/commit/fc76aeecb087429974b7b52b725173186e6f0246)) ### Code Refactoring * Remove obsolete coordinate calculation workarounds needed for older xCode SDKs ([#698](https://github.com/appium/WebDriverAgent/issues/698)) ([025b42c](https://github.com/appium/WebDriverAgent/commit/025b42c8a34ff0beba4379f4cb0c1d79d2b222ed)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1b7cd70d..e3edf36bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [5.1.0](https://github.com/appium/WebDriverAgent/compare/v5.0.0...v5.1.0) (2023-05-14) + + +### Features + +* Add a possibility to provide a target picker value ([#699](https://github.com/appium/WebDriverAgent/issues/699)) ([fc76aee](https://github.com/appium/WebDriverAgent/commit/fc76aeecb087429974b7b52b725173186e6f0246)) + + +### Code Refactoring + +* Remove obsolete coordinate calculation workarounds needed for older xCode SDKs ([#698](https://github.com/appium/WebDriverAgent/issues/698)) ([025b42c](https://github.com/appium/WebDriverAgent/commit/025b42c8a34ff0beba4379f4cb0c1d79d2b222ed)) + ## [5.0.0](https://github.com/appium/WebDriverAgent/compare/v4.15.1...v5.0.0) (2023-05-14) diff --git a/package.json b/package.json index 0aeff7451..6ab281f68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.0.0", + "version": "5.1.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 94e5c51bce1d4518418e999b4ac466cd46ca3bc3 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 15 May 2023 20:30:09 +0200 Subject: [PATCH 018/133] fix: Assert app is installed before launching or activating it (#704) --- WebDriverAgentLib/FBApplication.h | 10 ++++++ WebDriverAgentLib/FBApplication.m | 36 +++++++++++++++++++ .../Routing/FBExceptionHandler.m | 3 +- WebDriverAgentLib/Routing/FBExceptions.h | 3 ++ WebDriverAgentLib/Routing/FBExceptions.m | 1 + .../FBSessionIntegrationTests.m | 29 +++++++++++++++ 6 files changed, 81 insertions(+), 1 deletion(-) diff --git a/WebDriverAgentLib/FBApplication.h b/WebDriverAgentLib/FBApplication.h index 00adb527d..2aaa3d888 100644 --- a/WebDriverAgentLib/FBApplication.h +++ b/WebDriverAgentLib/FBApplication.h @@ -44,6 +44,16 @@ NS_ASSUME_NONNULL_BEGIN */ + (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error; +/** + Returns the bundle indentifier of the system app (ususally Springboard) + */ ++ (NSString *)fb_systemApplicationBundleID; + +/** + Checks if the app is installed on the device under test. + */ +- (BOOL)fb_isInstalled; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/FBApplication.m b/WebDriverAgentLib/FBApplication.m index 8a9a48ba0..095620118 100644 --- a/WebDriverAgentLib/FBApplication.m +++ b/WebDriverAgentLib/FBApplication.m @@ -9,6 +9,7 @@ #import "FBApplication.h" +#import "FBExceptions.h" #import "FBXCAccessibilityElement.h" #import "FBLogger.h" #import "FBRunLoopSpinner.h" @@ -16,6 +17,7 @@ #import "FBActiveAppDetectionPoint.h" #import "FBXCodeCompatibility.h" #import "FBXCTestDaemonsProxy.h" +#import "LSApplicationWorkspace.h" #import "XCUIApplication.h" #import "XCUIApplication+FBHelpers.h" #import "XCUIApplicationImpl.h" @@ -133,6 +135,16 @@ + (instancetype)fb_systemApplication [[FBXCAXClientProxy.sharedClient systemApplication] processIdentifier]]; } ++ (NSString *)fb_systemApplicationBundleID +{ + static dispatch_once_t onceToken; + static NSString *systemAppBundleID; + dispatch_once(&onceToken, ^{ + systemAppBundleID = [[self.class fb_systemApplication] bundleID]; + }); + return systemAppBundleID; +} + + (instancetype)applicationWithPID:(pid_t)processID { if ([NSProcessInfo processInfo].processIdentifier == processID) { @@ -141,14 +153,33 @@ + (instancetype)applicationWithPID:(pid_t)processID return (FBApplication *)[FBXCAXClientProxy.sharedClient monitoredApplicationWithProcessIdentifier:processID]; } +/** + https://github.com/appium/WebDriverAgent/issues/702 + */ +- (void)fb_assertInstalledByAction:(NSString *)action +{ + if (![self.bundleID isEqualToString:[self.class fb_systemApplicationBundleID]] && !self.fb_isInstalled) { + NSString *message = [NSString stringWithFormat:@"The application '%@' cannot be %@ because it is not installed on the device under test", + self.bundleID, action]; + [[NSException exceptionWithName:FBApplicationMissingException reason:message userInfo:nil] raise]; + } +} + - (void)launch { + [self fb_assertInstalledByAction:@"launched"]; [super launch]; if (![self fb_waitForAppElement:APP_STATE_CHANGE_TIMEOUT]) { [FBLogger logFmt:@"The application '%@' is not running in foreground after %.2f seconds", self.bundleID, APP_STATE_CHANGE_TIMEOUT]; } } +- (void)activate +{ + [self fb_assertInstalledByAction:@"activated"]; + [super activate]; +} + - (void)terminate { [super terminate]; @@ -181,4 +212,9 @@ + (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error error:error]; } +- (BOOL)fb_isInstalled +{ + return [[LSApplicationWorkspace defaultWorkspace] applicationIsInstalled:self.bundleID]; +} + @end diff --git a/WebDriverAgentLib/Routing/FBExceptionHandler.m b/WebDriverAgentLib/Routing/FBExceptionHandler.m index 203fcf0e7..7b7a8263f 100644 --- a/WebDriverAgentLib/Routing/FBExceptionHandler.m +++ b/WebDriverAgentLib/Routing/FBExceptionHandler.m @@ -24,7 +24,8 @@ - (void)handleException:(NSException *)exception forResponse:(RouteResponse *)re commandStatus = [FBCommandStatus noSuchDriverErrorWithMessage:exception.reason traceback:traceback]; } else if ([exception.name isEqualToString:FBInvalidArgumentException] - || [exception.name isEqualToString:FBElementAttributeUnknownException]) { + || [exception.name isEqualToString:FBElementAttributeUnknownException] + || [exception.name isEqualToString:FBApplicationMissingException]) { commandStatus = [FBCommandStatus invalidArgumentErrorWithMessage:exception.reason traceback:traceback]; } else if ([exception.name isEqualToString:FBApplicationCrashedException] diff --git a/WebDriverAgentLib/Routing/FBExceptions.h b/WebDriverAgentLib/Routing/FBExceptions.h index 4cbc3e5c4..1c9507a19 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.h +++ b/WebDriverAgentLib/Routing/FBExceptions.h @@ -49,4 +49,7 @@ extern NSString *const FBClassChainQueryParseException; /*! Exception used to notify about application crash */ extern NSString *const FBApplicationCrashedException; +/*! Exception used to notify about the application is not installed */ +extern NSString *const FBApplicationMissingException; + NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBExceptions.m b/WebDriverAgentLib/Routing/FBExceptions.m index 5ff6fed85..571cea4fb 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.m +++ b/WebDriverAgentLib/Routing/FBExceptions.m @@ -20,3 +20,4 @@ NSString *const FBXPathQueryEvaluationException = @"FBXPathQueryEvaluationException"; NSString *const FBClassChainQueryParseException = @"FBClassChainQueryParseException"; NSString *const FBApplicationCrashedException = @"FBApplicationCrashedException"; +NSString *const FBApplicationMissingException = @"FBApplicationMissingException"; diff --git a/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m index dc9a9b1af..655d91b85 100644 --- a/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m @@ -11,6 +11,7 @@ #import "FBIntegrationTestCase.h" #import "FBApplication.h" +#import "FBExceptions.h" #import "FBMacros.h" #import "FBSession.h" #import "FBXCodeCompatibility.h" @@ -100,6 +101,34 @@ - (void)testMainAppCanBeRestartedInScopeOfTheCurrentSession FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:testedApp.bundleID]); } +- (void)testAppWithInvalidBundleIDCannotBeStarted +{ + FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; + @try { + [testedApp launch]; + XCTFail(@"An exception is expected to be thrown"); + } @catch (NSException *exception) { + XCTAssertEqualObjects(FBApplicationMissingException, exception.name); + } +} + +- (void)testAppWithInvalidBundleIDCannotBeActivated +{ + FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; + @try { + [testedApp activate]; + XCTFail(@"An exception is expected to be thrown"); + } @catch (NSException *exception) { + XCTAssertEqualObjects(FBApplicationMissingException, exception.name); + } +} + +- (void)testAppWithInvalidBundleIDCannotBeTerminated +{ + FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; + [testedApp terminate]; +} + - (void)testLaunchUnattachedApp { [FBUnattachedAppLauncher launchAppWithBundleId:SETTINGS_BUNDLE_ID]; From ff2f5b50a5e47c435ffde423c5f09018f6f8cb22 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 15 May 2023 18:38:50 +0000 Subject: [PATCH 019/133] chore(release): 5.1.1 [skip ci] ## [5.1.1](https://github.com/appium/WebDriverAgent/compare/v5.1.0...v5.1.1) (2023-05-15) ### Bug Fixes * Assert app is installed before launching or activating it ([#704](https://github.com/appium/WebDriverAgent/issues/704)) ([94e5c51](https://github.com/appium/WebDriverAgent/commit/94e5c51bce1d4518418e999b4ac466cd46ca3bc3)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3edf36bb..570dc461b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.1.1](https://github.com/appium/WebDriverAgent/compare/v5.1.0...v5.1.1) (2023-05-15) + + +### Bug Fixes + +* Assert app is installed before launching or activating it ([#704](https://github.com/appium/WebDriverAgent/issues/704)) ([94e5c51](https://github.com/appium/WebDriverAgent/commit/94e5c51bce1d4518418e999b4ac466cd46ca3bc3)) + ## [5.1.0](https://github.com/appium/WebDriverAgent/compare/v5.0.0...v5.1.0) (2023-05-14) diff --git a/package.json b/package.json index 6ab281f68..e6b387d00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.1.0", + "version": "5.1.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 4a9faa5f85e0615c18a5f35090335bdbc7d56ebe Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 15 May 2023 14:57:40 -0700 Subject: [PATCH 020/133] chore: remove code for old os versions (#694) --- WebDriverAgentLib/Commands/FBElementCommands.m | 14 ++++++-------- WebDriverAgentLib/Utilities/FBConfiguration.m | 4 +--- .../IntegrationTests/FBAutoAlertsHandlerTests.m | 8 -------- .../IntegrationTests/FBConfigurationTests.m | 6 +----- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 004a66cfd..49c3a0231 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -696,14 +696,12 @@ + (XCUICoordinate *)gestureCoordinateWithCoordinate:(CGPoint)coordinate See issue #732: https://github.com/facebook/WebDriverAgent/issues/732 */ XCUIElement *element = application; - if (isSDKVersionGreaterThanOrEqualTo(@"11.0")) { - XCUIElement *window = application.windows.allElementsBoundByIndex.firstObject; - if (window) { - element = window; - id snapshot = element.fb_cachedSnapshot ?: element.fb_takeSnapshot; - point.x -= snapshot.frame.origin.x; - point.y -= snapshot.frame.origin.y; - } + XCUIElement *window = application.windows.allElementsBoundByIndex.firstObject; + if (window) { + element = window; + id snapshot = element.fb_cachedSnapshot ?: element.fb_takeSnapshot; + point.x -= snapshot.frame.origin.x; + point.y -= snapshot.frame.origin.y; } return [self gestureCoordinateWithCoordinate:point element:element]; } diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index 59cd5eb9b..1c80e5498 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -275,9 +275,7 @@ + (void)configureDefaultKeyboardPreferences // To dismiss keyboard tutorial on iOS 11+ (iPad) if ([controller respondsToSelector:@selector(setValue:forPreferenceKey:)]) { - if (isSDKVersionGreaterThanOrEqualTo(@"11.0")) { - [controller setValue:@YES forPreferenceKey:@"DidShowGestureKeyboardIntroduction"]; - } + [controller setValue:@YES forPreferenceKey:@"DidShowGestureKeyboardIntroduction"]; if (isSDKVersionGreaterThanOrEqualTo(@"13.0")) { [controller setValue:@YES forPreferenceKey:@"DidShowContinuousPathIntroduction"]; } diff --git a/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m b/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m index f0385c05f..5294fb50c 100644 --- a/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m @@ -49,10 +49,6 @@ - (void)tearDown // The test is flaky on slow Travis CI - (void)disabled_testAutoAcceptingOfAlerts { - if (SYSTEM_VERSION_LESS_THAN(@"11.0")) { - return; - } - self.session = [FBSession initWithApplication:FBApplication.fb_activeApplication defaultAlertAction:@"accept"]; @@ -66,10 +62,6 @@ - (void)disabled_testAutoAcceptingOfAlerts // The test is flaky on slow Travis CI - (void)disabled_testAutoDismissingOfAlerts { - if (SYSTEM_VERSION_LESS_THAN(@"11.0")) { - return; - } - self.session = [FBSession initWithApplication:FBApplication.fb_activeApplication defaultAlertAction:@"dismiss"]; diff --git a/WebDriverAgentTests/IntegrationTests/FBConfigurationTests.m b/WebDriverAgentTests/IntegrationTests/FBConfigurationTests.m index 77aaae14c..ca47cdd74 100644 --- a/WebDriverAgentTests/IntegrationTests/FBConfigurationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBConfigurationTests.m @@ -33,11 +33,7 @@ - (void)testReduceMotion XCTAssertTrue([FBConfiguration reduceMotionEnabled]); [FBConfiguration setReduceMotionEnabled:defaultReduceMotionEnabled]; - if (isSDKVersionLessThan(@"10.0")) { - XCTAssertFalse([FBConfiguration reduceMotionEnabled]); - } else { - XCTAssertEqual([FBConfiguration reduceMotionEnabled], defaultReduceMotionEnabled); - } + XCTAssertEqual([FBConfiguration reduceMotionEnabled], defaultReduceMotionEnabled); } @end From 8c0677fffca9088890bd5192cc885e82c632cc19 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 15 May 2023 22:06:01 +0000 Subject: [PATCH 021/133] chore(release): 5.1.2 [skip ci] ## [5.1.2](https://github.com/appium/WebDriverAgent/compare/v5.1.1...v5.1.2) (2023-05-15) ### Miscellaneous Chores * remove code for old os versions ([#694](https://github.com/appium/WebDriverAgent/issues/694)) ([4a9faa5](https://github.com/appium/WebDriverAgent/commit/4a9faa5f85e0615c18a5f35090335bdbc7d56ebe)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 570dc461b..af8197117 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.1.2](https://github.com/appium/WebDriverAgent/compare/v5.1.1...v5.1.2) (2023-05-15) + + +### Miscellaneous Chores + +* remove code for old os versions ([#694](https://github.com/appium/WebDriverAgent/issues/694)) ([4a9faa5](https://github.com/appium/WebDriverAgent/commit/4a9faa5f85e0615c18a5f35090335bdbc7d56ebe)) + ## [5.1.1](https://github.com/appium/WebDriverAgent/compare/v5.1.0...v5.1.1) (2023-05-15) diff --git a/package.json b/package.json index e6b387d00..64c01ae07 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.1.1", + "version": "5.1.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 00baeb2045b9aac98d27fe2e96cedce0dde5e8be Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 16 May 2023 04:18:26 -0700 Subject: [PATCH 022/133] fix: Revert "fix: Assert app is installed before launching or activating it (#704)" (#705) This reverts commit 94e5c51bce1d4518418e999b4ac466cd46ca3bc3. --- WebDriverAgentLib/FBApplication.h | 10 ------ WebDriverAgentLib/FBApplication.m | 36 ------------------- .../Routing/FBExceptionHandler.m | 3 +- WebDriverAgentLib/Routing/FBExceptions.h | 3 -- WebDriverAgentLib/Routing/FBExceptions.m | 1 - .../FBSessionIntegrationTests.m | 29 --------------- 6 files changed, 1 insertion(+), 81 deletions(-) diff --git a/WebDriverAgentLib/FBApplication.h b/WebDriverAgentLib/FBApplication.h index 2aaa3d888..00adb527d 100644 --- a/WebDriverAgentLib/FBApplication.h +++ b/WebDriverAgentLib/FBApplication.h @@ -44,16 +44,6 @@ NS_ASSUME_NONNULL_BEGIN */ + (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error; -/** - Returns the bundle indentifier of the system app (ususally Springboard) - */ -+ (NSString *)fb_systemApplicationBundleID; - -/** - Checks if the app is installed on the device under test. - */ -- (BOOL)fb_isInstalled; - @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/FBApplication.m b/WebDriverAgentLib/FBApplication.m index 095620118..8a9a48ba0 100644 --- a/WebDriverAgentLib/FBApplication.m +++ b/WebDriverAgentLib/FBApplication.m @@ -9,7 +9,6 @@ #import "FBApplication.h" -#import "FBExceptions.h" #import "FBXCAccessibilityElement.h" #import "FBLogger.h" #import "FBRunLoopSpinner.h" @@ -17,7 +16,6 @@ #import "FBActiveAppDetectionPoint.h" #import "FBXCodeCompatibility.h" #import "FBXCTestDaemonsProxy.h" -#import "LSApplicationWorkspace.h" #import "XCUIApplication.h" #import "XCUIApplication+FBHelpers.h" #import "XCUIApplicationImpl.h" @@ -135,16 +133,6 @@ + (instancetype)fb_systemApplication [[FBXCAXClientProxy.sharedClient systemApplication] processIdentifier]]; } -+ (NSString *)fb_systemApplicationBundleID -{ - static dispatch_once_t onceToken; - static NSString *systemAppBundleID; - dispatch_once(&onceToken, ^{ - systemAppBundleID = [[self.class fb_systemApplication] bundleID]; - }); - return systemAppBundleID; -} - + (instancetype)applicationWithPID:(pid_t)processID { if ([NSProcessInfo processInfo].processIdentifier == processID) { @@ -153,33 +141,14 @@ + (instancetype)applicationWithPID:(pid_t)processID return (FBApplication *)[FBXCAXClientProxy.sharedClient monitoredApplicationWithProcessIdentifier:processID]; } -/** - https://github.com/appium/WebDriverAgent/issues/702 - */ -- (void)fb_assertInstalledByAction:(NSString *)action -{ - if (![self.bundleID isEqualToString:[self.class fb_systemApplicationBundleID]] && !self.fb_isInstalled) { - NSString *message = [NSString stringWithFormat:@"The application '%@' cannot be %@ because it is not installed on the device under test", - self.bundleID, action]; - [[NSException exceptionWithName:FBApplicationMissingException reason:message userInfo:nil] raise]; - } -} - - (void)launch { - [self fb_assertInstalledByAction:@"launched"]; [super launch]; if (![self fb_waitForAppElement:APP_STATE_CHANGE_TIMEOUT]) { [FBLogger logFmt:@"The application '%@' is not running in foreground after %.2f seconds", self.bundleID, APP_STATE_CHANGE_TIMEOUT]; } } -- (void)activate -{ - [self fb_assertInstalledByAction:@"activated"]; - [super activate]; -} - - (void)terminate { [super terminate]; @@ -212,9 +181,4 @@ + (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error error:error]; } -- (BOOL)fb_isInstalled -{ - return [[LSApplicationWorkspace defaultWorkspace] applicationIsInstalled:self.bundleID]; -} - @end diff --git a/WebDriverAgentLib/Routing/FBExceptionHandler.m b/WebDriverAgentLib/Routing/FBExceptionHandler.m index 7b7a8263f..203fcf0e7 100644 --- a/WebDriverAgentLib/Routing/FBExceptionHandler.m +++ b/WebDriverAgentLib/Routing/FBExceptionHandler.m @@ -24,8 +24,7 @@ - (void)handleException:(NSException *)exception forResponse:(RouteResponse *)re commandStatus = [FBCommandStatus noSuchDriverErrorWithMessage:exception.reason traceback:traceback]; } else if ([exception.name isEqualToString:FBInvalidArgumentException] - || [exception.name isEqualToString:FBElementAttributeUnknownException] - || [exception.name isEqualToString:FBApplicationMissingException]) { + || [exception.name isEqualToString:FBElementAttributeUnknownException]) { commandStatus = [FBCommandStatus invalidArgumentErrorWithMessage:exception.reason traceback:traceback]; } else if ([exception.name isEqualToString:FBApplicationCrashedException] diff --git a/WebDriverAgentLib/Routing/FBExceptions.h b/WebDriverAgentLib/Routing/FBExceptions.h index 1c9507a19..4cbc3e5c4 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.h +++ b/WebDriverAgentLib/Routing/FBExceptions.h @@ -49,7 +49,4 @@ extern NSString *const FBClassChainQueryParseException; /*! Exception used to notify about application crash */ extern NSString *const FBApplicationCrashedException; -/*! Exception used to notify about the application is not installed */ -extern NSString *const FBApplicationMissingException; - NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBExceptions.m b/WebDriverAgentLib/Routing/FBExceptions.m index 571cea4fb..5ff6fed85 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.m +++ b/WebDriverAgentLib/Routing/FBExceptions.m @@ -20,4 +20,3 @@ NSString *const FBXPathQueryEvaluationException = @"FBXPathQueryEvaluationException"; NSString *const FBClassChainQueryParseException = @"FBClassChainQueryParseException"; NSString *const FBApplicationCrashedException = @"FBApplicationCrashedException"; -NSString *const FBApplicationMissingException = @"FBApplicationMissingException"; diff --git a/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m index 655d91b85..dc9a9b1af 100644 --- a/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m @@ -11,7 +11,6 @@ #import "FBIntegrationTestCase.h" #import "FBApplication.h" -#import "FBExceptions.h" #import "FBMacros.h" #import "FBSession.h" #import "FBXCodeCompatibility.h" @@ -101,34 +100,6 @@ - (void)testMainAppCanBeRestartedInScopeOfTheCurrentSession FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:testedApp.bundleID]); } -- (void)testAppWithInvalidBundleIDCannotBeStarted -{ - FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; - @try { - [testedApp launch]; - XCTFail(@"An exception is expected to be thrown"); - } @catch (NSException *exception) { - XCTAssertEqualObjects(FBApplicationMissingException, exception.name); - } -} - -- (void)testAppWithInvalidBundleIDCannotBeActivated -{ - FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; - @try { - [testedApp activate]; - XCTFail(@"An exception is expected to be thrown"); - } @catch (NSException *exception) { - XCTAssertEqualObjects(FBApplicationMissingException, exception.name); - } -} - -- (void)testAppWithInvalidBundleIDCannotBeTerminated -{ - FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; - [testedApp terminate]; -} - - (void)testLaunchUnattachedApp { [FBUnattachedAppLauncher launchAppWithBundleId:SETTINGS_BUNDLE_ID]; From f46e86f1049dac80059a8c8c5dfb37b82dd61688 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 16 May 2023 11:27:06 +0000 Subject: [PATCH 023/133] chore(release): 5.1.3 [skip ci] ## [5.1.3](https://github.com/appium/WebDriverAgent/compare/v5.1.2...v5.1.3) (2023-05-16) ### Bug Fixes * Revert "fix: Assert app is installed before launching or activating it ([#704](https://github.com/appium/WebDriverAgent/issues/704))" ([#705](https://github.com/appium/WebDriverAgent/issues/705)) ([00baeb2](https://github.com/appium/WebDriverAgent/commit/00baeb2045b9aac98d27fe2e96cedce0dde5e8be)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af8197117..a5d6cbd33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.1.3](https://github.com/appium/WebDriverAgent/compare/v5.1.2...v5.1.3) (2023-05-16) + + +### Bug Fixes + +* Revert "fix: Assert app is installed before launching or activating it ([#704](https://github.com/appium/WebDriverAgent/issues/704))" ([#705](https://github.com/appium/WebDriverAgent/issues/705)) ([00baeb2](https://github.com/appium/WebDriverAgent/commit/00baeb2045b9aac98d27fe2e96cedce0dde5e8be)) + ## [5.1.2](https://github.com/appium/WebDriverAgent/compare/v5.1.1...v5.1.2) (2023-05-15) diff --git a/package.json b/package.json index 64c01ae07..bf837980d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.1.2", + "version": "5.1.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From c4976e3e99afa4d471bd39c3dccfc7d9f58d8bfc Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 16 May 2023 20:45:30 +0200 Subject: [PATCH 024/133] fix: Prevent freeze on launch/activate of a missing app (#706) --- .../XCTest/XCTRunnerDaemonSession.h | 7 ++ .../Routing/FBExceptionHandler.m | 3 +- WebDriverAgentLib/Routing/FBExceptions.h | 3 + WebDriverAgentLib/Routing/FBExceptions.m | 1 + .../Utilities/FBXCTestDaemonsProxy.m | 81 +++++++++++++------ .../FBSessionIntegrationTests.m | 23 ++++++ 6 files changed, 94 insertions(+), 24 deletions(-) diff --git a/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h b/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h index 1afedbbef..7473b2e0a 100644 --- a/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h +++ b/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h @@ -80,4 +80,11 @@ @property(readonly) _Bool supportsLocationSimulation; #endif +// Since Xcode 10.2 +- (void)launchApplicationWithPath:(NSString *)arg1 + bundleID:(NSString *)arg2 + arguments:(NSArray *)arg3 + environment:(NSDictionary *)arg4 + completion:(void (^)(_Bool, NSError *))arg5; + @end diff --git a/WebDriverAgentLib/Routing/FBExceptionHandler.m b/WebDriverAgentLib/Routing/FBExceptionHandler.m index 203fcf0e7..7b7a8263f 100644 --- a/WebDriverAgentLib/Routing/FBExceptionHandler.m +++ b/WebDriverAgentLib/Routing/FBExceptionHandler.m @@ -24,7 +24,8 @@ - (void)handleException:(NSException *)exception forResponse:(RouteResponse *)re commandStatus = [FBCommandStatus noSuchDriverErrorWithMessage:exception.reason traceback:traceback]; } else if ([exception.name isEqualToString:FBInvalidArgumentException] - || [exception.name isEqualToString:FBElementAttributeUnknownException]) { + || [exception.name isEqualToString:FBElementAttributeUnknownException] + || [exception.name isEqualToString:FBApplicationMissingException]) { commandStatus = [FBCommandStatus invalidArgumentErrorWithMessage:exception.reason traceback:traceback]; } else if ([exception.name isEqualToString:FBApplicationCrashedException] diff --git a/WebDriverAgentLib/Routing/FBExceptions.h b/WebDriverAgentLib/Routing/FBExceptions.h index 4cbc3e5c4..1c9507a19 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.h +++ b/WebDriverAgentLib/Routing/FBExceptions.h @@ -49,4 +49,7 @@ extern NSString *const FBClassChainQueryParseException; /*! Exception used to notify about application crash */ extern NSString *const FBApplicationCrashedException; +/*! Exception used to notify about the application is not installed */ +extern NSString *const FBApplicationMissingException; + NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBExceptions.m b/WebDriverAgentLib/Routing/FBExceptions.m index 5ff6fed85..571cea4fb 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.m +++ b/WebDriverAgentLib/Routing/FBExceptions.m @@ -20,3 +20,4 @@ NSString *const FBXPathQueryEvaluationException = @"FBXPathQueryEvaluationException"; NSString *const FBClassChainQueryParseException = @"FBClassChainQueryParseException"; NSString *const FBApplicationCrashedException = @"FBApplicationCrashedException"; +NSString *const FBApplicationMissingException = @"FBApplicationMissingException"; diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m index 99b9d8ea9..2bee1b96c 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m @@ -13,6 +13,7 @@ #import "FBConfiguration.h" #import "FBErrorBuilder.h" +#import "FBExceptions.h" #import "FBLogger.h" #import "FBRunLoopSpinner.h" #import "XCTestDriver.h" @@ -20,23 +21,61 @@ #import "XCUIApplication.h" #import "XCUIDevice.h" -@implementation FBXCTestDaemonsProxy +#define LAUNCH_APP_TIMEOUT_SEC 300 + +static void (*originalLaunchAppMethod)(id, SEL, NSString*, NSString*, NSArray*, NSDictionary*, void (^)(_Bool, NSError *)); -static Class FBXCTRunnerDaemonSessionClass = nil; -static dispatch_once_t onceTestRunnerDaemonClass; +static void swizzledLaunchApp(id self, SEL _cmd, NSString *path, NSString *bundleID, + NSArray *arguments, NSDictionary *environment, + void (^reply)(_Bool, NSError *)) +{ + __block BOOL isSuccessful; + __block NSError *error; + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + originalLaunchAppMethod(self, _cmd, path, bundleID, arguments, environment, ^(BOOL passed, NSError *innerError) { + isSuccessful = passed; + error = innerError; + dispatch_semaphore_signal(sem); + }); + int64_t timeoutNs = (int64_t)(LAUNCH_APP_TIMEOUT_SEC * NSEC_PER_SEC); + if (0 != dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, timeoutNs))) { + NSString *message = [NSString stringWithFormat:@"The application '%@' cannot be launched within %d seconds timeout", + bundleID ?: path, LAUNCH_APP_TIMEOUT_SEC]; + @throw [NSException exceptionWithName:FBTimeoutException reason:message userInfo:nil]; + } + if (!isSuccessful || nil != error) { + [FBLogger logFmt:@"%@", error.description]; + NSString *message = error.description ?: [NSString stringWithFormat:@"The application '%@' is not installed on the device under test", + bundleID ?: path]; + @throw [NSException exceptionWithName:FBApplicationMissingException reason:message userInfo:nil]; + } + reply(isSuccessful, error); +} + +@implementation FBXCTestDaemonsProxy #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" + (void)load { - dispatch_once(&onceTestRunnerDaemonClass, ^{ - FBXCTRunnerDaemonSessionClass = objc_lookUpClass("XCTRunnerDaemonSession"); - }); + [self.class swizzleLaunchApp]; } #pragma clang diagnostic pop ++ (void)swizzleLaunchApp { + Method original = class_getInstanceMethod([XCTRunnerDaemonSession class], + @selector(launchApplicationWithPath:bundleID:arguments:environment:completion:)); + if (original == nil) { + [FBLogger log:@"Could not find method -[XCTRunnerDaemonSession launchApplicationWithPath:]"]; + return; + } + // Workaround for https://github.com/appium/WebDriverAgent/issues/702 + originalLaunchAppMethod = (void(*)(id, SEL, NSString*, NSString*, NSArray*, NSDictionary*, void (^)(_Bool, NSError *))) method_getImplementation(original); + method_setImplementation(original, (IMP)swizzledLaunchApp); +} + + (id)testRunnerProxy { static id proxy = nil; @@ -56,7 +95,7 @@ + (void)load + (id)retrieveTestRunnerProxy { - return ((XCTRunnerDaemonSession *)[FBXCTRunnerDaemonSessionClass sharedSession]).daemonProxy; + return ((XCTRunnerDaemonSession *)[XCTRunnerDaemonSession sharedSession]).daemonProxy; } + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSError *__autoreleasing*)error @@ -70,24 +109,20 @@ + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSEr didSucceed = (invokeError == nil); completion(); }; - - if (nil == FBXCTRunnerDaemonSessionClass) { - [[self testRunnerProxy] _XCT_synthesizeEvent:record completion:errorHandler]; - } else { - XCEventGeneratorHandler handlerBlock = ^(XCSynthesizedEventRecord *innerRecord, NSError *invokeError) { - errorHandler(invokeError); - }; - [[XCUIDevice.sharedDevice eventSynthesizer] synthesizeEvent:record completion:(id)^(BOOL result, NSError *invokeError) { - handlerBlock(record, invokeError); - }]; - } + + XCEventGeneratorHandler handlerBlock = ^(XCSynthesizedEventRecord *innerRecord, NSError *invokeError) { + errorHandler(invokeError); + }; + [[XCUIDevice.sharedDevice eventSynthesizer] synthesizeEvent:record completion:(id)^(BOOL result, NSError *invokeError) { + handlerBlock(record, invokeError); + }]; }]; return didSucceed; } + (BOOL)openURL:(NSURL *)url usingApplication:(NSString *)bundleId error:(NSError *__autoreleasing*)error { - XCTRunnerDaemonSession *session = [FBXCTRunnerDaemonSessionClass sharedSession]; + XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(openURL:usingApplication:completion:)]) { if (error) { [[[FBErrorBuilder builder] @@ -112,7 +147,7 @@ + (BOOL)openURL:(NSURL *)url usingApplication:(NSString *)bundleId error:(NSErro + (BOOL)openDefaultApplicationForURL:(NSURL *)url error:(NSError *__autoreleasing*)error { - XCTRunnerDaemonSession *session = [FBXCTRunnerDaemonSessionClass sharedSession]; + XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(openDefaultApplicationForURL:completion:)]) { if (error) { [[[FBErrorBuilder builder] @@ -138,7 +173,7 @@ + (BOOL)openDefaultApplicationForURL:(NSURL *)url error:(NSError *__autoreleasin #if !TARGET_OS_TV + (BOOL)setSimulatedLocation:(CLLocation *)location error:(NSError *__autoreleasing*)error { - XCTRunnerDaemonSession *session = [FBXCTRunnerDaemonSessionClass sharedSession]; + XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(setSimulatedLocation:completion:)]) { if (error) { [[[FBErrorBuilder builder] @@ -171,7 +206,7 @@ + (BOOL)setSimulatedLocation:(CLLocation *)location error:(NSError *__autoreleas + (nullable CLLocation *)getSimulatedLocation:(NSError *__autoreleasing*)error; { - XCTRunnerDaemonSession *session = [FBXCTRunnerDaemonSessionClass sharedSession]; + XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(getSimulatedLocationWithReply:)]) { if (error) { [[[FBErrorBuilder builder] @@ -206,7 +241,7 @@ + (nullable CLLocation *)getSimulatedLocation:(NSError *__autoreleasing*)error; + (BOOL)clearSimulatedLocation:(NSError *__autoreleasing*)error { - XCTRunnerDaemonSession *session = [FBXCTRunnerDaemonSessionClass sharedSession]; + XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(clearSimulatedLocationWithReply:)]) { if (error) { [[[FBErrorBuilder builder] diff --git a/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m index dc9a9b1af..ea9fb4cfe 100644 --- a/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m @@ -11,6 +11,7 @@ #import "FBIntegrationTestCase.h" #import "FBApplication.h" +#import "FBExceptions.h" #import "FBMacros.h" #import "FBSession.h" #import "FBXCodeCompatibility.h" @@ -107,4 +108,26 @@ - (void)testLaunchUnattachedApp XCTAssertEqualObjects(SETTINGS_BUNDLE_ID, FBApplication.fb_activeApplication.bundleID); } +- (void)testAppWithInvalidBundleIDCannotBeStarted +{ + FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; + @try { + [testedApp launch]; + XCTFail(@"An exception is expected to be thrown"); + } @catch (NSException *exception) { + XCTAssertEqualObjects(FBApplicationMissingException, exception.name); + } +} + +- (void)testAppWithInvalidBundleIDCannotBeActivated +{ + FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; + @try { + [testedApp activate]; + XCTFail(@"An exception is expected to be thrown"); + } @catch (NSException *exception) { + XCTAssertEqualObjects(FBApplicationMissingException, exception.name); + } +} + @end From 0bd9ae2e57e34bebbf9db6df30ff672f50c99485 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 16 May 2023 18:58:43 +0000 Subject: [PATCH 025/133] chore(release): 5.1.4 [skip ci] ## [5.1.4](https://github.com/appium/WebDriverAgent/compare/v5.1.3...v5.1.4) (2023-05-16) ### Bug Fixes * Prevent freeze on launch/activate of a missing app ([#706](https://github.com/appium/WebDriverAgent/issues/706)) ([c4976e3](https://github.com/appium/WebDriverAgent/commit/c4976e3e99afa4d471bd39c3dccfc7d9f58d8bfc)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5d6cbd33..bf2c328b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.1.4](https://github.com/appium/WebDriverAgent/compare/v5.1.3...v5.1.4) (2023-05-16) + + +### Bug Fixes + +* Prevent freeze on launch/activate of a missing app ([#706](https://github.com/appium/WebDriverAgent/issues/706)) ([c4976e3](https://github.com/appium/WebDriverAgent/commit/c4976e3e99afa4d471bd39c3dccfc7d9f58d8bfc)) + ## [5.1.3](https://github.com/appium/WebDriverAgent/compare/v5.1.2...v5.1.3) (2023-05-16) diff --git a/package.json b/package.json index bf837980d..90c318a34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.1.3", + "version": "5.1.4", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 259f7319305b15a3f541957d3ccaa3cb12c9e1a3 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 18 May 2023 09:25:41 +0200 Subject: [PATCH 026/133] chore: Drop obsolete workarounds for coordinates calculation (#701) --- WebDriverAgent.xcodeproj/project.pbxproj | 12 -- .../Categories/XCUIApplication+FBHelpers.m | 4 +- .../Categories/XCUIElement+FBForceTouch.m | 8 +- .../Categories/XCUIElement+FBTap.h | 35 ----- .../Categories/XCUIElement+FBTap.m | 32 ----- .../Categories/XCUIElement+FBTyping.m | 3 +- .../Commands/FBElementCommands.m | 135 ++++++------------ WebDriverAgentLib/FBAlert.m | 24 ++-- WebDriverAgentLib/WebDriverAgentLib.h | 1 - .../IntegrationTests/FBAlertTests.m | 5 +- .../FBAutoAlertsHandlerTests.m | 4 +- .../FBElementAttributeTests.m | 2 +- .../IntegrationTests/FBTapTest.m | 17 +-- 13 files changed, 77 insertions(+), 205 deletions(-) delete mode 100644 WebDriverAgentLib/Categories/XCUIElement+FBTap.h delete mode 100644 WebDriverAgentLib/Categories/XCUIElement+FBTap.m diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index b719df35b..eafb306ad 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -112,7 +112,6 @@ 641EE6222240C5CA00173FCB /* FBApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7671CAEDF0C008C271F /* FBApplication.m */; }; 641EE6232240C5CA00173FCB /* FBScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 715AFAC01FFA29180053896D /* FBScreen.m */; }; 641EE6242240C5CA00173FCB /* FBXCTestDaemonsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = EE35AD7A1E3B80C000A02D78 /* FBXCTestDaemonsProxy.m */; }; - 641EE6252240C5CA00173FCB /* XCUIElement+FBTap.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB74C1CAEDF0C008C271F /* XCUIElement+FBTap.m */; }; 641EE6262240C5CA00173FCB /* FBMathUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = EE1888391DA661C400307AA8 /* FBMathUtils.m */; }; 641EE6272240C5CA00173FCB /* FBXCAXClientProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7157B290221DADD2001C348C /* FBXCAXClientProxy.m */; }; 641EE6312240C5CA00173FCB /* XCUIElement+FBWebDriverAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = EEE376471D59FAE900ED88DD /* XCUIElement+FBWebDriverAttributes.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -161,7 +160,6 @@ 641EE65D2240C5CA00173FCB /* XCTRunnerAutomationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACEE1E3B77D600A02D78 /* XCTRunnerAutomationSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE65F2240C5CA00173FCB /* XCSourceCodeTreeNodeEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACC61E3B77D600A02D78 /* XCSourceCodeTreeNodeEnumerator.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6602240C5CA00173FCB /* XCUIElement+FBIsVisible.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7471CAEDF0C008C271F /* XCUIElement+FBIsVisible.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 641EE6612240C5CA00173FCB /* XCUIElement+FBTap.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB74B1CAEDF0C008C271F /* XCUIElement+FBTap.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6622240C5CA00173FCB /* FBResponsePayload.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7821CAEDF0C008C271F /* FBResponsePayload.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6632240C5CA00173FCB /* FBUnknownCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7641CAEDF0C008C271F /* FBUnknownCommands.h */; }; 641EE6642240C5CA00173FCB /* NSPredicate+FBFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A224E31DE2F56600844D55 /* NSPredicate+FBFormat.h */; }; @@ -571,8 +569,6 @@ EE158AB11CBD456F00A3E3F0 /* XCUIElement+FBIsVisible.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7481CAEDF0C008C271F /* XCUIElement+FBIsVisible.m */; }; EE158AB21CBD456F00A3E3F0 /* XCUIElement+FBScrolling.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7491CAEDF0C008C271F /* XCUIElement+FBScrolling.h */; settings = {ATTRIBUTES = (Public, ); }; }; EE158AB31CBD456F00A3E3F0 /* XCUIElement+FBScrolling.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB74A1CAEDF0C008C271F /* XCUIElement+FBScrolling.m */; }; - EE158AB41CBD456F00A3E3F0 /* XCUIElement+FBTap.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB74B1CAEDF0C008C271F /* XCUIElement+FBTap.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE158AB51CBD456F00A3E3F0 /* XCUIElement+FBTap.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB74C1CAEDF0C008C271F /* XCUIElement+FBTap.m */; }; EE158AB81CBD456F00A3E3F0 /* FBAlertViewCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7501CAEDF0C008C271F /* FBAlertViewCommands.h */; }; EE158AB91CBD456F00A3E3F0 /* FBAlertViewCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7511CAEDF0C008C271F /* FBAlertViewCommands.m */; }; EE158ABA1CBD456F00A3E3F0 /* FBCustomCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7521CAEDF0C008C271F /* FBCustomCommands.h */; }; @@ -1272,8 +1268,6 @@ EE9AB7481CAEDF0C008C271F /* XCUIElement+FBIsVisible.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBIsVisible.m"; sourceTree = ""; }; EE9AB7491CAEDF0C008C271F /* XCUIElement+FBScrolling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBScrolling.h"; sourceTree = ""; }; EE9AB74A1CAEDF0C008C271F /* XCUIElement+FBScrolling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBScrolling.m"; sourceTree = ""; }; - EE9AB74B1CAEDF0C008C271F /* XCUIElement+FBTap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBTap.h"; sourceTree = ""; }; - EE9AB74C1CAEDF0C008C271F /* XCUIElement+FBTap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBTap.m"; sourceTree = ""; }; EE9AB7501CAEDF0C008C271F /* FBAlertViewCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBAlertViewCommands.h; sourceTree = ""; }; EE9AB7511CAEDF0C008C271F /* FBAlertViewCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBAlertViewCommands.m; sourceTree = ""; }; EE9AB7521CAEDF0C008C271F /* FBCustomCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBCustomCommands.h; sourceTree = ""; }; @@ -1757,8 +1751,6 @@ EE9AB74A1CAEDF0C008C271F /* XCUIElement+FBScrolling.m */, 71F5BE21252E576C00EE9EBA /* XCUIElement+FBSwiping.h */, 71F5BE22252E576C00EE9EBA /* XCUIElement+FBSwiping.m */, - EE9AB74B1CAEDF0C008C271F /* XCUIElement+FBTap.h */, - EE9AB74C1CAEDF0C008C271F /* XCUIElement+FBTap.m */, AD76723B1D6B7CC000610457 /* XCUIElement+FBTyping.h */, AD76723C1D6B7CC000610457 /* XCUIElement+FBTyping.m */, 71B49EC51ED1A58100D51AD6 /* XCUIElement+FBUID.h */, @@ -2299,7 +2291,6 @@ 641EE65D2240C5CA00173FCB /* XCTRunnerAutomationSession.h in Headers */, 641EE65F2240C5CA00173FCB /* XCSourceCodeTreeNodeEnumerator.h in Headers */, 641EE6602240C5CA00173FCB /* XCUIElement+FBIsVisible.h in Headers */, - 641EE6612240C5CA00173FCB /* XCUIElement+FBTap.h in Headers */, 641EE6622240C5CA00173FCB /* FBResponsePayload.h in Headers */, 641EE6632240C5CA00173FCB /* FBUnknownCommands.h in Headers */, 641EE7062240CDCF00173FCB /* XCUIElement+FBTVFocuse.h in Headers */, @@ -2536,7 +2527,6 @@ EE35AD371E3B77D600A02D78 /* XCSourceCodeTreeNodeEnumerator.h in Headers */, EE158AB01CBD456F00A3E3F0 /* XCUIElement+FBIsVisible.h in Headers */, 71414ED42670A1EE003A8C5D /* LRUCache.h in Headers */, - EE158AB41CBD456F00A3E3F0 /* XCUIElement+FBTap.h in Headers */, EE158ADC1CBD456F00A3E3F0 /* FBResponsePayload.h in Headers */, 13815F6F2328D20400CDAB61 /* FBActiveAppDetectionPoint.h in Headers */, EE158ACC1CBD456F00A3E3F0 /* FBUnknownCommands.h in Headers */, @@ -3159,7 +3149,6 @@ 641EE6232240C5CA00173FCB /* FBScreen.m in Sources */, 71D04DCB25356C43008A052C /* XCUIElement+FBCaching.m in Sources */, 641EE6242240C5CA00173FCB /* FBXCTestDaemonsProxy.m in Sources */, - 641EE6252240C5CA00173FCB /* XCUIElement+FBTap.m in Sources */, 13DE7A58287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m in Sources */, 641EE6262240C5CA00173FCB /* FBMathUtils.m in Sources */, 641EE6272240C5CA00173FCB /* FBXCAXClientProxy.m in Sources */, @@ -3292,7 +3281,6 @@ 715AFAC21FFA29180053896D /* FBScreen.m in Sources */, 71B155DC230711E900646AFB /* FBCommandStatus.m in Sources */, EE35AD7C1E3B80C000A02D78 /* FBXCTestDaemonsProxy.m in Sources */, - EE158AB51CBD456F00A3E3F0 /* XCUIElement+FBTap.m in Sources */, EE18883B1DA661C400307AA8 /* FBMathUtils.m in Sources */, 7157B292221DADD2001C348C /* FBXCAXClientProxy.m in Sources */, ); diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 086643296..ec752c5a0 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -256,7 +256,7 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames continue; } - [matchedKey fb_tapWithError:nil]; + [matchedKey tap]; if (isKeyboardInvisible()) { return YES; } @@ -269,7 +269,7 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames @[@(XCUIElementTypeKey), @(XCUIElementTypeButton)]]; NSArray *matchedKeys = findMatchingKeys(searchPredicate); if (matchedKeys.count > 0) { - [matchedKeys[matchedKeys.count - 1] fb_tapWithError:nil]; + [matchedKeys[matchedKeys.count - 1] tap]; } } #endif diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m b/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m index e7629c6bc..1c7a9ce0e 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m @@ -35,10 +35,10 @@ - (BOOL)fb_forceTouchCoordinate:(NSValue *)relativeCoordinate [self pressWithPressure:[pressure doubleValue] duration:[duration doubleValue]]; } } else { - CGSize size = self.frame.size; - CGVector offset = CGVectorMake(size.width > 0 ? relativeCoordinate.CGPointValue.x / size.width : 0, - size.height > 0 ? relativeCoordinate.CGPointValue.y / size.height : 0); - XCUICoordinate *hitPoint = [self coordinateWithNormalizedOffset:offset]; + CGVector offset = CGVectorMake(relativeCoordinate.CGPointValue.x, + relativeCoordinate.CGPointValue.y); + XCUICoordinate *hitPoint = [[self coordinateWithNormalizedOffset:CGVectorMake(0, 0)] + coordinateWithOffset:offset]; if (nil == pressure || nil == duration) { [hitPoint forcePress]; } else { diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTap.h b/WebDriverAgentLib/Categories/XCUIElement+FBTap.h deleted file mode 100644 index ed92bb6d7..000000000 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTap.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface XCUIElement (FBTap) - -/** - Waits for element to become stable (not move) and performs sync tap on element - - @param error If there is an error, upon return contains an NSError object that describes the problem. - @return YES if the operation succeeds, otherwise NO. -*/ -- (BOOL)fb_tapWithError:(NSError **)error; - -/** - Waits for element to become stable (not move) and performs sync tap on element - - @param relativeCoordinate hit point coordinate relative to the current element position - @param error If there is an error, upon return contains an NSError object that describes the problem. - @return YES if the operation succeeds, otherwise NO. - */ -- (BOOL)fb_tapCoordinate:(CGPoint)relativeCoordinate error:(NSError **)error; - -@end - -NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTap.m b/WebDriverAgentLib/Categories/XCUIElement+FBTap.m deleted file mode 100644 index c3c4346ae..000000000 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTap.m +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "XCUIElement+FBTap.h" - - -#if !TARGET_OS_TV -@implementation XCUIElement (FBTap) - -- (BOOL)fb_tapWithError:(NSError **)error -{ - [self tap]; - return YES; -} - -- (BOOL)fb_tapCoordinate:(CGPoint)relativeCoordinate error:(NSError **)error -{ - XCUICoordinate *startCoordinate = [self coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; - CGVector offset = CGVectorMake(relativeCoordinate.x, relativeCoordinate.y); - XCUICoordinate *dstCoordinate = [startCoordinate coordinateWithOffset:offset]; - [dstCoordinate tap]; - return YES; -} - -@end -#endif diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m index aabc6e8bf..a538be380 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m @@ -16,7 +16,6 @@ #import "FBXCElementSnapshotWrapper.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "XCUIElement+FBCaching.h" -#import "XCUIElement+FBTap.h" #import "XCUIElement+FBUtilities.h" #import "FBXCodeCompatibility.h" @@ -72,7 +71,7 @@ - (void)fb_prepareForTextInputWithSnapshot:(FBXCElementSnapshotWrapper *)snapsho // There is no possibility to open the keyboard by tapping a field in TvOS #if !TARGET_OS_TV [FBLogger logFmt:@"Trying to tap the \"%@\" element to have it focused", snapshot.fb_description]; - [self fb_tapWithError:nil]; + [self tap]; // It might take some time to update the UI [self fb_takeSnapshot]; #endif diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 49c3a0231..adb5f6092 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -30,7 +30,6 @@ #import "XCUIElement+FBIsVisible.h" #import "XCUIElement+FBPickerWheel.h" #import "XCUIElement+FBScrolling.h" -#import "XCUIElement+FBTap.h" #import "XCUIElement+FBForceTouch.h" #import "XCUIElement+FBSwiping.h" #import "XCUIElement+FBTyping.h" @@ -233,14 +232,14 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - NSError *error = nil; #if TARGET_OS_IOS - if (![element fb_tapWithError:&error]) { + [element tap]; #elif TARGET_OS_TV + NSError *error = nil; if (![element fb_selectWithError:&error]) { -#endif return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description traceback:nil]); } +#endif return FBResponseWithOK(); } @@ -296,9 +295,10 @@ + (NSArray *)routes + (id)handleDoubleTapCoordinate:(FBRouteRequest *)request { - CGPoint doubleTapPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]); - XCUICoordinate *doubleTapCoordinate = [self.class gestureCoordinateWithCoordinate:doubleTapPoint - application:request.session.activeApplication]; + CGVector offset = CGVectorMake([request.arguments[@"x"] doubleValue], + [request.arguments[@"y"] doubleValue]); + XCUICoordinate *doubleTapCoordinate = [self.class gestureCoordinateWithOffset:offset + element:request.session.activeApplication]; [doubleTapCoordinate doubleTap]; return FBResponseWithOK(); } @@ -334,9 +334,10 @@ + (NSArray *)routes + (id)handleTouchAndHoldCoordinate:(FBRouteRequest *)request { - CGPoint touchPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]); - XCUICoordinate *pressCoordinate = [self.class gestureCoordinateWithCoordinate:touchPoint - application:request.session.activeApplication]; + CGVector offset = CGVectorMake([request.arguments[@"x"] doubleValue], + [request.arguments[@"y"] doubleValue]); + XCUICoordinate *pressCoordinate = [self.class gestureCoordinateWithOffset:offset + element:request.session.activeApplication]; [pressCoordinate pressForDuration:[request.arguments[@"duration"] doubleValue]]; return FBResponseWithOK(); } @@ -359,18 +360,18 @@ + (NSArray *)routes + (id)handlePressAndDragCoordinateWithVelocity:(FBRouteRequest *)request { FBSession *session = request.session; - CGPoint startPoint = CGPointMake((CGFloat)[request.arguments[@"fromX"] doubleValue], - (CGFloat)[request.arguments[@"fromY"] doubleValue]); - CGPoint endPoint = CGPointMake((CGFloat)[request.arguments[@"toX"] doubleValue], - (CGFloat)[request.arguments[@"toY"] doubleValue]); - XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithCoordinate:endPoint - application:session.activeApplication]; - XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithCoordinate:startPoint - application:session.activeApplication]; + CGVector startOffset = CGVectorMake((CGFloat)[request.arguments[@"fromX"] doubleValue], + (CGFloat)[request.arguments[@"fromY"] doubleValue]); + XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset + element:session.activeApplication]; if (![startCoordinate respondsToSelector:@selector(pressForDuration:thenDragToCoordinate:withVelocity:thenHoldForDuration:)]) { return FBResponseWithStatus([FBCommandStatus unsupportedOperationErrorWithMessage:@"This method is only supported in Xcode 12 and above" traceback:nil]); } + CGVector endOffset = CGVectorMake((CGFloat)[request.arguments[@"toX"] doubleValue], + (CGFloat)[request.arguments[@"toY"] doubleValue]); + XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithOffset:endOffset + element:session.activeApplication]; [startCoordinate pressForDuration:[request.arguments[@"pressDuration"] doubleValue] thenDragToCoordinate:endCoordinate withVelocity:[request.arguments[@"velocity"] doubleValue] @@ -444,13 +445,15 @@ + (NSArray *)routes + (id)handleDragCoordinate:(FBRouteRequest *)request { FBSession *session = request.session; - CGPoint startPoint = CGPointMake((CGFloat)[request.arguments[@"fromX"] doubleValue], (CGFloat)[request.arguments[@"fromY"] doubleValue]); - CGPoint endPoint = CGPointMake((CGFloat)[request.arguments[@"toX"] doubleValue], (CGFloat)[request.arguments[@"toY"] doubleValue]); + CGVector startOffset = CGVectorMake([request.arguments[@"fromX"] doubleValue], + [request.arguments[@"fromY"] doubleValue]); + XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset + element:session.activeApplication]; + CGVector endOffset = CGVectorMake([request.arguments[@"toX"] doubleValue], + [request.arguments[@"toY"] doubleValue]); + XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithOffset:endOffset + element:session.activeApplication]; NSTimeInterval duration = [request.arguments[@"duration"] doubleValue]; - XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithCoordinate:endPoint - application:session.activeApplication]; - XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithCoordinate:startPoint - application:session.activeApplication]; [startCoordinate pressForDuration:duration thenDragToCoordinate:endCoordinate]; return FBResponseWithOK(); } @@ -460,14 +463,13 @@ + (NSArray *)routes FBSession *session = request.session; FBElementCache *elementCache = session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - CGRect frame = [(id)element.lastSnapshot frame]; - CGPoint startPoint = CGPointMake((CGFloat)(frame.origin.x + [request.arguments[@"fromX"] doubleValue]), (CGFloat)(frame.origin.y + [request.arguments[@"fromY"] doubleValue])); - CGPoint endPoint = CGPointMake((CGFloat)(frame.origin.x + [request.arguments[@"toX"] doubleValue]), (CGFloat)(frame.origin.y + [request.arguments[@"toY"] doubleValue])); + CGVector startOffset = CGVectorMake([request.arguments[@"fromX"] doubleValue], + [request.arguments[@"fromY"] doubleValue]); + XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset element:element]; + CGVector endOffset = CGVectorMake([request.arguments[@"toX"] doubleValue], + [request.arguments[@"toY"] doubleValue]); + XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithOffset:endOffset element:element]; NSTimeInterval duration = [request.arguments[@"duration"] doubleValue]; - XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithCoordinate:endPoint - application:session.activeApplication]; - XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithCoordinate:startPoint - application:session.activeApplication]; [startCoordinate pressForDuration:duration thenDragToCoordinate:endCoordinate]; return FBResponseWithOK(); } @@ -493,19 +495,13 @@ + (NSArray *)routes + (id)handleTap:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - CGPoint tapPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]); - if ([elementCache hasElementWithUUID:request.parameters[@"uuid"]]) { - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - NSError *error; - if (![element fb_tapCoordinate:tapPoint error:&error]) { - return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description - traceback:nil]); - } - } else { - XCUICoordinate *tapCoordinate = [self.class gestureCoordinateWithCoordinate:tapPoint - application:request.session.activeApplication]; - [tapCoordinate tap]; - } + CGVector offset = CGVectorMake([request.arguments[@"x"] doubleValue], + [request.arguments[@"y"] doubleValue]); + XCUIElement *element = [elementCache hasElementWithUUID:request.parameters[@"uuid"]] + ? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]] + : request.session.activeApplication; + XCUICoordinate *tapCoordinate = [self.class gestureCoordinateWithOffset:offset element:element]; + [tapCoordinate tap]; return FBResponseWithOK(); } @@ -672,55 +668,18 @@ + (NSArray *)routes } /** - Returns gesture coordinate for the application based on absolute coordinate + Returns gesture coordinate for the element based on absolute coordinate - @param coordinate absolute screen coordinates - @param application the instance of current application under test + @param offset absolute screen offset for the given application + @param element the element instance to perform the gesture on @return translated gesture coordinates ready to be passed to XCUICoordinate methods */ -+ (XCUICoordinate *)gestureCoordinateWithCoordinate:(CGPoint)coordinate - application:(XCUIApplication *)application -{ - CGPoint point = coordinate; - /** - If SDK >= 11, the tap coordinate based on application is not correct when - the application orientation is landscape and - tapX > application portrait width or tapY > application portrait height. - Pass the window element to the method [FBElementCommands gestureCoordinateWithCoordinate:element:] - will resolve the problem. - More details about the bug, please see the following issues: - #705: https://github.com/facebook/WebDriverAgent/issues/705 - #798: https://github.com/facebook/WebDriverAgent/issues/798 - #856: https://github.com/facebook/WebDriverAgent/issues/856 - Notice: On iOS 10, if the application is not launched by wda, no elements will be found. - See issue #732: https://github.com/facebook/WebDriverAgent/issues/732 - */ - XCUIElement *element = application; - XCUIElement *window = application.windows.allElementsBoundByIndex.firstObject; - if (window) { - element = window; - id snapshot = element.fb_cachedSnapshot ?: element.fb_takeSnapshot; - point.x -= snapshot.frame.origin.x; - point.y -= snapshot.frame.origin.y; - } - return [self gestureCoordinateWithCoordinate:point element:element]; -} - -/** - Returns gesture coordinate based on the specified element. - - @param coordinate absolute coordinates based on the element - @param element the element in the current application under test - @return translated gesture coordinates ready to be passed to XCUICoordinate methods - */ -+ (XCUICoordinate *)gestureCoordinateWithCoordinate:(CGPoint)coordinate - element:(XCUIElement *)element ++ (XCUICoordinate *)gestureCoordinateWithOffset:(CGVector)offset + element:(XCUIElement *)element { - XCUICoordinate *appCoordinate = [[XCUICoordinate alloc] initWithElement:element - normalizedOffset:CGVectorMake(0, 0)]; - return [[XCUICoordinate alloc] initWithCoordinate:appCoordinate - pointsOffset:CGVectorMake(coordinate.x, coordinate.y)]; + return [[element coordinateWithNormalizedOffset:CGVectorMake(0, 0)] coordinateWithOffset:offset]; } + #endif @end diff --git a/WebDriverAgentLib/FBAlert.m b/WebDriverAgentLib/FBAlert.m index 705ab3ccc..d692b04b2 100644 --- a/WebDriverAgentLib/FBAlert.m +++ b/WebDriverAgentLib/FBAlert.m @@ -17,7 +17,6 @@ #import "FBXCodeCompatibility.h" #import "XCUIApplication+FBAlert.h" #import "XCUIElement+FBClassChain.h" -#import "XCUIElement+FBTap.h" #import "XCUIElement+FBTyping.h" #import "XCUIElement+FBUtilities.h" #import "XCUIElement+FBWebDriverAttributes.h" @@ -190,11 +189,13 @@ - (BOOL)acceptWithError:(NSError **)error ? buttons.lastObject : buttons.firstObject; } - return nil == acceptButton - ? [[[FBErrorBuilder builder] + if (nil == acceptButton) { + return [[[FBErrorBuilder builder] withDescriptionFormat:@"Failed to find accept button for alert: %@", self.alertElement] - buildError:error] - : [acceptButton fb_tapWithError:error]; + buildError:error]; + } + [acceptButton tap]; + return YES; } - (BOOL)dismissWithError:(NSError **)error @@ -230,11 +231,13 @@ - (BOOL)dismissWithError:(NSError **)error : buttons.lastObject; } - return nil == dismissButton - ? [[[FBErrorBuilder builder] + if (nil == dismissButton) { + return [[[FBErrorBuilder builder] withDescriptionFormat:@"Failed to find dismiss button for alert: %@", self.alertElement] - buildError:error] - : [dismissButton fb_tapWithError:error]; + buildError:error]; + } + [dismissButton tap]; + return YES; } - (BOOL)clickAlertButton:(NSString *)label error:(NSError **)error @@ -251,7 +254,8 @@ - (BOOL)clickAlertButton:(NSString *)label error:(NSError **)error withDescriptionFormat:@"Failed to find button with label '%@' for alert: %@", label, self.alertElement] buildError:error]; } - return [requestedButton fb_tapWithError:error]; + [requestedButton tap]; + return YES; } - (XCUIElement *)alertElement diff --git a/WebDriverAgentLib/WebDriverAgentLib.h b/WebDriverAgentLib/WebDriverAgentLib.h index b8f85e98f..6d9daa1f6 100644 --- a/WebDriverAgentLib/WebDriverAgentLib.h +++ b/WebDriverAgentLib/WebDriverAgentLib.h @@ -46,7 +46,6 @@ FOUNDATION_EXPORT const unsigned char WebDriverAgentLib_VersionString[]; #import #import #import -#import #import #import #import diff --git a/WebDriverAgentTests/IntegrationTests/FBAlertTests.m b/WebDriverAgentTests/IntegrationTests/FBAlertTests.m index e94c4109e..57c48e492 100644 --- a/WebDriverAgentTests/IntegrationTests/FBAlertTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBAlertTests.m @@ -15,7 +15,6 @@ #import "FBIntegrationTestCase.h" #import "FBTestMacros.h" #import "FBMacros.h" -#import "XCUIElement+FBTap.h" @interface FBAlertTests : FBIntegrationTestCase @end @@ -42,13 +41,13 @@ - (void)tearDown - (void)showApplicationAlert { - [self.testedApplication.buttons[FBShowAlertButtonName] fb_tapWithError:nil]; + [self.testedApplication.buttons[FBShowAlertButtonName] tap]; FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count != 0); } - (void)showApplicationSheet { - [self.testedApplication.buttons[FBShowSheetAlertButtonName] fb_tapWithError:nil]; + [self.testedApplication.buttons[FBShowSheetAlertButtonName] tap]; FBAssertWaitTillBecomesTrue(self.testedApplication.sheets.count != 0); } diff --git a/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m b/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m index 5294fb50c..25dc39d21 100644 --- a/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m @@ -53,7 +53,7 @@ - (void)disabled_testAutoAcceptingOfAlerts initWithApplication:FBApplication.fb_activeApplication defaultAlertAction:@"accept"]; for (int i = 0; i < 2; i++) { - [self.testedApplication.buttons[FBShowAlertButtonName] fb_tapWithError:nil]; + [self.testedApplication.buttons[FBShowAlertButtonName] tap]; [self.testedApplication fb_waitUntilStable]; FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0); } @@ -66,7 +66,7 @@ - (void)disabled_testAutoDismissingOfAlerts initWithApplication:FBApplication.fb_activeApplication defaultAlertAction:@"dismiss"]; for (int i = 0; i < 2; i++) { - [self.testedApplication.buttons[FBShowAlertButtonName] fb_tapWithError:nil]; + [self.testedApplication.buttons[FBShowAlertButtonName] tap]; [self.testedApplication fb_waitUntilStable]; FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count == 0); } diff --git a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m index bc0966f91..c7cc3505e 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m @@ -160,7 +160,7 @@ - (void)testSwitchAttributes XCTAssertNil(element.wdLabel); XCTAssertEqualObjects(element.wdValue, @"1"); XCTAssertFalse(element.wdSelected); - XCTAssertTrue([element fb_tapWithError:nil]); + [element tap]; XCTAssertEqualObjects(element.wdValue, @"0"); XCTAssertFalse(element.wdSelected); } diff --git a/WebDriverAgentTests/IntegrationTests/FBTapTest.m b/WebDriverAgentTests/IntegrationTests/FBTapTest.m index 30b5f0f9e..9dce4084c 100644 --- a/WebDriverAgentTests/IntegrationTests/FBTapTest.m +++ b/WebDriverAgentTests/IntegrationTests/FBTapTest.m @@ -15,7 +15,6 @@ #import "FBElementCache.h" #import "FBTestMacros.h" #import "XCUIDevice+FBRotation.h" -#import "XCUIElement+FBTap.h" #import "XCUIElement+FBIsVisible.h" @interface FBTapTest : FBIntegrationTestCase @@ -28,8 +27,7 @@ @implementation FBTapTest - (void)verifyTapWithOrientation:(UIDeviceOrientation)orientation { [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation]; - NSError *error; - [self.testedApplication.buttons[FBShowAlertButtonName] fb_tapWithError:&error]; + [self.testedApplication.buttons[FBShowAlertButtonName] tap]; FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0); } @@ -66,10 +64,7 @@ - (void)testTapInLandscapeRight [self verifyTapWithOrientation:UIDeviceOrientationLandscapeRight]; } -// Visibility detection for upside-down orientation is broken -// and cannot be workarounded properly, but this is not very important for Appium, since -// We don't support such orientation anyway -- (void)disabled_testTapInPortraitUpsideDown +- (void)testTapInPortraitUpsideDown { [self verifyTapWithOrientation:UIDeviceOrientationPortraitUpsideDown]; } @@ -77,9 +72,8 @@ - (void)disabled_testTapInPortraitUpsideDown - (void)verifyTapByCoordinatesWithOrientation:(UIDeviceOrientation)orientation { [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation]; - NSError *error; XCUIElement *dstButton = self.testedApplication.buttons[FBShowAlertButtonName]; - [dstButton fb_tapCoordinate:CGPointMake(dstButton.frame.size.width / 2, dstButton.frame.size.height / 2) error:&error]; + [[dstButton coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)] tap]; FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0); } @@ -98,10 +92,7 @@ - (void)testTapCoordinatesInLandscapeRight [self verifyTapByCoordinatesWithOrientation:UIDeviceOrientationLandscapeRight]; } -// Visibility detection for upside-down orientation is broken -// and cannot be workarounded properly, but this is not very important for Appium, since -// We don't support such orientation anyway -- (void)disabled_testTapCoordinatesInPortraitUpsideDown +- (void)testTapCoordinatesInPortraitUpsideDown { [self verifyTapByCoordinatesWithOrientation:UIDeviceOrientationPortraitUpsideDown]; } From dc498910133a0d17a91d1d9cf4caa89e1afa1704 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 May 2023 07:34:17 +0000 Subject: [PATCH 027/133] chore(release): 5.1.5 [skip ci] ## [5.1.5](https://github.com/appium/WebDriverAgent/compare/v5.1.4...v5.1.5) (2023-05-18) ### Miscellaneous Chores * Drop obsolete workarounds for coordinates calculation ([#701](https://github.com/appium/WebDriverAgent/issues/701)) ([259f731](https://github.com/appium/WebDriverAgent/commit/259f7319305b15a3f541957d3ccaa3cb12c9e1a3)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf2c328b8..f6b245d64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.1.5](https://github.com/appium/WebDriverAgent/compare/v5.1.4...v5.1.5) (2023-05-18) + + +### Miscellaneous Chores + +* Drop obsolete workarounds for coordinates calculation ([#701](https://github.com/appium/WebDriverAgent/issues/701)) ([259f731](https://github.com/appium/WebDriverAgent/commit/259f7319305b15a3f541957d3ccaa3cb12c9e1a3)) + ## [5.1.4](https://github.com/appium/WebDriverAgent/compare/v5.1.3...v5.1.4) (2023-05-16) diff --git a/package.json b/package.json index 90c318a34..0c888e5b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.1.4", + "version": "5.1.5", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 3e495230674a46db29ecea3b36c2ed0ea1bf2842 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 May 2023 17:20:52 +0200 Subject: [PATCH 028/133] chore(deps): bump @appium/support from 3.1.11 to 4.0.0 (#710) Bumps [@appium/support](https://github.com/appium/appium/tree/HEAD/packages/support) from 3.1.11 to 4.0.0. - [Release notes](https://github.com/appium/appium/releases) - [Changelog](https://github.com/appium/appium/blob/master/packages/support/CHANGELOG.md) - [Commits](https://github.com/appium/appium/commits/@appium/support@4.0.0/packages/support) --- updated-dependencies: - dependency-name: "@appium/support" dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0c888e5b1..8989cb318 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ }, "dependencies": { "@appium/base-driver": "^9.0.0", - "@appium/support": "^3.0.0", + "@appium/support": "^4.0.0", "@babel/runtime": "^7.0.0", "appium-ios-device": "^2.5.0", "appium-ios-simulator": "^5.0.1", From 5738bb59388f09fde741b02b00a78be937eb98bb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 May 2023 15:29:51 +0000 Subject: [PATCH 029/133] chore(release): 5.1.6 [skip ci] ## [5.1.6](https://github.com/appium/WebDriverAgent/compare/v5.1.5...v5.1.6) (2023-05-18) ### Miscellaneous Chores * **deps:** bump @appium/support from 3.1.11 to 4.0.0 ([#710](https://github.com/appium/WebDriverAgent/issues/710)) ([3e49523](https://github.com/appium/WebDriverAgent/commit/3e495230674a46db29ecea3b36c2ed0ea1bf2842)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6b245d64..de99d00fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.1.6](https://github.com/appium/WebDriverAgent/compare/v5.1.5...v5.1.6) (2023-05-18) + + +### Miscellaneous Chores + +* **deps:** bump @appium/support from 3.1.11 to 4.0.0 ([#710](https://github.com/appium/WebDriverAgent/issues/710)) ([3e49523](https://github.com/appium/WebDriverAgent/commit/3e495230674a46db29ecea3b36c2ed0ea1bf2842)) + ## [5.1.5](https://github.com/appium/WebDriverAgent/compare/v5.1.4...v5.1.5) (2023-05-18) diff --git a/package.json b/package.json index 8989cb318..bc9cd830a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.1.5", + "version": "5.1.6", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 9afc2d79c0b6ae5413cc966346b9240768cd5377 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 18 May 2023 21:27:59 +0200 Subject: [PATCH 030/133] ci: Disable tests that are unstable in CI env with older OS versions (#711) --- .../IntegrationTests/FBScrollingTests.m | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/WebDriverAgentTests/IntegrationTests/FBScrollingTests.m b/WebDriverAgentTests/IntegrationTests/FBScrollingTests.m index 16c9df00e..f1c5e15a0 100644 --- a/WebDriverAgentTests/IntegrationTests/FBScrollingTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBScrollingTests.m @@ -49,6 +49,11 @@ - (void)testCellVisibility - (void)testSimpleScroll { + if (SYSTEM_VERSION_LESS_THAN(@"16.0")) { + // This test is unstable in CI env + return; + } + FBAssertVisibleCell(@"0"); FBAssertVisibleCell(@"10"); [self.scrollView fb_scrollDownByNormalizedDistance:1.0]; @@ -82,6 +87,11 @@ - (void)testFarScrollToVisible - (void)testNativeFarScrollToVisible { + if (SYSTEM_VERSION_LESS_THAN(@"16.0")) { + // This test is unstable in CI env + return; + } + NSString *cellName = @"80"; NSError *error; FBAssertInvisibleCell(cellName); @@ -100,6 +110,12 @@ - (void)testAttributeWithNullScrollToVisible [element fb_scrollToVisibleWithError:&error]; XCTAssertNil(error); XCTAssertTrue(element.fb_isVisible); + + if (SYSTEM_VERSION_LESS_THAN(@"16.0")) { + // This test is unstable in CI env + return; + } + [element tap]; XCTAssertTrue(element.wdSelected); } From cdfae408be0bcf6607f0ca4462925eed2c300f5e Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 20 May 2023 09:10:41 +0200 Subject: [PATCH 031/133] feat: Replace non-encodable characters in the resulting JSON (#713) --- WebDriverAgent.xcodeproj/project.pbxproj | 15 ++++ .../NSDictionary+FBUtf8SafeDictionary.h | 40 +++++++++ .../NSDictionary+FBUtf8SafeDictionary.m | 88 +++++++++++++++++++ .../Routing/FBResponseJSONPayload.m | 9 ++ .../UnitTests/NSDictionaryFBUtf8SafeTests.m | 35 ++++++++ 5 files changed, 187 insertions(+) create mode 100644 WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h create mode 100644 WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m create mode 100644 WebDriverAgentTests/UnitTests/NSDictionaryFBUtf8SafeTests.m diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index eafb306ad..a5b933127 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -399,6 +399,9 @@ 716E0BCE1E917E810087A825 /* NSString+FBXMLSafeString.h in Headers */ = {isa = PBXBuildFile; fileRef = 716E0BCC1E917E810087A825 /* NSString+FBXMLSafeString.h */; }; 716E0BCF1E917E810087A825 /* NSString+FBXMLSafeString.m in Sources */ = {isa = PBXBuildFile; fileRef = 716E0BCD1E917E810087A825 /* NSString+FBXMLSafeString.m */; }; 716E0BD11E917F260087A825 /* FBXMLSafeStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 716E0BD01E917F260087A825 /* FBXMLSafeStringTests.m */; }; + 716F0DA12A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */; }; + 716F0DA32A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 716F0DA02A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m */; }; + 716F0DA62A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 716F0DA52A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m */; }; 718226CA2587443700661B83 /* GCDAsyncUdpSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 718226C62587443600661B83 /* GCDAsyncUdpSocket.h */; }; 718226CB2587443700661B83 /* GCDAsyncUdpSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 718226C62587443600661B83 /* GCDAsyncUdpSocket.h */; }; 718226CC2587443700661B83 /* GCDAsyncSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 718226C72587443600661B83 /* GCDAsyncSocket.h */; }; @@ -1004,6 +1007,9 @@ 716E0BCC1E917E810087A825 /* NSString+FBXMLSafeString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+FBXMLSafeString.h"; sourceTree = ""; }; 716E0BCD1E917E810087A825 /* NSString+FBXMLSafeString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+FBXMLSafeString.m"; sourceTree = ""; }; 716E0BD01E917F260087A825 /* FBXMLSafeStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXMLSafeStringTests.m; sourceTree = ""; }; + 716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+FBUtf8SafeDictionary.h"; sourceTree = ""; }; + 716F0DA02A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+FBUtf8SafeDictionary.m"; sourceTree = ""; }; + 716F0DA52A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSDictionaryFBUtf8SafeTests.m; sourceTree = ""; }; 717C0D702518ED2800CAA6EC /* TVOSSettings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TVOSSettings.xcconfig; sourceTree = ""; }; 717C0D862518ED7000CAA6EC /* TVOSTestSettings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TVOSTestSettings.xcconfig; sourceTree = ""; }; 718226C62587443600661B83 /* GCDAsyncUdpSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GCDAsyncUdpSocket.h; path = WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.h; sourceTree = SOURCE_ROOT; }; @@ -1701,6 +1707,8 @@ EE9AB73E1CAEDF0C008C271F /* Categories */ = { isa = PBXGroup; children = ( + 716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */, + 716F0DA02A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m */, 71555A3B1DEC460A007D4A8B /* NSExpression+FBFormat.h */, 71555A3C1DEC460A007D4A8B /* NSExpression+FBFormat.m */, 71A224E31DE2F56600844D55 /* NSPredicate+FBFormat.h */, @@ -2022,6 +2030,7 @@ 716E0BD01E917F260087A825 /* FBXMLSafeStringTests.m */, 712A0C841DA3E459007D02E5 /* FBXPathTests.m */, EE9B76581CF7987300275851 /* Info.plist */, + 716F0DA52A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m */, 7139145B1DF01A12005896C2 /* NSExpressionFBFormatTests.m */, 71A224E71DE326C500844D55 /* NSPredicateFBFormatTests.m */, 713914591DF01989005896C2 /* XCUIElementHelpersTests.m */, @@ -2405,6 +2414,7 @@ 641EE6C02240C5CA00173FCB /* XCUIApplication+FBHelpers.h in Headers */, 641EE6C12240C5CA00173FCB /* _XCTestObservationCenterImplementation.h in Headers */, 714EAA0E2673FDFE005C5B47 /* FBCapabilities.h in Headers */, + 716F0DA22A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h in Headers */, 641EE6C22240C5CA00173FCB /* XCUIDevice+FBHelpers.h in Headers */, 71D3B3D6267FC7260076473D /* XCUIElement+FBResolve.h in Headers */, 641EE6C32240C5CA00173FCB /* FBClassChainQueryParser.h in Headers */, @@ -2594,6 +2604,7 @@ EE35AD271E3B77D600A02D78 /* XCApplicationMonitor.h in Headers */, EE8DDD7F20C5733C004D4925 /* XCUIElement+FBForceTouch.h in Headers */, 71A5C67329A4F39600421C37 /* XCTIssue+FBPatcher.h in Headers */, + 716F0DA12A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h in Headers */, EE158AEA1CBD456F00A3E3F0 /* FBRuntimeUtils.h in Headers */, 7136A4791E8918E60024FC3D /* XCUIElement+FBPickerWheel.h in Headers */, E444DCB324913C220060D7EB /* RoutingHTTPServer.h in Headers */, @@ -3106,6 +3117,7 @@ 641EE5FF2240C5CA00173FCB /* XCUIElement+FBForceTouch.m in Sources */, 716C9E0327315EFF005AD475 /* XCUIApplication+FBUIInterruptions.m in Sources */, 641EE6002240C5CA00173FCB /* FBTouchActionCommands.m in Sources */, + 716F0DA42A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m in Sources */, 719DCF182601EAFB000E765F /* FBNotificationsHelper.m in Sources */, 714EAA102673FDFE005C5B47 /* FBCapabilities.m in Sources */, 641EE6012240C5CA00173FCB /* FBImageIOScaler.m in Sources */, @@ -3160,6 +3172,7 @@ buildActionMask = 2147483647; files = ( 64B26508228C5514002A5025 /* XCUIElementDouble.m in Sources */, + 716F0DA72A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m in Sources */, 64B26504228C5299002A5025 /* FBTVNavigationTrackerTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3229,6 +3242,7 @@ 716E0BCF1E917E810087A825 /* NSString+FBXMLSafeString.m in Sources */, EE158ACD1CBD456F00A3E3F0 /* FBUnknownCommands.m in Sources */, EE158AC51CBD456F00A3E3F0 /* FBOrientationCommands.m in Sources */, + 716F0DA32A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m in Sources */, 71D475C42538F5A8008D9401 /* XCUIApplicationProcess+FBQuiescence.m in Sources */, 641EE7082240CDEB00173FCB /* XCUIElement+FBTVFocuse.m in Sources */, 71E75E6F254824230099FC87 /* XCUIElementQuery+FBHelpers.m in Sources */, @@ -3346,6 +3360,7 @@ 7139145C1DF01A12005896C2 /* NSExpressionFBFormatTests.m in Sources */, 71A224E81DE326C500844D55 /* NSPredicateFBFormatTests.m in Sources */, EE6A892B1D0B25820083E92B /* FBApplicationDouble.m in Sources */, + 716F0DA62A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m in Sources */, EE6A892D1D0B2AF40083E92B /* FBErrorBuilderTests.m in Sources */, 712A0C851DA3E459007D02E5 /* FBXPathTests.m in Sources */, ADBC39981D07842800327304 /* XCUIElementDouble.m in Sources */, diff --git a/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h b/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h new file mode 100644 index 000000000..0f657ab6f --- /dev/null +++ b/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSString (FBUtf8SafeString) + +/** + Converts the string, so it could be properly represented in UTF-8 encoding. All non-encodable characters are replaced with + the given `replacement` + + @param replacement The character to use a a replacement for the lossy encoding + @returns Either the same string or a string with non-encodable chars replaced + */ +- (instancetype)fb_utf8SafeStringWithReplacement:(unichar)replacement; + +@end + +@interface NSDictionary (FBUtf8SafeDictionary) + +/** + Converts the dictionary, so it could be properly represented in UTF-8 encoding. All non-encodable characters + in string values are replaced with the Unocde question mark characters. Nested dictionaries and arrays are + processed recursively. + + @returns Either the same dictionary or a dictionary with non-encodable chars in string values replaced + */ +- (instancetype)fb_utf8SafeDictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m b/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m new file mode 100644 index 000000000..399769142 --- /dev/null +++ b/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "NSDictionary+FBUtf8SafeDictionary.h" + +const unichar REPLACER = 0xfffd; + +@implementation NSString (FBUtf8SafeString) + +- (instancetype)fb_utf8SafeStringWithReplacement:(unichar)replacement +{ + if ([self canBeConvertedToEncoding:NSUTF8StringEncoding]) { + return self; + } + + NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; + NSString *convertedString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSMutableString *result = [NSMutableString string]; + NSString *replacementStr = [NSString stringWithCharacters:&replacement length:1]; + NSUInteger originalIdx = 0; + NSUInteger convertedIdx = 0; + while (originalIdx < [self length] && convertedIdx < [convertedString length]) { + unichar originalChar = [self characterAtIndex:originalIdx]; + unichar convertedChar = [convertedString characterAtIndex:convertedIdx]; + + if (originalChar == convertedChar) { + [result appendString:[NSString stringWithCharacters:&originalChar length:1]]; + originalIdx++; + convertedIdx++; + continue; + } + + while (originalChar != convertedChar && originalIdx < [self length]) { + [result appendString:replacementStr]; + originalChar = [self characterAtIndex:++originalIdx]; + } + } + return result.copy; +} + +@end + +@implementation NSArray (FBUtf8SafeArray) + +- (instancetype)fb_utf8SafeArray +{ + NSMutableArray *result = [NSMutableArray array]; + for (id item in self) { + if ([item isKindOfClass:NSString.class]) { + [result addObject:[(NSString *)item fb_utf8SafeStringWithReplacement:REPLACER]]; + } else if ([item isKindOfClass:NSDictionary.class]) { + [result addObject:[(NSDictionary *)item fb_utf8SafeDictionary]]; + } else if ([item isKindOfClass:NSArray.class]) { + [result addObject:[(NSArray *)item fb_utf8SafeArray]]; + } else { + [result addObject:item]; + } + } + return result.copy; +} + +@end + +@implementation NSDictionary (FBUtf8SafeDictionary) + +- (instancetype)fb_utf8SafeDictionary +{ + NSMutableDictionary *result = [self mutableCopy]; + for (id key in self) { + id value = result[key]; + if ([value isKindOfClass:NSString.class]) { + result[key] = [(NSString *)value fb_utf8SafeStringWithReplacement:REPLACER]; + } else if ([value isKindOfClass:NSArray.class]) { + result[key] = [(NSArray *)value fb_utf8SafeArray]; + } else if ([value isKindOfClass:NSDictionary.class]) { + result[key] = [(NSDictionary *)value fb_utf8SafeDictionary]; + } + } + return result.copy; +} + +@end diff --git a/WebDriverAgentLib/Routing/FBResponseJSONPayload.m b/WebDriverAgentLib/Routing/FBResponseJSONPayload.m index d00ed38a7..4ad1c37ad 100644 --- a/WebDriverAgentLib/Routing/FBResponseJSONPayload.m +++ b/WebDriverAgentLib/Routing/FBResponseJSONPayload.m @@ -9,6 +9,8 @@ #import "FBResponseJSONPayload.h" +#import "FBLogger.h" +#import "NSDictionary+FBUtf8SafeDictionary.h" #import "RouteResponse.h" @interface FBResponseJSONPayload () @@ -43,6 +45,13 @@ - (void)dispatchWithResponse:(RouteResponse *)response options:NSJSONWritingPrettyPrinted error:&error]; NSCAssert(jsonData, @"Valid JSON must be responded, error of %@", error); + if (nil == [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]) { + [FBLogger log:@"The incoming data cannot be encoded to UTF-8 JSON. Applying lossy conversion as a workaround."]; + jsonData = [NSJSONSerialization dataWithJSONObject:[self.dictionary fb_utf8SafeDictionary] + options:NSJSONWritingPrettyPrinted + error:&error]; + } + NSCAssert(jsonData, @"Valid JSON must be responded, error of %@", error); [response setHeader:@"Content-Type" value:@"application/json;charset=UTF-8"]; [response setStatusCode:self.httpStatusCode]; [response respondWithData:jsonData]; diff --git a/WebDriverAgentTests/UnitTests/NSDictionaryFBUtf8SafeTests.m b/WebDriverAgentTests/UnitTests/NSDictionaryFBUtf8SafeTests.m new file mode 100644 index 000000000..3f6f465a3 --- /dev/null +++ b/WebDriverAgentTests/UnitTests/NSDictionaryFBUtf8SafeTests.m @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import "NSDictionary+FBUtf8SafeDictionary.h" + +@interface NSDictionaryFBUtf8SafeTests : XCTestCase +@end + +@implementation NSDictionaryFBUtf8SafeTests + +- (void)testEmptySafeDictConversion +{ + NSDictionary *d = @{}; + XCTAssertEqualObjects(d, d.fb_utf8SafeDictionary); +} + +- (void)testNonEmptySafeDictConversion +{ + NSDictionary *d = @{ + @"1": @[@3, @4], + @"5": @{@"6": @7, @"8": @9}, + @"10": @"11" + }; + XCTAssertEqualObjects(d, d.fb_utf8SafeDictionary); +} + +@end From 0cb36e656126755196efc243af66468c4d115c92 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 20 May 2023 07:19:21 +0000 Subject: [PATCH 032/133] chore(release): 5.2.0 [skip ci] ## [5.2.0](https://github.com/appium/WebDriverAgent/compare/v5.1.6...v5.2.0) (2023-05-20) ### Features * Replace non-encodable characters in the resulting JSON ([#713](https://github.com/appium/WebDriverAgent/issues/713)) ([cdfae40](https://github.com/appium/WebDriverAgent/commit/cdfae408be0bcf6607f0ca4462925eed2c300f5e)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de99d00fb..40c8f9b69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.2.0](https://github.com/appium/WebDriverAgent/compare/v5.1.6...v5.2.0) (2023-05-20) + + +### Features + +* Replace non-encodable characters in the resulting JSON ([#713](https://github.com/appium/WebDriverAgent/issues/713)) ([cdfae40](https://github.com/appium/WebDriverAgent/commit/cdfae408be0bcf6607f0ca4462925eed2c300f5e)) + ## [5.1.6](https://github.com/appium/WebDriverAgent/compare/v5.1.5...v5.1.6) (2023-05-18) diff --git a/package.json b/package.json index bc9cd830a..33183142a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.1.6", + "version": "5.2.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 4611792ee5d5d7f39d188b5ebc31017f436c5ace Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 22 May 2023 09:16:42 +0200 Subject: [PATCH 033/133] feat: Use strongbox to persist the previous version of the module (#714) --- lib/webdriveragent.js | 80 +++++++++++++++++++++---------------------- package.json | 1 + 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index ef6e8e766..350353ed2 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -3,7 +3,7 @@ import path from 'path'; import url from 'url'; import B from 'bluebird'; import { JWProxy } from '@appium/base-driver'; -import { fs, util, plist, mkdirp } from '@appium/support'; +import { fs, util, plist } from '@appium/support'; import defaultLogger from './logger'; import { NoSessionProxy } from './no-session-proxy'; import { @@ -15,14 +15,16 @@ import { exec } from 'teen_process'; import { bundleWDASim } from './check-dependencies'; import { WDA_RUNNER_BUNDLE_ID, WDA_RUNNER_BUNDLE_ID_FOR_XCTEST, WDA_RUNNER_APP, - WDA_BASE_URL, WDA_UPGRADE_TIMESTAMP_PATH, + WDA_BASE_URL, WDA_UPGRADE_TIMESTAMP_PATH } from './constants'; import {Xctest} from 'appium-ios-device'; +import {strongbox} from '@appium/strongbox'; const WDA_LAUNCH_TIMEOUT = 60 * 1000; const WDA_AGENT_PORT = 8100; const WDA_CF_BUNDLE_NAME = 'WebDriverAgentRunner-Runner'; const SHARED_RESOURCES_GUARD = new AsyncLock(); +const RECENT_MODULE_VERSION_ITEM_NAME = 'recentWdaModuleVersion'; class WebDriverAgent { constructor (xcodeVersion, args = {}, log = null) { @@ -224,63 +226,61 @@ class WebDriverAgent { } async _cleanupProjectIfFresh () { - const homeFolder = process.env.HOME; - if (!homeFolder) { - this.log.info('The HOME folder path cannot be determined'); - return; - } - - const currentUpgradeTimestamp = await getWDAUpgradeTimestamp(); - if (!_.isInteger(currentUpgradeTimestamp)) { - this.log.info('It is impossible to determine the timestamp of the package'); + if (this.canSkipXcodebuild) { return; } - const timestampPath = path.resolve(homeFolder, WDA_UPGRADE_TIMESTAMP_PATH); - const didTimestampExist = await fs.exists(timestampPath); - if (didTimestampExist) { - try { - await fs.access(timestampPath, fs.W_OK); - } catch (ign) { - this.log.info(`WebDriverAgent upgrade timestamp at '${timestampPath}' is not writeable. ` + - `Skipping sources cleanup`); - return; - } - const recentUpgradeTimestamp = parseInt(await fs.readFile(timestampPath, 'utf8'), 10); - if (_.isInteger(recentUpgradeTimestamp)) { - if (recentUpgradeTimestamp >= currentUpgradeTimestamp) { - this.log.info(`WebDriverAgent does not need a cleanup. The sources are up to date ` + - `(${recentUpgradeTimestamp} >= ${currentUpgradeTimestamp})`); + const packageInfo = JSON.parse(await fs.readFile(path.join(BOOTSTRAP_PATH, 'package.json'), 'utf8')); + const box = strongbox(packageInfo.name); + let boxItem = box.getItem(RECENT_MODULE_VERSION_ITEM_NAME); + if (!boxItem) { + const timestampPath = path.resolve(process.env.HOME, WDA_UPGRADE_TIMESTAMP_PATH); + if (await fs.exists(timestampPath)) { + // TODO: It is probably a bit ugly to hardcode the recent version string, + // TODO: hovewer it should do the job as a temporary transition trick + // TODO: to switch from a hardcoded file path to the strongbox usage. + try { + boxItem = await box.createItemWithContents(RECENT_MODULE_VERSION_ITEM_NAME, '5.0.0'); + } catch (e) { + this.log.warn(`The actual module version cannot be persisted: ${e.message}`); return; } - this.log.info(`WebDriverAgent sources have been upgraded ` + - `(${recentUpgradeTimestamp} < ${currentUpgradeTimestamp})`); } else { - this.log.warn(`The recent upgrade timestamp at '${timestampPath}' is corrupted. Trying to fix it`); + this.log.info('There is no need to perform the project cleanup. A fresh install has been detected'); + try { + await box.createItemWithContents(RECENT_MODULE_VERSION_ITEM_NAME, packageInfo.version); + } catch (e) { + this.log.warn(`The actual module version cannot be persisted: ${e.message}`); + } + return; } } + let recentModuleVersion = await boxItem.read(); try { - await mkdirp(path.dirname(timestampPath)); - await fs.writeFile(timestampPath, `${currentUpgradeTimestamp}`, 'utf8'); - this.log.debug(`Stored the recent WebDriverAgent upgrade timestamp ${currentUpgradeTimestamp} ` + - `at '${timestampPath}'`); + recentModuleVersion = util.coerceVersion(recentModuleVersion, true); } catch (e) { - this.log.info(`Unable to create the recent WebDriverAgent upgrade timestamp at '${timestampPath}'. ` + - `Original error: ${e.message}`); + this.log.warn(`The persisted module version string has been damaged: ${e.message}`); + this.log.info(`Updating it to '${packageInfo.version}' assuming the project clenup is not needed`); + await boxItem.write(packageInfo.version); return; } - if (!didTimestampExist) { - this.log.info('There is no need to perform the project cleanup. A fresh install has been detected'); + if (util.compareVersions(recentModuleVersion, '>=', packageInfo.version)) { + this.log.info( + `WebDriverAgent does not need a cleanup. The project sources are up to date ` + + `(${recentModuleVersion} >= ${packageInfo.version})` + ); return; } - if (this.canSkipXcodebuild) { - return; - } + this.log.info( + `Cleaning up the WebDriverAgent project after the module upgrade has happened ` + + `(${recentModuleVersion} < ${packageInfo.version})` + ); try { await this.xcodebuild.cleanProject(); + await boxItem.write(packageInfo.version); } catch (e) { this.log.warn(`Cannot perform WebDriverAgent project cleanup. Original error: ${e.message}`); } diff --git a/package.json b/package.json index 33183142a..069be4176 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ }, "dependencies": { "@appium/base-driver": "^9.0.0", + "@appium/strongbox": "^0.x", "@appium/support": "^4.0.0", "@babel/runtime": "^7.0.0", "appium-ios-device": "^2.5.0", From 1be93e7e2d8f1330680cb72196e8647bf41e1bd0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 22 May 2023 07:25:17 +0000 Subject: [PATCH 034/133] chore(release): 5.3.0 [skip ci] ## [5.3.0](https://github.com/appium/WebDriverAgent/compare/v5.2.0...v5.3.0) (2023-05-22) ### Features * Use strongbox to persist the previous version of the module ([#714](https://github.com/appium/WebDriverAgent/issues/714)) ([4611792](https://github.com/appium/WebDriverAgent/commit/4611792ee5d5d7f39d188b5ebc31017f436c5ace)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40c8f9b69..3110ef040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.3.0](https://github.com/appium/WebDriverAgent/compare/v5.2.0...v5.3.0) (2023-05-22) + + +### Features + +* Use strongbox to persist the previous version of the module ([#714](https://github.com/appium/WebDriverAgent/issues/714)) ([4611792](https://github.com/appium/WebDriverAgent/commit/4611792ee5d5d7f39d188b5ebc31017f436c5ace)) + ## [5.2.0](https://github.com/appium/WebDriverAgent/compare/v5.1.6...v5.2.0) (2023-05-20) diff --git a/package.json b/package.json index 069be4176..af98cd09c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.2.0", + "version": "5.3.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 8bc3135f021b529d916846477544f4b8ca890f59 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 1 Jun 2023 11:14:35 -0700 Subject: [PATCH 035/133] ci: build wda for simulators in a task (#718) * refer to env.HOST * ci: use a shell script * ci: tweak paths * ci: tweak name * add zip for sim * ci: tweak the naming * tweak a bit * tweak the paths * simplify simulators * fix syntax error * fix syntax of runs on * fix synax * remove unnecessary env * try matrix * tweak * tweak naming * tweak * run after a release task as well --- .github/workflows/wda-package.yml | 102 ++++++++++++++++++++---------- Scripts/ci/build-real.sh | 17 +++++ Scripts/ci/build-sim.sh | 19 ++++++ 3 files changed, 105 insertions(+), 33 deletions(-) create mode 100755 Scripts/ci/build-real.sh create mode 100755 Scripts/ci/build-sim.sh diff --git a/.github/workflows/wda-package.yml b/.github/workflows/wda-package.yml index 21cfe155a..d544e927e 100644 --- a/.github/workflows/wda-package.yml +++ b/.github/workflows/wda-package.yml @@ -2,18 +2,35 @@ name: Building WebDriverAgent on: workflow_dispatch: + workflow_run: + workflows: ["Release"] + types: + - completed + +env: + HOST: macos-12 + XCODE_VERSION: 14.2 + DESTINATION_SIM: platform=iOS Simulator,name=iPhone 14 Pro + DESTINATION_SIM_tvOS: platform=tvOS Simulator,name=Apple TV jobs: - build: + host_machine: + runs-on: ubuntu-latest + outputs: + host: ${{ steps.macos_host.outputs.host }} + steps: + - run: | + echo "host=${{ env.HOST }}" >> $GITHUB_OUTPUT + id: macos_host + + for_real_devices: + needs: [host_machine] name: Build WDA for real iOS and tvOS devices - runs-on: macos-12 + runs-on: ${{ needs.host_machine.outputs.host }} env: - XCODE_VERSION: 14.1 ZIP_PKG_NAME_IOS: "WebDriverAgentRunner-Runner.zip" - PKG_PATH_IOS: "appium_wda_ios" ZIP_PKG_NAME_TVOS: "WebDriverAgentRunner_tvOS-Runner.zip" - PKG_PATH_TVOS: "appium_wda_tvos" steps: - name: Checkout @@ -21,34 +38,24 @@ jobs: - uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: "${{ env.XCODE_VERSION }}" - - name: Build iOS - run: | - xcodebuild clean build-for-testing \ - -project WebDriverAgent.xcodeproj \ - -derivedDataPath $PKG_PATH_IOS \ - -scheme WebDriverAgentRunner \ - -destination generic/platform=iOS \ - CODE_SIGNING_ALLOWED=NO ARCHS=arm64 - - name: Creating a zip of WebDriverAgentRunner-Runner.app for iOS - run: | - pushd appium_wda_ios/Build/Products/Debug-iphoneos - zip -r $ZIP_PKG_NAME_IOS WebDriverAgentRunner-Runner.app - popd - mv $PKG_PATH_IOS/Build/Products/Debug-iphoneos/$ZIP_PKG_NAME_IOS ./ - - name: Build tvOS - run: | - xcodebuild clean build-for-testing \ - -project WebDriverAgent.xcodeproj \ - -derivedDataPath $PKG_PATH_TVOS \ - -scheme WebDriverAgentRunner_tvOS \ - -destination generic/platform=tvOS \ - CODE_SIGNING_ALLOWED=NO ARCHS=arm64 - - name: Creating a zip of WebDriverAgentRunner-Runner.app for tvOS - run: | - pushd appium_wda_tvos/Build/Products/Debug-appletvos - zip -r $ZIP_PKG_NAME_TVOS WebDriverAgentRunner_tvOS-Runner.app - popd - mv $PKG_PATH_TVOS/Build/Products/Debug-appletvos/$ZIP_PKG_NAME_TVOS ./ + - name: Create a zip file of WebDriverAgentRunner-Runner.app for iOS + run: sh $GITHUB_WORKSPACE/Scripts/ci/build-real.sh + env: + DERIVED_DATA_PATH: appium_wda_ios + SCHEME: WebDriverAgentRunner + DESTINATION: generic/platform=iOS + WD: appium_wda_ios/Build/Products/Debug-iphoneos + ZIP_PKG_NAME: "${{ env.ZIP_PKG_NAME_IOS }}" + + - name: Create a zip file of WebDriverAgentRunner-Runner.app for tvOS + run: sh $GITHUB_WORKSPACE/Scripts/ci/build-real.sh + env: + DERIVED_DATA_PATH: appium_wda_tvos + SCHEME: WebDriverAgentRunner_tvOS + DESTINATION: generic/platform=tvOS + WD: appium_wda_tvos/Build/Products/Debug-appletvos + ZIP_PKG_NAME: "${{ env.ZIP_PKG_NAME_TVOS }}" + - name: Upload the built generic app package for iOS uses: actions/upload-artifact@v3.1.0 with: @@ -57,3 +64,32 @@ jobs: uses: actions/upload-artifact@v3.1.0 with: path: "${{ env.ZIP_PKG_NAME_TVOS }}" + + for_simulator_devices: + needs: [host_machine] + name: Build WDA for ${{ matrix.target }} simulators + runs-on: ${{ needs.host_machine.outputs.host }} + + strategy: + matrix: + # '' is for iOS + target: ['', '_tvOS'] + arch: [x86_64, arm64] + steps: + - name: Checkout + uses: actions/checkout@v3 + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: "${{ env.XCODE_VERSION }}" + - name: Create a zip of WebDriverAgentRunner${{ matrix.target }} for simulator for ${{ matrix.arch }} + run: | + DESTINATION=$DESTINATION_SIM${{ matrix.target }} sh $GITHUB_WORKSPACE/Scripts/ci/build-sim.sh + env: + TARGET: ${{ matrix.target }} + SCHEME: WebDriverAgentRunner${{ matrix.target }} + ARCHS: ${{ matrix.arch }} + ZIP_PKG_NAME: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" + - name: Upload the built generic app package for WebDriverAgentRunner${{ matrix.target }} with ${{ matrix.arch }} + uses: actions/upload-artifact@v3.1.0 + with: + path: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" diff --git a/Scripts/ci/build-real.sh b/Scripts/ci/build-real.sh new file mode 100755 index 000000000..9303ffe3b --- /dev/null +++ b/Scripts/ci/build-real.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# To run build script for CI + +xcodebuild clean build-for-testing \ + -project WebDriverAgent.xcodeproj \ + -derivedDataPath $DERIVED_DATA_PATH \ + -scheme $SCHEME \ + -destination "$DESTINATION" \ + CODE_SIGNING_ALLOWED=NO ARCHS=arm64 + +# Only .app is needed. + +pushd $WD +zip -r $ZIP_PKG_NAME $SCHEME-Runner.app +popd +mv $WD/$ZIP_PKG_NAME ./ diff --git a/Scripts/ci/build-sim.sh b/Scripts/ci/build-sim.sh new file mode 100755 index 000000000..de52abccf --- /dev/null +++ b/Scripts/ci/build-sim.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# To run build script for CI + +xcodebuild clean build-for-testing \ + -project WebDriverAgent.xcodeproj \ + -derivedDataPath wda_build \ + -scheme $SCHEME \ + -destination "$DESTINATION" \ + CODE_SIGNING_ALLOWED=NO ARCHS=$ARCHS + +# simulator needs to build entire build files + +pushd wda_build +# to remove unnecessary space consuming files +rm -rf Build/Intermediates.noindex +zip -r $ZIP_PKG_NAME Build +popd +mv wda_build/$ZIP_PKG_NAME ./ From 5f811ac65ba3ac770e42bd7f8614815df8ec990f Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 5 Jun 2023 21:47:47 -0700 Subject: [PATCH 036/133] fix: remove Parameter of overriding method should be annotated with __attribute__((noescape)) (#720) --- PrivateHeaders/XCTest/XCTestCase.h | 1 - 1 file changed, 1 deletion(-) diff --git a/PrivateHeaders/XCTest/XCTestCase.h b/PrivateHeaders/XCTest/XCTestCase.h index f00038ef9..d68d949c5 100644 --- a/PrivateHeaders/XCTest/XCTestCase.h +++ b/PrivateHeaders/XCTest/XCTestCase.h @@ -51,7 +51,6 @@ - (void)reportMeasurements:(id)arg1 forMetricID:(id)arg2 reportFailures:(BOOL)arg3; - (void)_recordValues:(id)arg1 forPerformanceMetricID:(id)arg2 name:(id)arg3 unitsOfMeasurement:(id)arg4 baselineName:(id)arg5 baselineAverage:(id)arg6 maxPercentRegression:(id)arg7 maxPercentRelativeStandardDeviation:(id)arg8 maxRegression:(id)arg9 maxStandardDeviation:(id)arg10 file:(id)arg11 line:(unsigned long long)arg12; - (id)_symbolicationRecordForTestCodeInAddressStack:(id)arg1; -- (void)measureBlock:(CDUnknownBlockType)arg1; - (void)stopMeasuring; - (void)startMeasuring; - (BOOL)_isMeasuringMetrics; From 244b8b85e671a20f21991fc13e21678848058fad Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 6 Jun 2023 05:00:44 +0000 Subject: [PATCH 037/133] chore(release): 5.3.1 [skip ci] ## [5.3.1](https://github.com/appium/WebDriverAgent/compare/v5.3.0...v5.3.1) (2023-06-06) ### Bug Fixes * remove Parameter of overriding method should be annotated with __attribute__((noescape)) ([#720](https://github.com/appium/WebDriverAgent/issues/720)) ([5f811ac](https://github.com/appium/WebDriverAgent/commit/5f811ac65ba3ac770e42bd7f8614815df8ec990f)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3110ef040..f61b4edc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.3.1](https://github.com/appium/WebDriverAgent/compare/v5.3.0...v5.3.1) (2023-06-06) + + +### Bug Fixes + +* remove Parameter of overriding method should be annotated with __attribute__((noescape)) ([#720](https://github.com/appium/WebDriverAgent/issues/720)) ([5f811ac](https://github.com/appium/WebDriverAgent/commit/5f811ac65ba3ac770e42bd7f8614815df8ec990f)) + ## [5.3.0](https://github.com/appium/WebDriverAgent/compare/v5.2.0...v5.3.0) (2023-05-22) diff --git a/package.json b/package.json index af98cd09c..76d2c5f9d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.3.0", + "version": "5.3.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From b22f61eda142ee6ec1db8c74a4788e0270ac7740 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 14:17:39 -0700 Subject: [PATCH 038/133] chore(deps-dev): bump conventional-changelog-conventionalcommits (#723) Bumps [conventional-changelog-conventionalcommits](https://github.com/conventional-changelog/conventional-changelog) from 5.0.0 to 6.0.0. - [Release notes](https://github.com/conventional-changelog/conventional-changelog/releases) - [Changelog](https://github.com/conventional-changelog/conventional-changelog/blob/master/.release-please-manifest.json) - [Commits](https://github.com/conventional-changelog/conventional-changelog/compare/conventional-changelog-conventionalcommits-v5.0.0...conventional-changelog-conventionalcommits-v6.0.0) --- updated-dependencies: - dependency-name: conventional-changelog-conventionalcommits dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 76d2c5f9d..f7969b0fd 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "appium-xcode": "^5.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "conventional-changelog-conventionalcommits": "^5.0.0", + "conventional-changelog-conventionalcommits": "^6.0.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.5.0", "glob": "^8.0.1", From 28b6e21df8173de8bf96c17452bf7432412fd9c5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 7 Jun 2023 21:28:12 +0000 Subject: [PATCH 039/133] chore(release): 5.3.2 [skip ci] ## [5.3.2](https://github.com/appium/WebDriverAgent/compare/v5.3.1...v5.3.2) (2023-06-07) ### Miscellaneous Chores * **deps-dev:** bump conventional-changelog-conventionalcommits ([#723](https://github.com/appium/WebDriverAgent/issues/723)) ([b22f61e](https://github.com/appium/WebDriverAgent/commit/b22f61eda142ee6ec1db8c74a4788e0270ac7740)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f61b4edc9..3284ed63a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.3.2](https://github.com/appium/WebDriverAgent/compare/v5.3.1...v5.3.2) (2023-06-07) + + +### Miscellaneous Chores + +* **deps-dev:** bump conventional-changelog-conventionalcommits ([#723](https://github.com/appium/WebDriverAgent/issues/723)) ([b22f61e](https://github.com/appium/WebDriverAgent/commit/b22f61eda142ee6ec1db8c74a4788e0270ac7740)) + ## [5.3.1](https://github.com/appium/WebDriverAgent/compare/v5.3.0...v5.3.1) (2023-06-06) diff --git a/package.json b/package.json index f7969b0fd..3d8c3763f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.3.1", + "version": "5.3.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From a070223e0ef43be8dd54d16ee3e3b96603ad5f3a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 8 Jun 2023 19:31:31 +0000 Subject: [PATCH 040/133] chore: Disable automatic screen recording by default (#726) --- WebDriverAgentLib/Utilities/FBConfiguration.h | 6 +++++- WebDriverAgentLib/Utilities/FBConfiguration.m | 10 ++++++++++ WebDriverAgentRunner/UITestingUITests.m | 5 +++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index 7bfbccc43..bcb341a8d 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -49,10 +49,14 @@ extern NSString *const FBSnapshotMaxDepthKey; /*! Disables XCTest automated screenshots taking */ + (void)disableScreenshots; - /*! Enables XCTest automated screenshots taking */ + (void)enableScreenshots; +/*! Disables XCTest automated videos taking (iOS 17+) */ ++ (void)disableScreenRecordings; +/*! Enables XCTest automated videos taking (iOS 17+) */ ++ (void)enableScreenRecordings; + /* The maximum typing frequency for all typing activities */ + (void)setMaxTypingFrequency:(NSUInteger)value; + (NSUInteger)maxTypingFrequency; diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index 1c80e5498..f99c9d148 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -94,6 +94,16 @@ + (void)enableScreenshots [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"DisableScreenshots"]; } ++ (void)disableScreenRecordings +{ + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"DisableDiagnosticScreenRecordings"]; +} + ++ (void)enableScreenRecordings +{ + [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"DisableDiagnosticScreenRecordings"]; +} + + (NSRange)bindingPortRange { // 'WebDriverAgent --port 8080' can be passed via the arguments to the process diff --git a/WebDriverAgentRunner/UITestingUITests.m b/WebDriverAgentRunner/UITestingUITests.m index c98fbd622..cc7c78073 100644 --- a/WebDriverAgentRunner/UITestingUITests.m +++ b/WebDriverAgentRunner/UITestingUITests.m @@ -26,6 +26,11 @@ + (void)setUp [FBConfiguration disableRemoteQueryEvaluation]; [FBConfiguration configureDefaultKeyboardPreferences]; [FBConfiguration disableApplicationUIInterruptionsHandling]; + if (NSProcessInfo.processInfo.environment[@"ENABLE_AUTOMATIC_SCREEN_RECORDINGS"]) { + [FBConfiguration enableScreenRecordings]; + } else { + [FBConfiguration disableScreenRecordings]; + } if (NSProcessInfo.processInfo.environment[@"ENABLE_AUTOMATIC_SCREENSHOTS"]) { [FBConfiguration enableScreenshots]; } else { From 0c198ed4a7af1eb5434199dddd0fe909ad8bf6c6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 8 Jun 2023 19:40:28 +0000 Subject: [PATCH 041/133] chore(release): 5.3.3 [skip ci] ## [5.3.3](https://github.com/appium/WebDriverAgent/compare/v5.3.2...v5.3.3) (2023-06-08) ### Miscellaneous Chores * Disable automatic screen recording by default ([#726](https://github.com/appium/WebDriverAgent/issues/726)) ([a070223](https://github.com/appium/WebDriverAgent/commit/a070223e0ef43be8dd54d16ee3e3b96603ad5f3a)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3284ed63a..fdbe0c6ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.3.3](https://github.com/appium/WebDriverAgent/compare/v5.3.2...v5.3.3) (2023-06-08) + + +### Miscellaneous Chores + +* Disable automatic screen recording by default ([#726](https://github.com/appium/WebDriverAgent/issues/726)) ([a070223](https://github.com/appium/WebDriverAgent/commit/a070223e0ef43be8dd54d16ee3e3b96603ad5f3a)) + ## [5.3.2](https://github.com/appium/WebDriverAgent/compare/v5.3.1...v5.3.2) (2023-06-07) diff --git a/package.json b/package.json index 3d8c3763f..0b530ba41 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.3.2", + "version": "5.3.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 364b7791393ffae9c048c5cac023e3e7d1813a14 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 9 Jun 2023 06:34:36 +0000 Subject: [PATCH 042/133] fix: Streamline errors handling for async block calls (#725) --- .../Utilities/FBXCTestDaemonsProxy.m | 118 ++++++++++-------- 1 file changed, 67 insertions(+), 51 deletions(-) diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m index 2bee1b96c..180689800 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m @@ -100,13 +100,12 @@ + (void)swizzleLaunchApp { + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSError *__autoreleasing*)error { - __block BOOL didSucceed = NO; + __block NSError *innerError = nil; [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ void (^errorHandler)(NSError *) = ^(NSError *invokeError) { - if (error) { - *error = invokeError; + if (nil != invokeError) { + innerError = invokeError; } - didSucceed = (invokeError == nil); completion(); }; @@ -117,31 +116,40 @@ + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSEr handlerBlock(record, invokeError); }]; }]; - return didSucceed; + if (nil != innerError) { + if (error) { + *error = innerError; + } + return NO; + } + return YES; } + (BOOL)openURL:(NSURL *)url usingApplication:(NSString *)bundleId error:(NSError *__autoreleasing*)error { XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(openURL:usingApplication:completion:)]) { - if (error) { - [[[FBErrorBuilder builder] - withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs with given application"] - buildError:error]; - } + [[[FBErrorBuilder builder] + withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs with given application"] + buildError:error]; return NO; } + __block NSError *innerError = nil; __block BOOL didSucceed = NO; [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ [session openURL:url usingApplication:bundleId completion:^(bool result, NSError *invokeError) { - if (error) { - *error = invokeError; + if (nil != invokeError) { + innerError = invokeError; + } else { + didSucceed = result; } - didSucceed = invokeError == nil && result; completion(); }]; }]; + if (nil != innerError && error) { + *error = innerError; + } return didSucceed; } @@ -149,24 +157,27 @@ + (BOOL)openDefaultApplicationForURL:(NSURL *)url error:(NSError *__autoreleasin { XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(openDefaultApplicationForURL:completion:)]) { - if (error) { - [[[FBErrorBuilder builder] - withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs. Consider upgrading to Xcode 14.3+/iOS 16.4+"] - buildError:error]; - } + [[[FBErrorBuilder builder] + withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs. Consider upgrading to Xcode 14.3+/iOS 16.4+"] + buildError:error]; return NO; } + __block NSError *innerError = nil; __block BOOL didSucceed = NO; [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ [session openDefaultApplicationForURL:url completion:^(bool result, NSError *invokeError) { - if (error) { - *error = invokeError; + if (nil != invokeError) { + innerError = invokeError; + } else { + didSucceed = result; } - didSucceed = invokeError == nil && result; completion(); }]; }]; + if (nil != innerError && error) { + *error = innerError; + } return didSucceed; } @@ -175,32 +186,33 @@ + (BOOL)setSimulatedLocation:(CLLocation *)location error:(NSError *__autoreleas { XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(setSimulatedLocation:completion:)]) { - if (error) { - [[[FBErrorBuilder builder] - withDescriptionFormat:@"The current Xcode SDK does not support location simulation. Consider upgrading to Xcode 14.3+/iOS 16.4+"] - buildError:error]; - } + [[[FBErrorBuilder builder] + withDescriptionFormat:@"The current Xcode SDK does not support location simulation. Consider upgrading to Xcode 14.3+/iOS 16.4+"] + buildError:error]; return NO; } if (![session supportsLocationSimulation]) { - if (error) { - [[[FBErrorBuilder builder] - withDescriptionFormat:@"Your device does not support location simulation"] - buildError:error]; - } + [[[FBErrorBuilder builder] + withDescriptionFormat:@"Your device does not support location simulation"] + buildError:error]; return NO; } + __block NSError *innerError = nil; __block BOOL didSucceed = NO; [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ [session setSimulatedLocation:location completion:^(bool result, NSError *invokeError) { - if (error) { - *error = invokeError; + if (nil != invokeError) { + innerError = invokeError; + } else { + didSucceed = result; } - didSucceed = invokeError == nil && result; completion(); }]; }]; + if (nil != innerError && error) { + *error = innerError; + } return didSucceed; } @@ -208,34 +220,33 @@ + (nullable CLLocation *)getSimulatedLocation:(NSError *__autoreleasing*)error; { XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(getSimulatedLocationWithReply:)]) { - if (error) { - [[[FBErrorBuilder builder] - withDescriptionFormat:@"The current Xcode SDK does not support location simulation. Consider upgrading to Xcode 14.3+/iOS 16.4+"] - buildError:error]; - } + [[[FBErrorBuilder builder] + withDescriptionFormat:@"The current Xcode SDK does not support location simulation. Consider upgrading to Xcode 14.3+/iOS 16.4+"] + buildError:error]; return nil; } if (![session supportsLocationSimulation]) { - if (error) { - [[[FBErrorBuilder builder] - withDescriptionFormat:@"Your device does not support location simulation"] - buildError:error]; - } + [[[FBErrorBuilder builder] + withDescriptionFormat:@"Your device does not support location simulation"] + buildError:error]; return nil; } + __block NSError *innerError = nil; __block CLLocation *location = nil; [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ [session getSimulatedLocationWithReply:^(CLLocation *reply, NSError *invokeError) { - if (error) { - *error = invokeError; - } - if (nil == invokeError) { + if (nil != invokeError) { + innerError = invokeError; + } else { location = reply; } completion(); }]; }]; + if (nil != innerError && error) { + *error = innerError; + } return location; } @@ -259,16 +270,21 @@ + (BOOL)clearSimulatedLocation:(NSError *__autoreleasing*)error return NO; } + __block NSError *innerError = nil; __block BOOL didSucceed = NO; [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ [session clearSimulatedLocationWithReply:^(bool result, NSError *invokeError) { - if (error) { - *error = invokeError; + if (nil != invokeError) { + innerError = invokeError; + } else { + didSucceed = result; } - didSucceed = invokeError == nil && result; completion(); }]; }]; + if (nil != innerError && error) { + *error = innerError; + } return didSucceed; } #endif From 4a08d7a843af6b93b378b4e3dc10f123d2e56359 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 9 Jun 2023 06:34:54 +0000 Subject: [PATCH 043/133] feat: Drop older screenshoting APIs (#721) --- WebDriverAgentLib/Utilities/FBConfiguration.h | 6 +- WebDriverAgentLib/Utilities/FBConfiguration.m | 2 +- WebDriverAgentLib/Utilities/FBImageIOScaler.h | 10 +- WebDriverAgentLib/Utilities/FBImageIOScaler.m | 13 +- WebDriverAgentLib/Utilities/FBMjpegServer.m | 15 +- WebDriverAgentLib/Utilities/FBScreenshot.h | 20 +- WebDriverAgentLib/Utilities/FBScreenshot.m | 176 ++++++------------ .../Utilities/FBUnattachedAppLauncher.m | 3 + .../IntegrationTests/FBImageIOScalerTests.m | 2 - 9 files changed, 89 insertions(+), 158 deletions(-) diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index bcb341a8d..8bb9d48ca 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -93,9 +93,9 @@ extern NSString *const FBSnapshotMaxDepthKey; + (void)setMjpegServerFramerate:(NSUInteger)framerate; /** - The quality of phone display screenshots. The higher quality you set is the bigger screenshot size is. - The highest quality value is 0 (lossless PNG). The lowest quality is 2 (highly compressed JPEG). - The default quality value is 1 (high quality JPEG). + The quality of display screenshots. The higher quality you set is the bigger screenshot size is. + The highest quality value is 0 (lossless PNG) or 3 (lossless HEIC). The lowest quality is 2 (highly compressed JPEG). + The default quality value is 3 (lossless HEIC). See https://developer.apple.com/documentation/xctest/xctimagequality?language=objc */ + (NSUInteger)screenshotQuality; diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index f99c9d148..f149d2193 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -453,7 +453,7 @@ + (void)resetSessionSettings FBShouldUseCompactResponses = YES; FBElementResponseAttributes = @"type,label"; FBMaxTypingFrequency = 60; - FBScreenshotQuality = 1; + FBScreenshotQuality = 3; FBCustomSnapshotTimeout = 15.; FBShouldUseFirstMatch = NO; FBShouldBoundElementsByIndex = NO; diff --git a/WebDriverAgentLib/Utilities/FBImageIOScaler.h b/WebDriverAgentLib/Utilities/FBImageIOScaler.h index d5801142a..476daba04 100644 --- a/WebDriverAgentLib/Utilities/FBImageIOScaler.h +++ b/WebDriverAgentLib/Utilities/FBImageIOScaler.h @@ -10,6 +10,8 @@ #import #import +@class UTType; + NS_ASSUME_NONNULL_BEGIN // Those values define the allowed ranges for the scaling factor and compression quality settings @@ -25,14 +27,12 @@ extern const CGFloat FBMaxCompressionQuality; queue it will be replaced with the new one @param image The image to scale down - @param uti Either kUTTypePNG or kUTTypeJPEG @param completionHandler called after successfully scaling down an image @param scalingFactor the scaling factor in range 0.01..1.0. A value of 1.0 won't perform scaling at all @param compressionQuality the compression quality in range 0.0..1.0 (0.0 for max. compression and 1.0 for lossless compression) - Only applicable for kUTTypeJPEG + Only applicable for UTTypeJPEG */ - (void)submitImage:(NSData *)image - uti:(NSString *)uti scalingFactor:(CGFloat)scalingFactor compressionQuality:(CGFloat)compressionQuality completionHandler:(void (^)(NSData *))completionHandler; @@ -41,7 +41,7 @@ extern const CGFloat FBMaxCompressionQuality; Scales and crops the source image @param image The source image data - @param uti Either kUTTypePNG or kUTTypeJPEG + @param uti Either UTTypePNG or UTTypeJPEG @param rect The cropping rectange for the screenshot. The value is expected to be non-scaled one since it happens after scaling/orientation change. CGRectNull could be used to take a screenshot of the full screen. @@ -52,7 +52,7 @@ extern const CGFloat FBMaxCompressionQuality; @returns Processed image data compressed according to the given UTI or nil in case of a failure */ - (nullable NSData *)scaledImageWithImage:(NSData *)image - uti:(NSString *)uti + uti:(UTType *)uti rect:(CGRect)rect scalingFactor:(CGFloat)scalingFactor compressionQuality:(CGFloat)compressionQuality diff --git a/WebDriverAgentLib/Utilities/FBImageIOScaler.m b/WebDriverAgentLib/Utilities/FBImageIOScaler.m index b0900c2c7..0ca87b747 100644 --- a/WebDriverAgentLib/Utilities/FBImageIOScaler.m +++ b/WebDriverAgentLib/Utilities/FBImageIOScaler.m @@ -11,7 +11,7 @@ #import #import -#import +@import UniformTypeIdentifiers; #import "FBConfiguration.h" #import "FBErrorBuilder.h" @@ -43,7 +43,6 @@ - (id)init } - (void)submitImage:(NSData *)image - uti:(NSString *)uti scalingFactor:(CGFloat)scalingFactor compressionQuality:(CGFloat)compressionQuality completionHandler:(void (^)(NSData *))completionHandler @@ -118,7 +117,7 @@ - (nullable NSData *)scaledJpegImageWithImage:(NSData *)image } - (nullable NSData *)scaledImageWithImage:(NSData *)image - uti:(NSString *)uti + uti:(UTType *)uti rect:(CGRect)rect scalingFactor:(CGFloat)scalingFactor compressionQuality:(CGFloat)compressionQuality @@ -154,7 +153,7 @@ - (nullable NSData *)scaledImageWithImage:(NSData *)image UIGraphicsEndImageContext(); } - return [uti isEqualToString:(__bridge id)kUTTypePNG] + return [uti conformsToType:UTTypePNG] ? UIImagePNGRepresentation(resultImage) : UIImageJPEGRepresentation(resultImage, compressionQuality); } @@ -163,7 +162,11 @@ - (nullable NSData *)jpegDataWithImage:(CGImageRef)imageRef compressionQuality:(CGFloat)compressionQuality { NSMutableData *newImageData = [NSMutableData data]; - CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((CFMutableDataRef)newImageData, kUTTypeJPEG, 1, NULL); + CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData( + (__bridge CFMutableDataRef) newImageData, + (__bridge CFStringRef) UTTypeJPEG.identifier, + 1, + NULL); CFDictionaryRef compressionOptions = (__bridge CFDictionaryRef)@{ (const NSString *)kCGImageDestinationLossyCompressionQuality: @(compressionQuality) }; diff --git a/WebDriverAgentLib/Utilities/FBMjpegServer.m b/WebDriverAgentLib/Utilities/FBMjpegServer.m index beacecc97..51fa48687 100644 --- a/WebDriverAgentLib/Utilities/FBMjpegServer.m +++ b/WebDriverAgentLib/Utilities/FBMjpegServer.m @@ -10,7 +10,7 @@ #import "FBMjpegServer.h" #import -#import +@import UniformTypeIdentifiers; #import "GCDAsyncSocket.h" #import "FBApplication.h" @@ -72,11 +72,6 @@ - (void)scheduleNextScreenshotWithInterval:(uint64_t)timerInterval timeStarted:( - (void)streamScreenshot { - if (![self.class canStreamScreenshots]) { - [FBLogger log:@"MJPEG server cannot start because the current iOS version is not supported"]; - return; - } - NSUInteger framerate = FBConfiguration.mjpegServerFramerate; uint64_t timerInterval = (uint64_t)(1.0 / ((0 == framerate || framerate > MAX_FPS) ? MAX_FPS : framerate) * NSEC_PER_SEC); uint64_t timeStarted = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW); @@ -96,7 +91,7 @@ - (void)streamScreenshot NSError *error; NSData *screenshotData = [FBScreenshot takeInOriginalResolutionWithScreenID:self.mainScreenID compressionQuality:screenshotCompressionQuality - uti:(__bridge id)kUTTypeJPEG + uti:UTTypeJPEG timeout:FRAME_TIMEOUT error:&error]; if (nil == screenshotData) { @@ -107,7 +102,6 @@ - (void)streamScreenshot if (usesScaling) { [self.imageScaler submitImage:screenshotData - uti:(__bridge id)kUTTypeJPEG scalingFactor:scalingFactor compressionQuality:compressionQuality completionHandler:^(NSData * _Nonnull scaled) { @@ -132,11 +126,6 @@ - (void)sendScreenshot:(NSData *)screenshotData { } } -+ (BOOL)canStreamScreenshots -{ - return [FBScreenshot isNewScreenshotAPISupported]; -} - - (void)didClientConnect:(GCDAsyncSocket *)newClient { [FBLogger logFmt:@"Got screenshots broadcast client connection at %@:%d", newClient.connectedHost, newClient.connectedPort]; diff --git a/WebDriverAgentLib/Utilities/FBScreenshot.h b/WebDriverAgentLib/Utilities/FBScreenshot.h index 52c6b8c29..036a5e1cb 100644 --- a/WebDriverAgentLib/Utilities/FBScreenshot.h +++ b/WebDriverAgentLib/Utilities/FBScreenshot.h @@ -8,22 +8,18 @@ */ #import +@class UTType; NS_ASSUME_NONNULL_BEGIN @interface FBScreenshot : NSObject -/** - Returns YES if the current OS SDK supports advanced screenshoting APIs (added since Xcode SDK 10) - */ -+ (BOOL)isNewScreenshotAPISupported; - /** Retrieves non-scaled screenshot of the whole screen - @param quality The number in range 0-2, where 2 (JPG) is the lowest and 0 (PNG) is the highest quality. + @param quality The number in range 0-3, where 0 is PNG (lossless), 3 is HEIC (lossless), 1- low quality JPEG and 2 - high quality JPEG @param error If there is an error, upon return contains an NSError object that describes the problem. - @return Device screenshot as PNG- or JPG-encoded data or nil in case of failure + @return Device screenshot as PNG-encoded data or nil in case of failure */ + (nullable NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality error:(NSError **)error; @@ -31,11 +27,11 @@ NS_ASSUME_NONNULL_BEGIN /** Retrieves non-scaled screenshot of the particular screen rectangle - @param quality The number in range 0-2, where 2 (JPG) is the lowest and 0 (PNG) is the highest quality. + @param quality The number in range 0-3, where 0 is PNG (lossless), 3 is HEIC (lossless), 1- low quality JPEG and 2 - high quality JPEG @param rect The bounding rectange for the screenshot. The value is expected be non-scaled one. CGRectNull could be used to take a screenshot of the full screen. @param error If there is an error, upon return contains an NSError object that describes the problem. - @return Device screenshot as PNG- or JPG-encoded data or nil in case of failure + @return Device screenshot as PNG-encoded data or nil in case of failure */ + (nullable NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality rect:(CGRect)rect @@ -46,14 +42,14 @@ NS_ASSUME_NONNULL_BEGIN @param screenID The screen identifier to take the screenshot from @param compressionQuality Normalized screenshot quality value in range 0..1, where 1 is the best quality - @param uti kUTType... constant, which defines the type of the returned screenshot image + @param uti UTType... constant, which defines the type of the returned screenshot image @param timeout how much time to allow for the screenshot to be taken @param error If there is an error, upon return contains an NSError object that describes the problem. - @return Device screenshot as PNG- or JPG-encoded data or nil in case of failure + @return Device screenshot as PNG-, HEIC- or JPG-encoded data or nil in case of failure */ + (nullable NSData *)takeInOriginalResolutionWithScreenID:(long long)screenID compressionQuality:(CGFloat)compressionQuality - uti:(NSString *)uti + uti:(UTType *)uti timeout:(NSTimeInterval)timeout error:(NSError **)error; diff --git a/WebDriverAgentLib/Utilities/FBScreenshot.m b/WebDriverAgentLib/Utilities/FBScreenshot.m index 740048e66..8cea6530d 100644 --- a/WebDriverAgentLib/Utilities/FBScreenshot.m +++ b/WebDriverAgentLib/Utilities/FBScreenshot.m @@ -9,7 +9,7 @@ #import "FBScreenshot.h" -#import +@import UniformTypeIdentifiers; #import "FBConfiguration.h" #import "FBErrorBuilder.h" @@ -33,16 +33,6 @@ @implementation FBScreenshot -+ (BOOL)isNewScreenshotAPISupported -{ - static dispatch_once_t newScreenshotAPISupported; - static BOOL result; - dispatch_once(&newScreenshotAPISupported, ^{ - result = [(NSObject *)[FBXCTestDaemonsProxy testRunnerProxy] respondsToSelector:@selector(_XCT_requestScreenshotOfScreenWithID:withRect:uti:compressionQuality:withReply:)]; - }); - return result; -} - + (CGFloat)compressionQualityWithQuality:(NSUInteger)quality { switch (quality) { @@ -55,14 +45,16 @@ + (CGFloat)compressionQualityWithQuality:(NSUInteger)quality } } -+ (NSString *)imageUtiWithQuality:(NSUInteger)quality ++ (UTType *)imageUtiWithQuality:(NSUInteger)quality { switch (quality) { case 1: case 2: - return (__bridge id)kUTTypeJPEG; + return UTTypeJPEG; + case 3: + return UTTypeHEIC; default: - return (__bridge id)kUTTypePNG; + return UTTypePNG; } } @@ -70,64 +62,28 @@ + (NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality rect:(CGRect)rect error:(NSError **)error { - if ([self.class isNewScreenshotAPISupported]) { - XCUIScreen *mainScreen = XCUIScreen.mainScreen; - return [self.class takeWithScreenID:mainScreen.displayID - scale:SCREENSHOT_SCALE - compressionQuality:[self.class compressionQualityWithQuality:FBConfiguration.screenshotQuality] - rect:rect - sourceUTI:[self.class imageUtiWithQuality:FBConfiguration.screenshotQuality] - error:error]; - } - - [[[FBErrorBuilder builder] - withDescription:@"Screenshots of limited areas are only available for newer OS versions"] - buildError:error]; - return nil; + XCUIScreen *mainScreen = XCUIScreen.mainScreen; + return [self.class takeWithScreenID:mainScreen.displayID + scale:SCREENSHOT_SCALE + compressionQuality:[self.class compressionQualityWithQuality:quality] + rect:rect + sourceUTI:[self.class imageUtiWithQuality:quality] + error:error]; } + (NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality error:(NSError **)error { - if ([self.class isNewScreenshotAPISupported]) { - XCUIScreen *mainScreen = XCUIScreen.mainScreen; - return [self.class takeWithScreenID:mainScreen.displayID - scale:SCREENSHOT_SCALE - compressionQuality:[self.class compressionQualityWithQuality:FBConfiguration.screenshotQuality] - rect:CGRectNull - sourceUTI:[self.class imageUtiWithQuality:FBConfiguration.screenshotQuality] - error:error]; - } - - id proxy = [FBXCTestDaemonsProxy testRunnerProxy]; - __block NSData *screenshotData = nil; - __block NSError *innerError = nil; - dispatch_semaphore_t sem = dispatch_semaphore_create(0); - [proxy _XCT_requestScreenshotWithReply:^(NSData *data, NSError *screenshotError) { - if (nil == screenshotError) { - screenshotData = data; - } else { - innerError = screenshotError; - } - dispatch_semaphore_signal(sem); - }]; - if (nil != innerError && error) { - *error = innerError; - } - int64_t timeoutNs = (int64_t)(SCREENSHOT_TIMEOUT * NSEC_PER_SEC); - if (0 != dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, timeoutNs))) { - [[[FBErrorBuilder builder] - withDescription:[NSString stringWithFormat:@"Cannot take a screenshot within %@ timeout", formatTimeInterval(SCREENSHOT_TIMEOUT)]] - buildError:error]; - }; - return screenshotData; + return [self.class takeInOriginalResolutionWithQuality:quality + rect:CGRectNull + error:error]; } + (NSData *)takeWithScreenID:(long long)screenID scale:(CGFloat)scale compressionQuality:(CGFloat)compressionQuality rect:(CGRect)rect - sourceUTI:(NSString *)uti + sourceUTI:(UTType *)uti error:(NSError **)error { NSData *screenshotData = [self.class takeInOriginalResolutionWithScreenID:screenID @@ -139,7 +95,7 @@ + (NSData *)takeWithScreenID:(long long)screenID return nil; } return [[[FBImageIOScaler alloc] init] scaledImageWithImage:screenshotData - uti:(__bridge id)kUTTypePNG + uti:UTTypePNG rect:rect scalingFactor:1.0 / scale compressionQuality:FBMaxCompressionQuality @@ -148,7 +104,7 @@ + (NSData *)takeWithScreenID:(long long)screenID + (NSData *)takeInOriginalResolutionWithScreenID:(long long)screenID compressionQuality:(CGFloat)compressionQuality - uti:(NSString *)uti + uti:(UTType *)uti timeout:(NSTimeInterval)timeout error:(NSError **)error { @@ -156,38 +112,23 @@ + (NSData *)takeInOriginalResolutionWithScreenID:(long long)screenID __block NSData *screenshotData = nil; __block NSError *innerError = nil; dispatch_semaphore_t sem = dispatch_semaphore_create(0); - if ([self.class shouldUseScreenshotRequestApiForProxy:(NSObject *)proxy]) { - id screnshotRequest = [self.class screenshotRequestWithScreenID:screenID - rect:CGRectNull - uti:uti - compressionQuality:compressionQuality - error:error]; - if (nil == screnshotRequest) { - return nil; - } - [proxy _XCT_requestScreenshot:screnshotRequest - withReply:^(id image, NSError *err) { - if (nil != err) { - innerError = err; - } else { - screenshotData = [image data]; - } - dispatch_semaphore_signal(sem); - }]; - } else { - [proxy _XCT_requestScreenshotOfScreenWithID:screenID - withRect:CGRectNull - uti:uti - compressionQuality:compressionQuality - withReply:^(NSData *data, NSError *err) { - if (nil != err) { - innerError = err; - } else { - screenshotData = data; - } - dispatch_semaphore_signal(sem); - }]; + id screnshotRequest = [self.class screenshotRequestWithScreenID:screenID + rect:CGRectNull + uti:uti + compressionQuality:compressionQuality + error:error]; + if (nil == screnshotRequest) { + return nil; } + [proxy _XCT_requestScreenshot:screnshotRequest + withReply:^(id image, NSError *err) { + if (nil != err) { + innerError = err; + } else { + screenshotData = [image data]; + } + dispatch_semaphore_signal(sem); + }]; int64_t timeoutNs = (int64_t)(timeout * NSEC_PER_SEC); if (0 != dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, timeoutNs))) { NSString *timeoutMsg = [NSString stringWithFormat:@"Cannot take a screenshot within %@ timeout", formatTimeInterval(SCREENSHOT_TIMEOUT)]; @@ -205,26 +146,7 @@ + (NSData *)takeInOriginalResolutionWithScreenID:(long long)screenID return screenshotData; } -+ (BOOL)shouldUseScreenshotRequestApiForProxy:(NSObject *)proxy -{ - static dispatch_once_t shouldUseSRApi; - static BOOL result; - dispatch_once(&shouldUseSRApi, ^{ - if ([proxy respondsToSelector:@selector(_XCT_requestScreenshot:withReply:)]) { -#if TARGET_OS_SIMULATOR - // Required to support simulators running iOS 14.4 and below with Xcode 12.5 and above due to unsupported API on the simulator side. - result = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"14.5"); -#else - result = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0"); -#endif - } else { - result = NO; - } - }); - return result; -} - -+ (nullable id)imageEncodingWithUniformTypeIdentifier:(NSString *)uti ++ (nullable id)imageEncodingWithUniformTypeIdentifier:(UTType *)uti compressionQuality:(CGFloat)compressionQuality error:(NSError **)error { @@ -235,6 +157,26 @@ + (nullable id)imageEncodingWithUniformTypeIdentifier:(NSString *)uti buildError:error]; return nil; } + + if ([uti conformsToType:UTTypeHEIC]) { + static BOOL isHeicSuppported = NO; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + SEL selector = NSSelectorFromString(@"supportsHEICImageEncoding"); + NSMethodSignature *signature = [imageEncodingClass methodSignatureForSelector:selector]; + if (nil != signature) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:selector]; + [invocation invokeWithTarget:imageEncodingClass]; + [invocation getReturnValue:&isHeicSuppported]; + } + }); + if (!isHeicSuppported) { + [FBLogger logFmt:@"The device under test does not support HEIC image encoding. Falling back to PNG"]; + uti = UTTypePNG; + } + } + id imageEncodingAllocated = [imageEncodingClass alloc]; SEL imageEncodingConstructorSelector = NSSelectorFromString(@"initWithUniformTypeIdentifier:compressionQuality:"); if (![imageEncodingAllocated respondsToSelector:imageEncodingConstructorSelector]) { @@ -246,7 +188,8 @@ + (nullable id)imageEncodingWithUniformTypeIdentifier:(NSString *)uti NSMethodSignature *imageEncodingContructorSignature = [imageEncodingAllocated methodSignatureForSelector:imageEncodingConstructorSelector]; NSInvocation *imageEncodingInitInvocation = [NSInvocation invocationWithMethodSignature:imageEncodingContructorSignature]; [imageEncodingInitInvocation setSelector:imageEncodingConstructorSelector]; - [imageEncodingInitInvocation setArgument:&uti atIndex:2]; + NSString *utiIdentifier = uti.identifier; + [imageEncodingInitInvocation setArgument:&utiIdentifier atIndex:2]; [imageEncodingInitInvocation setArgument:&compressionQuality atIndex:3]; [imageEncodingInitInvocation invokeWithTarget:imageEncodingAllocated]; id __unsafe_unretained imageEncoding; @@ -256,11 +199,10 @@ + (nullable id)imageEncodingWithUniformTypeIdentifier:(NSString *)uti + (nullable id)screenshotRequestWithScreenID:(long long)screenID rect:(struct CGRect)rect - uti:(NSString *)uti + uti:(UTType *)uti compressionQuality:(CGFloat)compressionQuality error:(NSError **)error { - // TODO: Use native accessors after we drop the support of Xcode 12.4 and below id imageEncoding = [self.class imageEncodingWithUniformTypeIdentifier:uti compressionQuality:compressionQuality error:error]; diff --git a/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m b/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m index 40b2278ab..f877b67c6 100644 --- a/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m +++ b/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m @@ -8,6 +8,9 @@ */ #import "FBUnattachedAppLauncher.h" + +#import + #import "LSApplicationWorkspace.h" @implementation FBUnattachedAppLauncher diff --git a/WebDriverAgentTests/IntegrationTests/FBImageIOScalerTests.m b/WebDriverAgentTests/IntegrationTests/FBImageIOScalerTests.m index 491e2cfd2..0c2f75b62 100644 --- a/WebDriverAgentTests/IntegrationTests/FBImageIOScalerTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBImageIOScalerTests.m @@ -8,7 +8,6 @@ */ #import -#import #import "FBImageIOScaler.h" #import "FBIntegrationTestCase.h" @@ -55,7 +54,6 @@ - (void)scaleImageWithFactor:(CGFloat)scalingFactor expectedSize:(CGSize)excpect id expScaled = [self expectationWithDescription:@"Receive scaled image"]; [scaler submitImage:self.originalImage - uti:(__bridge id)kUTTypeJPEG scalingFactor:scalingFactor compressionQuality:1.0 completionHandler:^(NSData *scaled) { From 4ac4f0b924cf63a106698b211709d66b51a25fe8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 9 Jun 2023 07:05:51 +0000 Subject: [PATCH 044/133] chore(release): 5.4.0 [skip ci] ## [5.4.0](https://github.com/appium/WebDriverAgent/compare/v5.3.3...v5.4.0) (2023-06-09) ### Features * Drop older screenshoting APIs ([#721](https://github.com/appium/WebDriverAgent/issues/721)) ([4a08d7a](https://github.com/appium/WebDriverAgent/commit/4a08d7a843af6b93b378b4e3dc10f123d2e56359)) ### Bug Fixes * Streamline errors handling for async block calls ([#725](https://github.com/appium/WebDriverAgent/issues/725)) ([364b779](https://github.com/appium/WebDriverAgent/commit/364b7791393ffae9c048c5cac023e3e7d1813a14)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdbe0c6ed..f28b44262 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [5.4.0](https://github.com/appium/WebDriverAgent/compare/v5.3.3...v5.4.0) (2023-06-09) + + +### Features + +* Drop older screenshoting APIs ([#721](https://github.com/appium/WebDriverAgent/issues/721)) ([4a08d7a](https://github.com/appium/WebDriverAgent/commit/4a08d7a843af6b93b378b4e3dc10f123d2e56359)) + + +### Bug Fixes + +* Streamline errors handling for async block calls ([#725](https://github.com/appium/WebDriverAgent/issues/725)) ([364b779](https://github.com/appium/WebDriverAgent/commit/364b7791393ffae9c048c5cac023e3e7d1813a14)) + ## [5.3.3](https://github.com/appium/WebDriverAgent/compare/v5.3.2...v5.3.3) (2023-06-08) diff --git a/package.json b/package.json index 0b530ba41..03ad37773 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.3.3", + "version": "5.4.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From e6e2dbd86fc0c48ae146905f0e69a6223360e856 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 9 Jun 2023 17:24:27 +0000 Subject: [PATCH 045/133] fix: Return default testmanagerd version if the info is not available (#728) --- .../Utilities/FBXCodeCompatibility.m | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m index 911c5ec85..4d7bb621d 100644 --- a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +++ b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m @@ -123,12 +123,16 @@ NSInteger FBTestmanagerdVersion(void) static NSInteger testmanagerdVersion; dispatch_once(&getTestmanagerdVersion, ^{ id proxy = [FBXCTestDaemonsProxy testRunnerProxy]; - dispatch_semaphore_t sem = dispatch_semaphore_create(0); - [proxy _XCT_exchangeProtocolVersion:testmanagerdVersion reply:^(unsigned long long code) { - testmanagerdVersion = (NSInteger) code; - dispatch_semaphore_signal(sem); - }]; - dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC))); + if ([(NSObject *)proxy respondsToSelector:@selector(_XCT_exchangeProtocolVersion:reply:)]) { + [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ + [proxy _XCT_exchangeProtocolVersion:testmanagerdVersion reply:^(unsigned long long code) { + testmanagerdVersion = (NSInteger) code; + completion(); + }]; + }]; + } else { + testmanagerdVersion = 0xFFFF; + } }); return testmanagerdVersion; } From 6c6b4cfa903bee15ee12a1e96a6c5a2fef74a4fa Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 9 Jun 2023 17:33:23 +0000 Subject: [PATCH 046/133] chore(release): 5.4.1 [skip ci] ## [5.4.1](https://github.com/appium/WebDriverAgent/compare/v5.4.0...v5.4.1) (2023-06-09) ### Bug Fixes * Return default testmanagerd version if the info is not available ([#728](https://github.com/appium/WebDriverAgent/issues/728)) ([e6e2dbd](https://github.com/appium/WebDriverAgent/commit/e6e2dbd86fc0c48ae146905f0e69a6223360e856)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f28b44262..260bb8b6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.4.1](https://github.com/appium/WebDriverAgent/compare/v5.4.0...v5.4.1) (2023-06-09) + + +### Bug Fixes + +* Return default testmanagerd version if the info is not available ([#728](https://github.com/appium/WebDriverAgent/issues/728)) ([e6e2dbd](https://github.com/appium/WebDriverAgent/commit/e6e2dbd86fc0c48ae146905f0e69a6223360e856)) + ## [5.4.0](https://github.com/appium/WebDriverAgent/compare/v5.3.3...v5.4.0) (2023-06-09) diff --git a/package.json b/package.json index 03ad37773..eb2f087da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.4.0", + "version": "5.4.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 78321dd3dafdb142eed136b48ec101f1daed50a4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 12 Jun 2023 20:01:13 +0000 Subject: [PATCH 047/133] feat: Add accessibility audit extension (#727) --- .../Categories/XCUIApplication+FBHelpers.h | 20 ++++ .../Categories/XCUIApplication+FBHelpers.m | 104 ++++++++++++++++++ WebDriverAgentLib/Commands/FBCustomCommands.m | 20 ++++ WebDriverAgentLib/FBApplication.m | 1 + .../XCUIApplicationHelperTests.m | 21 ++++ 5 files changed, 166 insertions(+) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h index 9d190a381..13fabcf88 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h @@ -103,6 +103,26 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames error:(NSError **)error; +/** + A wrapper over https://developer.apple.com/documentation/xctest/xcuiapplication/4190847-performaccessibilityauditwithaud?language=objc + + @param auditTypes Combination of https://developer.apple.com/documentation/xctest/xcuiaccessibilityaudittype?language=objc + @param error If there is an error, upon return contains an NSError object that describes the problem. + @return List of found issues or nil if there was a failure + */ +- (nullable NSArray *> *)fb_performAccessibilityAuditWithAuditTypesSet:(NSSet *)auditTypes + error:(NSError **)error; + +/** + A wrapper over https://developer.apple.com/documentation/xctest/xcuiapplication/4190847-performaccessibilityauditwithaud?language=objc + + @param auditTypes Combination of https://developer.apple.com/documentation/xctest/xcuiaccessibilityaudittype?language=objc + @param error If there is an error, upon return contains an NSError object that describes the problem. + @return List of found issues or nil if there was a failure + */ +- (nullable NSArray *> *)fb_performAccessibilityAuditWithAuditTypes:(uint64_t)auditTypes + error:(NSError **)error; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index ec752c5a0..7c9ff9967 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -12,6 +12,7 @@ #import "FBElementTypeTransformer.h" #import "FBKeyboard.h" #import "FBLogger.h" +#import "FBExceptions.h" #import "FBMacros.h" #import "FBMathUtils.h" #import "FBActiveAppDetectionPoint.h" @@ -33,6 +34,54 @@ static NSString* const FBUnknownBundleId = @"unknown"; +_Nullable id extractIssueProperty(id issue, NSString *propertyName) { + SEL selector = NSSelectorFromString(propertyName); + NSMethodSignature *methodSignature = [issue methodSignatureForSelector:selector]; + if (nil == methodSignature) { + return nil; + } + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation invokeWithTarget:issue]; + id __unsafe_unretained result; + [invocation getReturnValue:&result]; + return result; +} + +NSDictionary *auditTypeNamesToValues(void) { + static dispatch_once_t onceToken; + static NSDictionary *result; + dispatch_once(&onceToken, ^{ + // https://developer.apple.com/documentation/xctest/xcuiaccessibilityaudittype?language=objc + result = @{ + @"XCUIAccessibilityAuditTypeAction": @(1UL << 32), + @"XCUIAccessibilityAuditTypeAll": @(~0UL), + @"XCUIAccessibilityAuditTypeContrast": @(1UL << 0), + @"XCUIAccessibilityAuditTypeDynamicType": @(1UL << 16), + @"XCUIAccessibilityAuditTypeElementDetection": @(1UL << 1), + @"XCUIAccessibilityAuditTypeHitRegion": @(1UL << 2), + @"XCUIAccessibilityAuditTypeParentChild": @(1UL << 33), + @"XCUIAccessibilityAuditTypeSufficientElementDescription": @(1UL << 3), + @"XCUIAccessibilityAuditTypeTextClipped": @(1UL << 17), + @"XCUIAccessibilityAuditTypeTrait": @(1UL << 18), + }; + }); + return result; +} + +NSDictionary *auditTypeValuesToNames(void) { + static dispatch_once_t onceToken; + static NSDictionary *result; + dispatch_once(&onceToken, ^{ + NSMutableDictionary *inverted = [NSMutableDictionary new]; + [auditTypeNamesToValues() enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSNumber *value, BOOL *stop) { + inverted[value] = key; + }]; + result = inverted.copy; + }); + return result; +} + @implementation XCUIApplication (FBHelpers) @@ -281,4 +330,59 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames error:error]; } +- (NSArray *> *)fb_performAccessibilityAuditWithAuditTypesSet:(NSSet *)auditTypes + error:(NSError **)error; +{ + uint64_t numTypes = 0; + NSDictionary *namesMap = auditTypeNamesToValues(); + for (NSString *value in auditTypes) { + NSNumber *typeValue = namesMap[value]; + if (nil == typeValue) { + NSString *reason = [NSString stringWithFormat:@"Audit type value '%@' is not known. Only the following audit types are supported: %@", value, namesMap.allKeys]; + @throw [NSException exceptionWithName:FBInvalidArgumentException reason:reason userInfo:@{}]; + } + numTypes |= [typeValue unsignedLongLongValue]; + } + return [self fb_performAccessibilityAuditWithAuditTypes:numTypes error:error]; +} + +- (NSArray *> *)fb_performAccessibilityAuditWithAuditTypes:(uint64_t)auditTypes + error:(NSError **)error; +{ + SEL selector = NSSelectorFromString(@"performAccessibilityAuditWithAuditTypes:issueHandler:error:"); + if (![self respondsToSelector:selector]) { + [[[FBErrorBuilder alloc] + withDescription:@"Accessibility audit is only supported since iOS 17/Xcode 15"] + buildError:error]; + return nil; + } + + NSMutableArray *resultArray = [NSMutableArray array]; + NSMethodSignature *methodSignature = [self methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setArgument:&auditTypes atIndex:2]; + BOOL (^issueHandler)(id) = ^BOOL(id issue) { + NSString *auditType = @""; + NSDictionary *valuesToNamesMap = auditTypeValuesToNames(); + NSNumber *auditTypeValue = [issue valueForKey:@"auditType"]; + if (nil != auditTypeValue) { + auditType = valuesToNamesMap[auditTypeValue] ?: [auditTypeValue stringValue]; + } + [resultArray addObject:@{ + @"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"", + @"compactDescription": extractIssueProperty(issue, @"compactDescription") ?: @"", + @"auditType": auditType, + @"element": [extractIssueProperty(issue, @"element") description] ?: @"", + }]; + return YES; + }; + [invocation setArgument:&issueHandler atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invokeWithTarget:self]; + BOOL isSuccessful; + [invocation getReturnValue:&isSuccessful]; + return isSuccessful ? resultArray.copy : nil; +} + @end diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index c2cde607e..9d8e324d7 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -58,6 +58,7 @@ + (NSArray *)routes [[FBRoute GET:@"/wda/batteryInfo"] respondWithTarget:self action:@selector(handleGetBatteryInfo:)], #endif [[FBRoute POST:@"/wda/pressButton"] respondWithTarget:self action:@selector(handlePressButtonCommand:)], + [[FBRoute POST:@"/wda/performAccessibilityAudit"] respondWithTarget:self action:@selector(handlePerformAccessibilityAudit:)], [[FBRoute POST:@"/wda/performIoHidEvent"] respondWithTarget:self action:@selector(handlePeformIOHIDEvent:)], [[FBRoute POST:@"/wda/expectNotification"] respondWithTarget:self action:@selector(handleExpectNotification:)], [[FBRoute POST:@"/wda/siri/activate"] respondWithTarget:self action:@selector(handleActivateSiri:)], @@ -544,4 +545,23 @@ + (NSString *)timeZone } #endif ++ (id)handlePerformAccessibilityAudit:(FBRouteRequest *)request +{ + NSError *error; + NSArray *requestedTypes = request.arguments[@"auditTypes"]; + NSMutableSet *typesSet = [NSMutableSet set]; + if (nil == requestedTypes || 0 == [requestedTypes count]) { + [typesSet addObject:@"XCUIAccessibilityAuditTypeAll"]; + } else { + [typesSet addObjectsFromArray:requestedTypes]; + } + NSArray *result = [request.session.activeApplication fb_performAccessibilityAuditWithAuditTypesSet:typesSet.copy + error:&error]; + if (nil == result) { + return FBResponseWithStatus([FBCommandStatus unknownErrorWithMessage:error.description + traceback:nil]); + } + return FBResponseWithObject(result); +} + @end diff --git a/WebDriverAgentLib/FBApplication.m b/WebDriverAgentLib/FBApplication.m index 8a9a48ba0..fe46393fb 100644 --- a/WebDriverAgentLib/FBApplication.m +++ b/WebDriverAgentLib/FBApplication.m @@ -11,6 +11,7 @@ #import "FBXCAccessibilityElement.h" #import "FBLogger.h" +#import "FBExceptions.h" #import "FBRunLoopSpinner.h" #import "FBMacros.h" #import "FBActiveAppDetectionPoint.h" diff --git a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m index 8a7d47ae7..41ee134a1 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m @@ -14,6 +14,7 @@ #import "FBApplication.h" #import "FBIntegrationTestCase.h" #import "FBElement.h" +#import "FBMacros.h" #import "FBTestMacros.h" #import "XCUIApplication+FBHelpers.h" #import "XCUIElement+FBIsVisible.h" @@ -94,4 +95,24 @@ - (void)testTestmanagerdVersion XCTAssertGreaterThan(FBTestmanagerdVersion(), 0); } +- (void)testAccessbilityAudit +{ + if (SYSTEM_VERSION_LESS_THAN(@"17.0")) { + return; + } + + NSError *error; + NSArray *auditIssues1 = [FBApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypes:~0UL + error:&error]; + XCTAssertNotNil(auditIssues1); + XCTAssertNil(error); + + NSMutableSet *set = [NSMutableSet new]; + [set addObject:@"XCUIAccessibilityAuditTypeAll"]; + NSArray *auditIssues2 = [FBApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypesSet:set.copy + error:&error]; + XCTAssertEqualObjects(auditIssues1, auditIssues2); + XCTAssertNil(error); +} + @end From 96010a6a3ea8a70a6f4ef8fbb9e8e540ffa6e640 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 12 Jun 2023 20:11:50 +0000 Subject: [PATCH 048/133] chore(release): 5.5.0 [skip ci] ## [5.5.0](https://github.com/appium/WebDriverAgent/compare/v5.4.1...v5.5.0) (2023-06-12) ### Features * Add accessibility audit extension ([#727](https://github.com/appium/WebDriverAgent/issues/727)) ([78321dd](https://github.com/appium/WebDriverAgent/commit/78321dd3dafdb142eed136b48ec101f1daed50a4)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 260bb8b6e..e8b2f6035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.5.0](https://github.com/appium/WebDriverAgent/compare/v5.4.1...v5.5.0) (2023-06-12) + + +### Features + +* Add accessibility audit extension ([#727](https://github.com/appium/WebDriverAgent/issues/727)) ([78321dd](https://github.com/appium/WebDriverAgent/commit/78321dd3dafdb142eed136b48ec101f1daed50a4)) + ## [5.4.1](https://github.com/appium/WebDriverAgent/compare/v5.4.0...v5.4.1) (2023-06-09) diff --git a/package.json b/package.json index eb2f087da..a0b52f566 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.4.1", + "version": "5.5.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 49770328aeeebacd76011ff1caf13d5b4ed71420 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 16 Jun 2023 09:42:28 +0200 Subject: [PATCH 049/133] fix: Update strongbox API name --- lib/webdriveragent.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 350353ed2..4c52e91d6 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -240,7 +240,7 @@ class WebDriverAgent { // TODO: hovewer it should do the job as a temporary transition trick // TODO: to switch from a hardcoded file path to the strongbox usage. try { - boxItem = await box.createItemWithContents(RECENT_MODULE_VERSION_ITEM_NAME, '5.0.0'); + boxItem = await box.createItemWithValue(RECENT_MODULE_VERSION_ITEM_NAME, '5.0.0'); } catch (e) { this.log.warn(`The actual module version cannot be persisted: ${e.message}`); return; @@ -248,7 +248,7 @@ class WebDriverAgent { } else { this.log.info('There is no need to perform the project cleanup. A fresh install has been detected'); try { - await box.createItemWithContents(RECENT_MODULE_VERSION_ITEM_NAME, packageInfo.version); + await box.createItemWithValue(RECENT_MODULE_VERSION_ITEM_NAME, packageInfo.version); } catch (e) { this.log.warn(`The actual module version cannot be persisted: ${e.message}`); } From c4853da316f3b8da8520de38f07b9388413a9f8a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 16 Jun 2023 07:51:04 +0000 Subject: [PATCH 050/133] chore(release): 5.5.1 [skip ci] ## [5.5.1](https://github.com/appium/WebDriverAgent/compare/v5.5.0...v5.5.1) (2023-06-16) ### Bug Fixes * Update strongbox API name ([4977032](https://github.com/appium/WebDriverAgent/commit/49770328aeeebacd76011ff1caf13d5b4ed71420)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8b2f6035..9a6d4b57d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.5.1](https://github.com/appium/WebDriverAgent/compare/v5.5.0...v5.5.1) (2023-06-16) + + +### Bug Fixes + +* Update strongbox API name ([4977032](https://github.com/appium/WebDriverAgent/commit/49770328aeeebacd76011ff1caf13d5b4ed71420)) + ## [5.5.0](https://github.com/appium/WebDriverAgent/compare/v5.4.1...v5.5.0) (2023-06-12) diff --git a/package.json b/package.json index a0b52f566..2b67f5207 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.5.0", + "version": "5.5.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 15614d030975f2b1eac5919d2353bc015f194d4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 06:58:52 +0200 Subject: [PATCH 051/133] chore(deps-dev): bump prettier from 2.8.8 to 3.0.0 (#735) Bumps [prettier](https://github.com/prettier/prettier) from 2.8.8 to 3.0.0. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.8.8...3.0.0) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b67f5207..153ed2db9 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "lint-staged": "^13.0.3", "mocha": "^10.0.0", "pre-commit": "^1.2.2", - "prettier": "^2.7.1", + "prettier": "^3.0.0", "semantic-release": "^20.0.2", "sinon": "^15.0.0" }, From 2c24c9db7329e644c97a8a27bd99959b1196772f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 7 Jul 2023 05:07:35 +0000 Subject: [PATCH 052/133] chore(release): 5.5.2 [skip ci] ## [5.5.2](https://github.com/appium/WebDriverAgent/compare/v5.5.1...v5.5.2) (2023-07-07) ### Miscellaneous Chores * **deps-dev:** bump prettier from 2.8.8 to 3.0.0 ([#735](https://github.com/appium/WebDriverAgent/issues/735)) ([15614d0](https://github.com/appium/WebDriverAgent/commit/15614d030975f2b1eac5919d2353bc015f194d4c)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a6d4b57d..dd046b302 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.5.2](https://github.com/appium/WebDriverAgent/compare/v5.5.1...v5.5.2) (2023-07-07) + + +### Miscellaneous Chores + +* **deps-dev:** bump prettier from 2.8.8 to 3.0.0 ([#735](https://github.com/appium/WebDriverAgent/issues/735)) ([15614d0](https://github.com/appium/WebDriverAgent/commit/15614d030975f2b1eac5919d2353bc015f194d4c)) + ## [5.5.1](https://github.com/appium/WebDriverAgent/compare/v5.5.0...v5.5.1) (2023-06-16) diff --git a/package.json b/package.json index 153ed2db9..97737b0a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.5.1", + "version": "5.5.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 239f04436a4cfbbd7c05935331cead63f699f5c0 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 15 Jul 2023 10:21:09 -0700 Subject: [PATCH 053/133] apply shouldWaitForQuiescence for activate in /wda/apps/launch (#739) --- WebDriverAgentLib/Routing/FBSession.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index 88d4385f9..69d0fff78 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -178,13 +178,13 @@ - (FBApplication *)launchApplicationWithBundleId:(NSString *)bundleIdentifier environment:(nullable NSDictionary *)environment { FBApplication *app = [[FBApplication alloc] initWithBundleIdentifier:bundleIdentifier]; + if (nil == shouldWaitForQuiescence) { + // Iherit the quiescence check setting from the main app under test by default + app.fb_shouldWaitForQuiescence = nil != self.testedApplicationBundleId && self.shouldAppsWaitForQuiescence; + } else { + app.fb_shouldWaitForQuiescence = [shouldWaitForQuiescence boolValue]; + } if (app.fb_state < 2) { - if (nil == shouldWaitForQuiescence) { - // Iherit the quiescence check setting from the main app under test by default - app.fb_shouldWaitForQuiescence = nil != self.testedApplicationBundleId && self.shouldAppsWaitForQuiescence; - } else { - app.fb_shouldWaitForQuiescence = [shouldWaitForQuiescence boolValue]; - } app.launchArguments = arguments ?: @[]; app.launchEnvironment = environment ?: @{}; [app launch]; From 66ab695f9fa1850145a1d94ef15978b70bc1b032 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 15 Jul 2023 10:50:57 -0700 Subject: [PATCH 054/133] feat: apply shouldWaitForQuiescence for activate in /wda/apps/launch (#739) (#740) This PR is a dummy to release https://github.com/appium/WebDriverAgent/pull/739 The merge via mobile app did not apply expected commit message.. From c204c73081ed210399427917ab43056c07f6f491 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 15 Jul 2023 18:01:46 +0000 Subject: [PATCH 055/133] chore(release): 5.6.0 [skip ci] ## [5.6.0](https://github.com/appium/WebDriverAgent/compare/v5.5.2...v5.6.0) (2023-07-15) ### Features * apply shouldWaitForQuiescence for activate in /wda/apps/launch ([#739](https://github.com/appium/WebDriverAgent/issues/739)) ([#740](https://github.com/appium/WebDriverAgent/issues/740)) ([66ab695](https://github.com/appium/WebDriverAgent/commit/66ab695f9fa1850145a1d94ef15978b70bc1b032)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd046b302..89bea69e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.6.0](https://github.com/appium/WebDriverAgent/compare/v5.5.2...v5.6.0) (2023-07-15) + + +### Features + +* apply shouldWaitForQuiescence for activate in /wda/apps/launch ([#739](https://github.com/appium/WebDriverAgent/issues/739)) ([#740](https://github.com/appium/WebDriverAgent/issues/740)) ([66ab695](https://github.com/appium/WebDriverAgent/commit/66ab695f9fa1850145a1d94ef15978b70bc1b032)) + ## [5.5.2](https://github.com/appium/WebDriverAgent/compare/v5.5.1...v5.5.2) (2023-07-07) diff --git a/package.json b/package.json index 97737b0a9..41c1d1083 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.5.2", + "version": "5.6.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 0b74bf5befaa6d87c93a5306beb690a5a0e1843d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:45:20 +0200 Subject: [PATCH 056/133] chore(deps-dev): bump lint-staged from 13.3.0 to 14.0.0 (#750) Bumps [lint-staged](https://github.com/okonet/lint-staged) from 13.3.0 to 14.0.0. - [Release notes](https://github.com/okonet/lint-staged/releases) - [Commits](https://github.com/okonet/lint-staged/compare/v13.3.0...v14.0.0) --- updated-dependencies: - dependency-name: lint-staged dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 41c1d1083..7fc4d6308 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-mocha": "^9.0.0", "eslint-plugin-promise": "^6.0.0", - "lint-staged": "^13.0.3", + "lint-staged": "^14.0.0", "mocha": "^10.0.0", "pre-commit": "^1.2.2", "prettier": "^3.0.0", From 2aee273ceda6ca86fcdaa57bb3067462a79e171b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 14 Aug 2023 18:59:54 +0000 Subject: [PATCH 057/133] chore(release): 5.6.1 [skip ci] ## [5.6.1](https://github.com/appium/WebDriverAgent/compare/v5.6.0...v5.6.1) (2023-08-14) ### Miscellaneous Chores * **deps-dev:** bump lint-staged from 13.3.0 to 14.0.0 ([#750](https://github.com/appium/WebDriverAgent/issues/750)) ([0b74bf5](https://github.com/appium/WebDriverAgent/commit/0b74bf5befaa6d87c93a5306beb690a5a0e1843d)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89bea69e8..c1bedbf5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.6.1](https://github.com/appium/WebDriverAgent/compare/v5.6.0...v5.6.1) (2023-08-14) + + +### Miscellaneous Chores + +* **deps-dev:** bump lint-staged from 13.3.0 to 14.0.0 ([#750](https://github.com/appium/WebDriverAgent/issues/750)) ([0b74bf5](https://github.com/appium/WebDriverAgent/commit/0b74bf5befaa6d87c93a5306beb690a5a0e1843d)) + ## [5.6.0](https://github.com/appium/WebDriverAgent/compare/v5.5.2...v5.6.0) (2023-07-15) diff --git a/package.json b/package.json index 7fc4d6308..c2d271130 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.6.0", + "version": "5.6.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From ee7655e0a2aa39dd1f0c6d80d89065b4f34f264d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 23 Aug 2023 19:28:20 +0200 Subject: [PATCH 058/133] chore: Remove unused glob dependency --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index c2d271130..f3cee7cd7 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,6 @@ "conventional-changelog-conventionalcommits": "^6.0.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.5.0", - "glob": "^8.0.1", "eslint-plugin-import": "^2.26.0", "eslint-plugin-mocha": "^9.0.0", "eslint-plugin-promise": "^6.0.0", From f6978872e7eafe4e77c41f332177a64e9f1e1c84 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 23 Aug 2023 19:09:10 +0000 Subject: [PATCH 059/133] chore(release): 5.6.2 [skip ci] ## [5.6.2](https://github.com/appium/WebDriverAgent/compare/v5.6.1...v5.6.2) (2023-08-23) ### Miscellaneous Chores * Remove unused glob dependency ([ee7655e](https://github.com/appium/WebDriverAgent/commit/ee7655e0a2aa39dd1f0c6d80d89065b4f34f264d)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1bedbf5c..6650bf5a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.6.2](https://github.com/appium/WebDriverAgent/compare/v5.6.1...v5.6.2) (2023-08-23) + + +### Miscellaneous Chores + +* Remove unused glob dependency ([ee7655e](https://github.com/appium/WebDriverAgent/commit/ee7655e0a2aa39dd1f0c6d80d89065b4f34f264d)) + ## [5.6.1](https://github.com/appium/WebDriverAgent/compare/v5.6.0...v5.6.1) (2023-08-14) diff --git a/package.json b/package.json index f3cee7cd7..f69d650d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.6.1", + "version": "5.6.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 76a4c7f066e1895acbb153ab035d6a08604277e4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 24 Aug 2023 07:36:00 +0200 Subject: [PATCH 060/133] feat: Switch babel to typescript (#753) --- .eslintrc.json | 24 ++++++++++++-- .github/workflows/functional-test.yml | 7 ++++ .mocharc.js | 2 +- babel.config.json | 25 --------------- lib/check-dependencies.js | 7 ++-- lib/utils.js | 17 ++++++---- lib/webdriveragent.js | 23 ++++++++------ lib/xcodebuild.js | 46 +++++++++++++++++++++++---- package.json | 44 +++++++++++++++---------- tsconfig.json | 14 ++++++++ 10 files changed, 136 insertions(+), 73 deletions(-) delete mode 100644 babel.config.json create mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json index 69a602c5c..3d7db0846 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,11 +1,29 @@ { - "extends": "@appium/eslint-config-appium", + "extends": ["@appium/eslint-config-appium-ts"], "overrides": [ { "files": "test/**/*.js", "rules": { - "func-names": "off" + "func-names": "off", + "@typescript-eslint/no-var-requires": "off" + } + }, + { + "files": "Scripts/**/*.js", + "parserOptions": {"sourceType": "script"}, + "rules": { + "@typescript-eslint/no-var-requires": "off" + } + }, + { + "files": "ci-jobs/scripts/*.js", + "parserOptions": {"sourceType": "script"}, + "rules": { + "@typescript-eslint/no-var-requires": "off" } } - ] + ], + "rules": { + "require-await": "error" + } } diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index 8c95517e9..e5c1ebad9 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -25,5 +25,12 @@ jobs: npm install mkdir -p ./Resources/WebDriverAgent.bundle name: Install dev dependencies + + - run: | + target_sim_id=$(xcrun simctl list devices available | grep "$DEVICE_NAME (" | cut -d "(" -f2 | cut -d ")" -f1) + open -Fn "$(xcode-select -p)/Applications/Simulator.app" + xcrun simctl bootstatus $target_sim_id -b + name: Preboot Simulator + - run: npm run e2e-test name: Run functional tests diff --git a/.mocharc.js b/.mocharc.js index 66d4a976a..40599e9df 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -1,4 +1,4 @@ module.exports = { - require: ['@babel/register'], + require: ['ts-node/register'], forbidOnly: Boolean(process.env.CI) }; diff --git a/babel.config.json b/babel.config.json deleted file mode 100644 index 048e9cf60..000000000 --- a/babel.config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "targets": { - "node": "14" - }, - "shippedProposals": true - } - ] - ], - "plugins": [ - "source-map-support", - "@babel/plugin-transform-runtime" - ], - "comments": false, - "sourceMaps": "both", - "env": { - "test": { - "retainLines": true, - "comments": true - } - } -} diff --git a/lib/check-dependencies.js b/lib/check-dependencies.js index 39b824373..ce145f5a1 100644 --- a/lib/check-dependencies.js +++ b/lib/check-dependencies.js @@ -27,10 +27,9 @@ async function checkForDependencies () { return false; } -async function bundleWDASim (xcodebuild, opts = {}) { +async function bundleWDASim (xcodebuild) { if (xcodebuild && !_.isFunction(xcodebuild.retrieveDerivedDataPath)) { - xcodebuild = new XcodeBuild(); - opts = xcodebuild; + xcodebuild = new XcodeBuild('', {}); } const derivedDataPath = await xcodebuild.retrieveDerivedDataPath(); @@ -38,7 +37,7 @@ async function bundleWDASim (xcodebuild, opts = {}) { if (await fs.exists(wdaBundlePath)) { return wdaBundlePath; } - await buildWDASim(xcodebuild, opts); + await buildWDASim(); return wdaBundlePath; } diff --git a/lib/utils.js b/lib/utils.js index 71cac28ba..4a1191600 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -188,8 +188,8 @@ CODE_SIGN_IDENTITY = ${signingId} * @param {DeviceInfo} deviceInfo * @param {string} sdkVersion - The Xcode SDK version of OS. * @param {string} bootstrapPath - The folder path containing xctestrun file. - * @param {string} wdaRemotePort - The remote port WDA is listening on. - * @return {string} returns xctestrunFilePath for given device + * @param {number|string} wdaRemotePort - The remote port WDA is listening on. + * @return {Promise} returns xctestrunFilePath for given device * @throws if WebDriverAgentRunner_iphoneos${sdkVersion|platformVersion}-arm64.xctestrun for real device * or WebDriverAgentRunner_iphonesimulator${sdkVersion|platformVersion}-x86_64.xctestrun for simulator is not found @bootstrapPath, * then it will throw file not found exception @@ -207,7 +207,7 @@ async function setXctestrunFile (deviceInfo, sdkVersion, bootstrapPath, wdaRemot /** * Return the WDA object which appends existing xctest runner content * @param {string} platformName - The name of the platform - * @param {string} version - The Xcode SDK version of OS. + * @param {number|string} wdaRemotePort - The remote port number * @return {object} returns a runner object which has USE_PORT */ function getAdditionalRunContent (platformName, wdaRemotePort) { @@ -228,6 +228,7 @@ function getAdditionalRunContent (platformName, wdaRemotePort) { * @param {DeviceInfo} deviceInfo * @param {string} sdkVersion - The Xcode SDK version of OS. * @param {string} bootstrapPath - The folder path containing xctestrun file. + * @returns {Promise} */ async function getXctestrunFilePath (deviceInfo, sdkVersion, bootstrapPath) { // First try the SDK path, for Xcode 10 (at least) @@ -256,9 +257,11 @@ async function getXctestrunFilePath (deviceInfo, sdkVersion, bootstrapPath) { } } - log.errorAndThrow(`If you are using 'useXctestrunFile' capability then you ` + + throw new Error( + `If you are using 'useXctestrunFile' capability then you ` + `need to have a xctestrun file (expected: ` + - `'${path.resolve(bootstrapPath, getXctestrunFileName(deviceInfo, sdkVersion))}')`); + `'${path.resolve(bootstrapPath, getXctestrunFileName(deviceInfo, sdkVersion))}')` + ); } @@ -316,7 +319,7 @@ function randomInt (low, high) { /** * Retrieves WDA upgrade timestamp * - * @return {?number} The UNIX timestamp of the package manifest. The manifest only gets modified on + * @return {Promise} The UNIX timestamp of the package manifest. The manifest only gets modified on * package upgrade. */ async function getWDAUpgradeTimestamp () { @@ -356,7 +359,7 @@ async function resetTestProcesses (udid, isSimulator) { * listening on given port, and is expected to return * either true or false to include/exclude the corresponding PID * from the resulting array. - * @returns {Array} - the list of matched process ids. + * @returns {Promise} - the list of matched process ids. */ async function getPIDsListeningOnPort (port, filteringFunc = null) { const result = []; diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 4c52e91d6..40196b6ea 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -150,7 +150,7 @@ class WebDriverAgent { /** * Return boolean if WDA is running or not - * @return {boolean} True if WDA is running + * @return {Promise} True if WDA is running * @throws {Error} If there was invalid response code or body */ async isRunning () { @@ -183,7 +183,7 @@ class WebDriverAgent { * } * } * - * @return {?object} State Object + * @return {Promise} State Object * @throws {Error} If there was invalid response code or body */ async getStatus () { @@ -234,7 +234,7 @@ class WebDriverAgent { const box = strongbox(packageInfo.name); let boxItem = box.getItem(RECENT_MODULE_VERSION_ITEM_NAME); if (!boxItem) { - const timestampPath = path.resolve(process.env.HOME, WDA_UPGRADE_TIMESTAMP_PATH); + const timestampPath = path.resolve(process.env.HOME ?? '', WDA_UPGRADE_TIMESTAMP_PATH); if (await fs.exists(timestampPath)) { // TODO: It is probably a bit ugly to hardcode the recent version string, // TODO: hovewer it should do the job as a temporary transition trick @@ -279,6 +279,7 @@ class WebDriverAgent { `(${recentModuleVersion} < ${packageInfo.version})` ); try { + // @ts-ignore xcodebuild should be set await this.xcodebuild.cleanProject(); await boxItem.write(packageInfo.version); } catch (e) { @@ -289,7 +290,7 @@ class WebDriverAgent { /** * Launch WDA with preinstalled package without xcodebuild. * @param {string} sessionId Launch WDA and establish the session with this sessionId - * @return {?object} State Object + * @return {Promise} State Object */ async launchWithPreinstalledWDA(sessionId) { const xctestEnv = { @@ -330,7 +331,7 @@ class WebDriverAgent { * } * * @param {string} sessionId Launch WDA and establish the session with this sessionId - * @return {?object} State Object + * @return {Promise} State Object * @throws {Error} If there was invalid response code or body */ async launch (sessionId) { @@ -374,12 +375,15 @@ class WebDriverAgent { return await this.startWithIDB(); } + // @ts-ignore xcodebuild should be set await this.xcodebuild.init(this.noSessionProxy); // Start the xcodebuild process if (this.prebuildWDA) { + // @ts-ignore xcodebuild should be set await this.xcodebuild.prebuild(); } + // @ts-ignore xcodebuild should be set return await this.xcodebuild.start(); } @@ -463,7 +467,9 @@ class WebDriverAgent { } } else if (!this.args.webDriverAgentUrl) { this.log.info('Shutting down sub-processes'); + // @ts-ignore xcodebuild should be set await this.xcodebuild.quit(); + // @ts-ignore xcodebuild should be set await this.xcodebuild.reset(); } else { this.log.debug('Do not stop xcodebuild nor XCTest session ' + @@ -504,14 +510,15 @@ class WebDriverAgent { return this.started; } - set fullyStarted (started = false) { - this.started = started; + set fullyStarted (started) { + this.started = started ?? false; } async retrieveDerivedDataPath () { if (this.canSkipXcodebuild) { return; } + // @ts-ignore xcodebuild should be set return await this.xcodebuild.retrieveDerivedDataPath(); } @@ -519,8 +526,6 @@ class WebDriverAgent { * Reuse running WDA if it has the same bundle id with updatedWDABundleId. * Or reuse it if it has the default id without updatedWDABundleId. * Uninstall it if the method faces an exception for the above situation. - * - * @param {string} updatedWDABundleId BundleId you'd like to use */ async setupCaching () { const status = await this.getStatus(); diff --git a/lib/xcodebuild.js b/lib/xcodebuild.js index df5cac008..348a4f967 100644 --- a/lib/xcodebuild.js +++ b/lib/xcodebuild.js @@ -11,6 +11,7 @@ import _ from 'lodash'; import path from 'path'; import { EOL } from 'os'; import { WDA_RUNNER_BUNDLE_ID } from './constants'; +import readline from 'node:readline'; const DEFAULT_SIGNING_ID = 'iPhone Developer'; @@ -33,6 +34,12 @@ const xcodeLog = logger.getLogger('Xcode'); class XcodeBuild { + /** + * @param {string} xcodeVersion + * @param {any} device + * @param {any} args + * @param {import('@appium/types').AppiumLogger?} log + */ constructor (xcodeVersion, device, args = {}, log = null) { this.xcodeVersion = xcodeVersion; @@ -201,7 +208,7 @@ class XcodeBuild { args.push('-resultBundleVersion', this.resultBundleVersion); } - if (this.useXctestrunFile) { + if (this.useXctestrunFile && this.xctestrunFilePath) { args.push('-xctestrun', this.xctestrunFilePath); } else { const runnerScheme = isTvOS(this.platformName) ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS; @@ -252,6 +259,7 @@ class XcodeBuild { const {cmd, args} = this.getCommand(buildOnly); this.log.debug(`Beginning ${buildOnly ? 'build' : 'test'} with command '${cmd} ${args.join(' ')}' ` + `in directory '${this.bootstrapPath}'`); + /** @type {Record} */ const env = Object.assign({}, process.env, { USE_PORT: this.wdaRemotePort, WDA_PRODUCT_BUNDLE_IDENTIFIER: this.updatedWDABundleId || WDA_RUNNER_BUNDLE_ID, @@ -260,7 +268,7 @@ class XcodeBuild { // https://github.com/appium/WebDriverAgent/pull/105 env.MJPEG_SERVER_PORT = this.mjpegServerPort; } - const upgradeTimestamp = await getWDAUpgradeTimestamp(this.bootstrapPath); + const upgradeTimestamp = await getWDAUpgradeTimestamp(); if (upgradeTimestamp) { env.UPGRADE_TIMESTAMP = upgradeTimestamp; } @@ -283,7 +291,9 @@ class XcodeBuild { if (out.includes('Writing diagnostic log for test session to')) { // pull out the first line that begins with the path separator // which *should* be the line indicating the log file generated + // @ts-ignore logLocation is a custom property xcodebuild.logLocation = _.first(_.remove(out.trim().split('\n'), (v) => v.startsWith(path.sep))); + // @ts-ignore logLocation is a custom property xcodeLog.debug(`Log file for xcodebuild test: ${xcodebuild.logLocation}`); } @@ -295,6 +305,7 @@ class XcodeBuild { logXcodeOutput = true; // terrible hack to handle case where xcode return 0 but is failing + // @ts-ignore _wda_error_occurred is a custom property xcodebuild._wda_error_occurred = true; } @@ -303,6 +314,7 @@ class XcodeBuild { for (const line of out.split(EOL)) { xcodeLog.error(line); if (line) { + // @ts-ignore _wda_error_message is a custom property xcodebuild._wda_error_message += `${EOL}${line}`; } } @@ -315,28 +327,45 @@ class XcodeBuild { async start (buildOnly = false) { this.xcodebuild = await this.createSubProcess(buildOnly); // Store xcodebuild message + // @ts-ignore _wda_error_message is a custom property this.xcodebuild._wda_error_message = ''; // wrap the start procedure in a promise so that we can catch, and report, // any startup errors that are thrown as events return await new B((resolve, reject) => { + // @ts-ignore xcodebuild must be present here this.xcodebuild.on('exit', async (code, signal) => { xcodeLog.error(`xcodebuild exited with code '${code}' and signal '${signal}'`); // print out the xcodebuild file if users have asked for it - if (this.showXcodeLog && this.xcodebuild.logLocation) { + // @ts-ignore logLocation is a custom property + if (this.showXcodeLog && this.xcodebuild?.logLocation) { + // @ts-ignore logLocation is a custom property xcodeLog.error(`Contents of xcodebuild log file '${this.xcodebuild.logLocation}':`); try { - let data = await fs.readFile(this.xcodebuild.logLocation, 'utf8'); - for (let line of data.split('\n')) { + const logFile = readline.createInterface({ + // @ts-ignore logLocation is a custom property + input: fs.createReadStream(this.xcodebuild.logLocation), + terminal: false + }); + logFile.on('line', (line) => { xcodeLog.error(line); - } + }); + await new B((_resolve) => { + logFile.once('close', () => { + logFile.removeAllListeners(); + _resolve(); + }); + }); } catch (err) { xcodeLog.error(`Unable to access xcodebuild log file: '${err.message}'`); } } + // @ts-ignore processExited is a custom property this.xcodebuild.processExited = true; + // @ts-ignore _wda_error_occurred is a custom property if (this.xcodebuild._wda_error_occurred || (!signal && code !== 0)) { return reject(new Error(`xcodebuild failed with code ${code}${EOL}` + + // @ts-ignore _wda_error_message is a custom property `xcodebuild error message:${EOL}${this.xcodebuild._wda_error_message}`)); } // in the case of just building, the process will exit and that is our finish @@ -348,6 +377,7 @@ class XcodeBuild { return (async () => { try { const timer = new timing.Timer().start(); + // @ts-ignore this.xcodebuild must be defined await this.xcodebuild.start(true); if (!buildOnly) { let status = await this.waitForStart(timer); @@ -367,8 +397,9 @@ class XcodeBuild { this.log.debug(`Waiting up to ${this.launchTimeout}ms for WebDriverAgent to start`); let currentStatus = null; try { - let retries = parseInt(this.launchTimeout / 500, 10); + let retries = parseInt(`${this.launchTimeout / 500}`, 10); await retryInterval(retries, 1000, async () => { + // @ts-ignore processExited is a custom property if (this.xcodebuild.processExited) { // there has been an error elsewhere and we need to short-circuit return; @@ -389,6 +420,7 @@ class XcodeBuild { } }); + // @ts-ignore processExited is a custom property if (this.xcodebuild.processExited) { // there has been an error elsewhere and we need to short-circuit return currentStatus; diff --git a/package.json b/package.json index f69d650d1..4068218fd 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,9 @@ "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { - "build": "rm -rf build && babel --out-dir=build/lib lib && babel --out-dir=build index.js", + "build": "tsc -b", "dev": "npm run build -- --watch", + "clean": "npm run build -- --clean", "lint": "eslint .", "lint:fix": "npm run lint -- --fix", "precommit-msg": "echo 'Pre-commit checks...' && exit 0", @@ -54,43 +55,52 @@ }, "homepage": "https://github.com/appium/WebDriverAgent#readme", "devDependencies": { - "@appium/eslint-config-appium": "^6.0.0", + "@appium/eslint-config-appium": "^8.0.4", + "@appium/eslint-config-appium-ts": "^0.3.1", "@appium/test-support": "^3.0.0", - "@babel/cli": "^7.18.10", - "@babel/core": "^7.18.10", - "@babel/eslint-parser": "^7.18.9", - "@babel/plugin-transform-runtime": "^7.18.10", - "@babel/preset-env": "^7.18.10", - "@babel/register": "^7.18.9", + "@appium/tsconfig": "^0.3.0", + "@appium/types": "^0.13.2", "@semantic-release/changelog": "^6.0.1", "@semantic-release/git": "^10.0.1", - "babel-plugin-source-map-support": "^2.2.0", + "@types/bluebird": "^3.5.38", + "@types/chai": "^4.3.5", + "@types/chai-as-promised": "^7.1.5", + "@types/lodash": "^4.14.196", + "@types/mocha": "^10.0.1", + "@types/node": "^20.4.7", + "@types/sinon": "^10.0.16", + "@types/sinon-chai": "^3.2.9", + "@types/teen_process": "2.0.0", + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", "appium-xcode": "^5.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "conventional-changelog-conventionalcommits": "^6.0.0", - "eslint": "^7.32.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-mocha": "^9.0.0", - "eslint-plugin-promise": "^6.0.0", + "eslint": "^8.46.0", + "eslint-config-prettier": "^8.9.0", + "eslint-import-resolver-typescript": "^3.5.5", + "eslint-plugin-import": "^2.28.0", + "eslint-plugin-mocha": "^10.1.0", + "eslint-plugin-promise": "^6.1.1", "lint-staged": "^14.0.0", "mocha": "^10.0.0", "pre-commit": "^1.2.2", "prettier": "^3.0.0", "semantic-release": "^20.0.2", - "sinon": "^15.0.0" + "sinon": "^15.0.0", + "ts-node": "^10.9.1", + "typescript": "^5.1.6" }, "dependencies": { "@appium/base-driver": "^9.0.0", "@appium/strongbox": "^0.x", "@appium/support": "^4.0.0", - "@babel/runtime": "^7.0.0", "appium-ios-device": "^2.5.0", "appium-ios-simulator": "^5.0.1", "async-lock": "^1.0.0", "asyncbox": "^2.5.3", - "axios": "^1.x", + "axios": "^1.4.0", "bluebird": "^3.5.5", "lodash": "^4.17.11", "node-simctl": "^7.0.1", diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..33d83ef45 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@appium/tsconfig/tsconfig.json", + "compilerOptions": { + "strict": false, // TODO: make this flag true + "outDir": "build", + "types": ["node"], + "checkJs": true + }, + "include": [ + "index.js", + "lib" + ] +} From aed7689ea86dba833173bcce5344f549281b9e9f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 24 Aug 2023 05:46:07 +0000 Subject: [PATCH 061/133] chore(release): 5.7.0 [skip ci] ## [5.7.0](https://github.com/appium/WebDriverAgent/compare/v5.6.2...v5.7.0) (2023-08-24) ### Features * Switch babel to typescript ([#753](https://github.com/appium/WebDriverAgent/issues/753)) ([76a4c7f](https://github.com/appium/WebDriverAgent/commit/76a4c7f066e1895acbb153ab035d6a08604277e4)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6650bf5a9..f864d6fd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.7.0](https://github.com/appium/WebDriverAgent/compare/v5.6.2...v5.7.0) (2023-08-24) + + +### Features + +* Switch babel to typescript ([#753](https://github.com/appium/WebDriverAgent/issues/753)) ([76a4c7f](https://github.com/appium/WebDriverAgent/commit/76a4c7f066e1895acbb153ab035d6a08604277e4)) + ## [5.6.2](https://github.com/appium/WebDriverAgent/compare/v5.6.1...v5.6.2) (2023-08-23) diff --git a/package.json b/package.json index 4068218fd..033a06d26 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.6.2", + "version": "5.7.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 075298b286c83ab5d4a2855e9e0bb915790b3f43 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 24 Aug 2023 22:20:46 +0200 Subject: [PATCH 062/133] feat: Add wdHittable property (#756) --- .../XCUIElement+FBWebDriverAttributes.m | 7 +++++ WebDriverAgentLib/Routing/FBElement.h | 3 ++ WebDriverAgentLib/Utilities/FBMacros.h | 4 +++ WebDriverAgentLib/Utilities/FBXPath.m | 31 ++++++++++++++++--- .../FBElementAttributeTests.m | 1 + .../FBXPathIntegrationTests.m | 7 +++-- .../IntegrationTests/XCUIElementFBFindTests.m | 2 +- .../Doubles/XCElementSnapshotDouble.m | 6 ++++ .../UnitTests/Doubles/XCUIElementDouble.h | 2 ++ .../UnitTests/Doubles/XCUIElementDouble.m | 2 ++ WebDriverAgentTests/UnitTests/FBXPathTests.m | 11 ++++--- .../Doubles/XCUIElementDouble.h | 1 + .../Doubles/XCUIElementDouble.m | 1 + 13 files changed, 65 insertions(+), 13 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m index 2f2368180..b29c5a8b2 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m @@ -20,6 +20,7 @@ #import "XCUIElement+FBUtilities.h" #import "FBElementUtils.h" #import "XCTestPrivateSymbols.h" +#import "XCUIHitPointResult.h" #define BROKEN_RECT CGRectMake(-1, -1, 0, 0) @@ -226,6 +227,12 @@ - (NSUInteger)wdIndex return 0; } +- (BOOL)isWDHittable +{ + XCUIHitPointResult *result = [self hitPoint:nil]; + return nil == result ? NO : result.hittable; +} + - (NSDictionary *)wdRect { CGRect frame = self.wdFrame; diff --git a/WebDriverAgentLib/Routing/FBElement.h b/WebDriverAgentLib/Routing/FBElement.h index 277a4ccd2..7cc8f269c 100644 --- a/WebDriverAgentLib/Routing/FBElement.h +++ b/WebDriverAgentLib/Routing/FBElement.h @@ -56,6 +56,9 @@ NS_ASSUME_NONNULL_BEGIN /*! Whether element is focused */ @property (nonatomic, readonly, getter = isWDFocused) BOOL wdFocused; +/*! Whether element is hittable */ +@property (nonatomic, readonly, getter = isWDHittable) BOOL wdHittable; + /*! Element's index relatively to its parent. Starts from zero */ @property (nonatomic, readonly) NSUInteger wdIndex; diff --git a/WebDriverAgentLib/Utilities/FBMacros.h b/WebDriverAgentLib/Utilities/FBMacros.h index ed4e6f7a0..dae0c5faf 100644 --- a/WebDriverAgentLib/Utilities/FBMacros.h +++ b/WebDriverAgentLib/Utilities/FBMacros.h @@ -52,3 +52,7 @@ /*! Converts the given number of milliseconds into seconds */ #define FBMillisToSeconds(ms) ((ms) / 1000.0) + +/*! Converts boolean value to its string representation */ +#define FBBoolToString(b) ((b) ? @"true" : @"false") + diff --git a/WebDriverAgentLib/Utilities/FBXPath.m b/WebDriverAgentLib/Utilities/FBXPath.m index 00c5d44e7..eae3ee438 100644 --- a/WebDriverAgentLib/Utilities/FBXPath.m +++ b/WebDriverAgentLib/Utilities/FBXPath.m @@ -12,6 +12,7 @@ #import "FBConfiguration.h" #import "FBExceptions.h" #import "FBLogger.h" +#import "FBMacros.h" #import "FBXMLGenerationOptions.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "NSString+FBXMLSafeString.h" @@ -87,6 +88,10 @@ @interface FBIndexAttribute : FBElementAttribute @end +@interface FBHittableAttribute : FBElementAttribute + +@end + @interface FBInternalIndexAttribute : FBElementAttribute @property (nonatomic, nonnull, readonly) NSString* indexValue; @@ -273,6 +278,9 @@ + (int)xmlRepresentationWithRootElement:(id)root NSMutableSet *includedAttributes; if (nil == query) { includedAttributes = [NSMutableSet setWithArray:FBElementAttribute.supportedAttributes]; + // The hittable attribute is expensive to calculate for each snapshot item + // thus we only include it when requested by an xPath query + [includedAttributes removeObject:FBHittableAttribute.class]; if (nil != excludedAttributes) { for (NSString *excludedAttributeName in excludedAttributes) { for (Class supportedAttribute in FBElementAttribute.supportedAttributes) { @@ -481,6 +489,7 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forElement:(id)eleme FBWidthAttribute.class, FBHeightAttribute.class, FBIndexAttribute.class, + FBHittableAttribute.class, ]; } @@ -557,7 +566,7 @@ + (NSString *)name + (NSString *)valueForElement:(id)element { - return element.wdEnabled ? @"true" : @"false"; + return FBBoolToString(element.wdEnabled); } @end @@ -571,7 +580,7 @@ + (NSString *)name + (NSString *)valueForElement:(id)element { - return element.wdVisible ? @"true" : @"false"; + return FBBoolToString(element.wdVisible); } @end @@ -585,7 +594,7 @@ + (NSString *)name + (NSString *)valueForElement:(id)element { - return element.wdAccessible ? @"true" : @"false"; + return FBBoolToString(element.wdAccessible); } @end @@ -601,7 +610,7 @@ + (NSString *)name + (NSString *)valueForElement:(id)element { - return element.wdFocused ? @"true" : @"false"; + return FBBoolToString(element.wdFocused); } @end @@ -667,6 +676,20 @@ + (NSString *)valueForElement:(id)element @end +@implementation FBHittableAttribute + ++ (NSString *)name +{ + return @"hittable"; +} + ++ (NSString *)valueForElement:(id)element +{ + return FBBoolToString(element.wdHittable); +} + +@end + @implementation FBInternalIndexAttribute + (NSString *)name diff --git a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m index c7cc3505e..13cba4e57 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m @@ -160,6 +160,7 @@ - (void)testSwitchAttributes XCTAssertNil(element.wdLabel); XCTAssertEqualObjects(element.wdValue, @"1"); XCTAssertFalse(element.wdSelected); + XCTAssertTrue(element.wdHittable); [element tap]; XCTAssertEqualObjects(element.wdValue, @"0"); XCTAssertFalse(element.wdSelected); diff --git a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m index 22983faa6..aa1ed56c2 100644 --- a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m @@ -10,6 +10,7 @@ #import #import "FBIntegrationTestCase.h" +#import "FBMacros.h" #import "FBTestMacros.h" #import "FBXPath.h" #import "FBXCodeCompatibility.h" @@ -58,7 +59,7 @@ - (void)testSingleDescendantXMLRepresentation NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot options:nil]; XCTAssertNotNil(xmlStr); - NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, wrappedSnapshot.wdEnabled ? @"true" : @"false", wrappedSnapshot.wdVisible ? @"true" : @"false", wrappedSnapshot.wdAccessible ? @"true" : @"false", [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex]; XCTAssertEqualObjects(xmlStr, expectedXml); } @@ -71,7 +72,7 @@ - (void)testSingleDescendantXMLRepresentationWithScope NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot options:options]; XCTAssertNotNil(xmlStr); - NSString *expectedXml = [NSString stringWithFormat:@"\n<%@>\n <%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\"/>\n\n", scope, wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, wrappedSnapshot.wdEnabled ? @"true" : @"false", wrappedSnapshot.wdVisible ? @"true" : @"false", wrappedSnapshot.wdAccessible ? @"true" : @"false", [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex, scope]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@>\n <%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\"/>\n\n", scope, wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex, scope]; XCTAssertEqualObjects(xmlStr, expectedXml); } @@ -84,7 +85,7 @@ - (void)testSingleDescendantXMLRepresentationWithoutAttributes NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot options:options]; XCTAssertNotNil(xmlStr); - NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, wrappedSnapshot.wdAccessible ? @"true" : @"false", [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue]]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue]]; XCTAssertEqualObjects(xmlStr, expectedXml); } diff --git a/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m b/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m index 202c48ba9..243ebec5d 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m @@ -127,7 +127,7 @@ - (void)testSelfWithXPathQuery - (void)testSingleDescendantWithXPathQuery { - NSArray *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton" + NSArray *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeButton[@hittable='true']" shouldReturnAfterFirstMatch:YES]; XCTAssertEqual(matchingSnapshots.count, 1); XCUIElement *matchingSnapshot = [matchingSnapshots firstObject]; diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m b/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m index 455e32227..d52c2904c 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +++ b/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m @@ -11,6 +11,7 @@ #import "FBXCAccessibilityElement.h" #import "FBXCElementSnapshot.h" +#import "XCUIHitPointResult.h" @implementation XCElementSnapshotDouble @@ -87,6 +88,11 @@ - (NSDictionary *)additionalAttributes return nil; } +- (XCUIHitPointResult *)hitPoint:(NSError **)error +{ + return [[XCUIHitPointResult alloc] initWithHitPoint:CGPointZero hittable:YES]; +} + - (NSArray *)children { return @[]; diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h index 473a40121..d40945545 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h @@ -32,6 +32,8 @@ @property (nonatomic, readwrite) NSUInteger wdIndex; @property (nonatomic, readwrite, getter=isWDVisible) BOOL wdVisible; @property (nonatomic, readwrite, getter=isWDAccessible) BOOL wdAccessible; +@property (nonatomic, readwrite, getter = isWDFocused) BOOL wdFocused; +@property (nonatomic, readwrite, getter = isWDHittable) BOOL wdHittable; @property (copy, nonnull) NSArray *children; @property (nonatomic, readwrite, assign) XCUIElementType elementType; @property (nonatomic, readwrite, getter=isWDAccessibilityContainer) BOOL wdAccessibilityContainer; diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m index b60e50c26..e9792f132 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m @@ -27,6 +27,8 @@ - (id)init self.wdAccessible = YES; self.wdEnabled = YES; self.wdSelected = YES; + self.wdFocused = YES; + self.wdHittable = YES; self.wdIndex = 0; #if TARGET_OS_TV self.wdFocused = YES; diff --git a/WebDriverAgentTests/UnitTests/FBXPathTests.m b/WebDriverAgentTests/UnitTests/FBXPathTests.m index 058d6dc89..ce9171107 100644 --- a/WebDriverAgentTests/UnitTests/FBXPathTests.m +++ b/WebDriverAgentTests/UnitTests/FBXPathTests.m @@ -9,6 +9,7 @@ #import +#import "FBMacros.h" #import "FBXPath.h" #import "FBXPath-Private.h" #import "XCUIElementDouble.h" @@ -63,7 +64,7 @@ - (void)testDefaultXPathPresentation xpathQuery:nil excludingAttributes:nil]; NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" private_indexPath=\"top\"/>\n", - element.wdType, element.wdType, element.wdValue, element.wdName, element.wdLabel, element.wdEnabled ? @"true" : @"false", element.wdVisible ? @"true" : @"false", element.wdAccessible ? @"true" : @"false", element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex]; + element.wdType, element.wdType, element.wdValue, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex]; XCTAssertTrue([resultXml isEqualToString: expectedXml]); } @@ -75,7 +76,7 @@ - (void)testtXPathPresentationWithSomeAttributesExcluded xpathQuery:nil excludingAttributes:@[@"type", @"visible", @"value", @"index"]]; NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ name=\"%@\" label=\"%@\" enabled=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" private_indexPath=\"top\"/>\n", - element.wdType, element.wdName, element.wdLabel, element.wdEnabled ? @"true" : @"false", element.wdAccessible ? @"true" : @"false", element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"]]; + element.wdType, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"]]; XCTAssertEqualObjects(resultXml, expectedXml); } @@ -88,9 +89,9 @@ - (void)testXPathPresentationBasedOnQueryMatchingAllAttributes NSString *resultXml = [self xmlStringWithElement:element xpathQuery:[NSString stringWithFormat:@"//%@[@*]", element.wdType] excludingAttributes:@[@"visible"]]; - NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" private_indexPath=\"top\"/>\n", - element.wdType, element.wdType, @"йоло<>&"", element.wdName, @"a b", element.wdEnabled ? @"true" : @"false", element.wdVisible ? @"true" : @"false", element.wdAccessible ? @"true" : @"false", element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex]; - XCTAssertTrue([resultXml isEqualToString:expectedXml]); + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" hittable=\"%@\" private_indexPath=\"top\"/>\n", + element.wdType, element.wdType, @"йоло<>&"", element.wdName, @"a b", FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex, FBBoolToString(element.wdHittable)]; + XCTAssertEqualObjects(expectedXml, resultXml); } - (void)testXPathPresentationBasedOnQueryMatchingSomeAttributes diff --git a/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h b/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h index d8f272d31..cb43c334d 100644 --- a/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h +++ b/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h @@ -32,6 +32,7 @@ @property (nonatomic, readwrite, getter=isWDVisible) BOOL wdVisible; @property (nonatomic, readwrite, getter=isWDAccessible) BOOL wdAccessible; @property (nonatomic, readwrite, getter=isWDFocused) BOOL wdFocused; +@property (nonatomic, readwrite, getter = isWDHittable) BOOL wdHittable; @property (copy, nonnull) NSArray *children; @property (nonatomic, readwrite, assign) XCUIElementType elementType; @property (nonatomic, readwrite, getter=isWDAccessibilityContainer) BOOL wdAccessibilityContainer; diff --git a/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.m b/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.m index f8b39940a..2ed546319 100644 --- a/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.m +++ b/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.m @@ -27,6 +27,7 @@ - (id)init self.wdAccessible = YES; self.wdEnabled = YES; self.wdSelected = YES; + self.wdHittable = YES; self.wdIndex = 0; #if TARGET_OS_TV self.wdFocused = YES; From 11e62d9e09dc8ec8ead2da998de8e26018bec79f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 24 Aug 2023 20:29:41 +0000 Subject: [PATCH 063/133] chore(release): 5.8.0 [skip ci] ## [5.8.0](https://github.com/appium/WebDriverAgent/compare/v5.7.0...v5.8.0) (2023-08-24) ### Features * Add wdHittable property ([#756](https://github.com/appium/WebDriverAgent/issues/756)) ([075298b](https://github.com/appium/WebDriverAgent/commit/075298b286c83ab5d4a2855e9e0bb915790b3f43)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f864d6fd3..6dbd23def 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.8.0](https://github.com/appium/WebDriverAgent/compare/v5.7.0...v5.8.0) (2023-08-24) + + +### Features + +* Add wdHittable property ([#756](https://github.com/appium/WebDriverAgent/issues/756)) ([075298b](https://github.com/appium/WebDriverAgent/commit/075298b286c83ab5d4a2855e9e0bb915790b3f43)) + ## [5.7.0](https://github.com/appium/WebDriverAgent/compare/v5.6.2...v5.7.0) (2023-08-24) diff --git a/package.json b/package.json index 033a06d26..2ab81005c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.7.0", + "version": "5.8.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From d86d9a64ca75ad40273cfa10855f49b967d9fd95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 23:04:59 -0700 Subject: [PATCH 064/133] chore(deps-dev): bump semantic-release from 20.1.3 to 21.1.0 (#754) Bumps [semantic-release](https://github.com/semantic-release/semantic-release) from 20.1.3 to 21.1.0. - [Release notes](https://github.com/semantic-release/semantic-release/releases) - [Commits](https://github.com/semantic-release/semantic-release/compare/v20.1.3...v21.1.0) --- updated-dependencies: - dependency-name: semantic-release dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ab81005c..e073e9428 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "mocha": "^10.0.0", "pre-commit": "^1.2.2", "prettier": "^3.0.0", - "semantic-release": "^20.0.2", + "semantic-release": "^21.1.0", "sinon": "^15.0.0", "ts-node": "^10.9.1", "typescript": "^5.1.6" From 734d13927b9d83deabb945062cc8e44a35960d77 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 25 Aug 2023 06:12:22 +0000 Subject: [PATCH 065/133] chore(release): 5.8.1 [skip ci] ## [5.8.1](https://github.com/appium/WebDriverAgent/compare/v5.8.0...v5.8.1) (2023-08-25) ### Miscellaneous Chores * **deps-dev:** bump semantic-release from 20.1.3 to 21.1.0 ([#754](https://github.com/appium/WebDriverAgent/issues/754)) ([d86d9a6](https://github.com/appium/WebDriverAgent/commit/d86d9a64ca75ad40273cfa10855f49b967d9fd95)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dbd23def..8cb22daf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.8.1](https://github.com/appium/WebDriverAgent/compare/v5.8.0...v5.8.1) (2023-08-25) + + +### Miscellaneous Chores + +* **deps-dev:** bump semantic-release from 20.1.3 to 21.1.0 ([#754](https://github.com/appium/WebDriverAgent/issues/754)) ([d86d9a6](https://github.com/appium/WebDriverAgent/commit/d86d9a64ca75ad40273cfa10855f49b967d9fd95)) + ## [5.8.0](https://github.com/appium/WebDriverAgent/compare/v5.7.0...v5.8.0) (2023-08-24) diff --git a/package.json b/package.json index e073e9428..afd05bd50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.8.0", + "version": "5.8.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From a3047ea70b7a9fd5ccb2a2c93b0964d7de609d38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:41:20 +0200 Subject: [PATCH 066/133] chore(deps-dev): bump conventional-changelog-conventionalcommits (#757) Bumps [conventional-changelog-conventionalcommits](https://github.com/conventional-changelog/conventional-changelog) from 6.1.0 to 7.0.1. - [Release notes](https://github.com/conventional-changelog/conventional-changelog/releases) - [Changelog](https://github.com/conventional-changelog/conventional-changelog/blob/master/.release-please-manifest.json) - [Commits](https://github.com/conventional-changelog/conventional-changelog/compare/conventional-changelog-conventionalcommits-v6.1.0...conventional-changelog-conventionalcommits-v7.0.1) --- updated-dependencies: - dependency-name: conventional-changelog-conventionalcommits dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index afd05bd50..d3193710e 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "appium-xcode": "^5.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "conventional-changelog-conventionalcommits": "^6.0.0", + "conventional-changelog-conventionalcommits": "^7.0.1", "eslint": "^8.46.0", "eslint-config-prettier": "^8.9.0", "eslint-import-resolver-typescript": "^3.5.5", From 2470883019400d9335d2d7263dab82d11b8c2448 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 28 Aug 2023 17:17:14 +0000 Subject: [PATCH 067/133] chore(release): 5.8.2 [skip ci] ## [5.8.2](https://github.com/appium/WebDriverAgent/compare/v5.8.1...v5.8.2) (2023-08-28) ### Miscellaneous Chores * **deps-dev:** bump conventional-changelog-conventionalcommits ([#757](https://github.com/appium/WebDriverAgent/issues/757)) ([a3047ea](https://github.com/appium/WebDriverAgent/commit/a3047ea70b7a9fd5ccb2a2c93b0964d7de609d38)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cb22daf6..96e1453c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.8.2](https://github.com/appium/WebDriverAgent/compare/v5.8.1...v5.8.2) (2023-08-28) + + +### Miscellaneous Chores + +* **deps-dev:** bump conventional-changelog-conventionalcommits ([#757](https://github.com/appium/WebDriverAgent/issues/757)) ([a3047ea](https://github.com/appium/WebDriverAgent/commit/a3047ea70b7a9fd5ccb2a2c93b0964d7de609d38)) + ## [5.8.1](https://github.com/appium/WebDriverAgent/compare/v5.8.0...v5.8.1) (2023-08-25) diff --git a/package.json b/package.json index d3193710e..b35df82fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.8.1", + "version": "5.8.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 87e87044d6216513f755c5184d61514a76cb0179 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 1 Sep 2023 07:25:19 +0200 Subject: [PATCH 068/133] fix: Address some typing-related issues (#759) --- lib/webdriveragent.js | 6 ++--- lib/xcodebuild.js | 63 ++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 40196b6ea..fdae2bff6 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -467,10 +467,8 @@ class WebDriverAgent { } } else if (!this.args.webDriverAgentUrl) { this.log.info('Shutting down sub-processes'); - // @ts-ignore xcodebuild should be set - await this.xcodebuild.quit(); - // @ts-ignore xcodebuild should be set - await this.xcodebuild.reset(); + await this.xcodebuild?.quit(); + await this.xcodebuild?.reset(); } else { this.log.debug('Do not stop xcodebuild nor XCTest session ' + 'since the WDA session is managed by outside this driver.'); diff --git a/lib/xcodebuild.js b/lib/xcodebuild.js index 348a4f967..23f365417 100644 --- a/lib/xcodebuild.js +++ b/lib/xcodebuild.js @@ -84,6 +84,13 @@ class XcodeBuild { this.resultBundlePath = args.resultBundlePath; this.resultBundleVersion = args.resultBundleVersion; + + /** @type {string} */ + this._logLocation = ''; + /** @type {string[]} */ + this._wdaErrorMessage = []; + this._didBuildFail = false; + this._didProcessExit = false; } async init (noSessionProxy) { @@ -163,8 +170,10 @@ class XcodeBuild { this.xcodebuild = null; - // pause a moment - await B.delay(this.prebuildDelay); + if (this.prebuildDelay > 0) { + // pause a moment + await B.delay(this.prebuildDelay); + } } async cleanProject () { @@ -272,6 +281,8 @@ class XcodeBuild { if (upgradeTimestamp) { env.UPGRADE_TIMESTAMP = upgradeTimestamp; } + this._logLocation = ''; + this._didBuildFail = false; const xcodebuild = new SubProcess(cmd, args, { cwd: this.bootstrapPath, env, @@ -291,10 +302,8 @@ class XcodeBuild { if (out.includes('Writing diagnostic log for test session to')) { // pull out the first line that begins with the path separator // which *should* be the line indicating the log file generated - // @ts-ignore logLocation is a custom property - xcodebuild.logLocation = _.first(_.remove(out.trim().split('\n'), (v) => v.startsWith(path.sep))); - // @ts-ignore logLocation is a custom property - xcodeLog.debug(`Log file for xcodebuild test: ${xcodebuild.logLocation}`); + this._logLocation = _.first(_.remove(out.trim().split('\n'), (v) => v.startsWith(path.sep))) ?? ''; + xcodeLog.debug(`Log file location for xcodebuild test: ${this._logLocation || 'unknown'}`); } // if we have an error we want to output the logs @@ -304,9 +313,8 @@ class XcodeBuild { if (this.showXcodeLog !== false && out.includes('Error Domain=') && !ignoreError) { logXcodeOutput = true; - // terrible hack to handle case where xcode return 0 but is failing - // @ts-ignore _wda_error_occurred is a custom property - xcodebuild._wda_error_occurred = true; + // handle case where xcode returns 0 but is failing + this._didBuildFail = true; } // do not log permission errors from trying to write to attachments folder @@ -314,8 +322,7 @@ class XcodeBuild { for (const line of out.split(EOL)) { xcodeLog.error(line); if (line) { - // @ts-ignore _wda_error_message is a custom property - xcodebuild._wda_error_message += `${EOL}${line}`; + this._wdaErrorMessage.push(line); } } } @@ -327,24 +334,23 @@ class XcodeBuild { async start (buildOnly = false) { this.xcodebuild = await this.createSubProcess(buildOnly); // Store xcodebuild message - // @ts-ignore _wda_error_message is a custom property - this.xcodebuild._wda_error_message = ''; + this._wdaErrorMessage = []; // wrap the start procedure in a promise so that we can catch, and report, // any startup errors that are thrown as events return await new B((resolve, reject) => { // @ts-ignore xcodebuild must be present here - this.xcodebuild.on('exit', async (code, signal) => { + this.xcodebuild.once('exit', async (code, signal) => { xcodeLog.error(`xcodebuild exited with code '${code}' and signal '${signal}'`); + this.xcodebuild?.removeAllListeners(); + const xcodeErrorMessage = this._wdaErrorMessage.join('\n'); + this._wdaErrorMessage = []; // print out the xcodebuild file if users have asked for it - // @ts-ignore logLocation is a custom property - if (this.showXcodeLog && this.xcodebuild?.logLocation) { - // @ts-ignore logLocation is a custom property - xcodeLog.error(`Contents of xcodebuild log file '${this.xcodebuild.logLocation}':`); + if (this.showXcodeLog && this._logLocation) { + xcodeLog.error(`Contents of xcodebuild log file '${this._logLocation}':`); try { const logFile = readline.createInterface({ - // @ts-ignore logLocation is a custom property - input: fs.createReadStream(this.xcodebuild.logLocation), + input: fs.createReadStream(this._logLocation), terminal: false }); logFile.on('line', (line) => { @@ -360,13 +366,10 @@ class XcodeBuild { xcodeLog.error(`Unable to access xcodebuild log file: '${err.message}'`); } } - // @ts-ignore processExited is a custom property - this.xcodebuild.processExited = true; - // @ts-ignore _wda_error_occurred is a custom property - if (this.xcodebuild._wda_error_occurred || (!signal && code !== 0)) { - return reject(new Error(`xcodebuild failed with code ${code}${EOL}` + - // @ts-ignore _wda_error_message is a custom property - `xcodebuild error message:${EOL}${this.xcodebuild._wda_error_message}`)); + this.didProcessExit = true; + if (this._didBuildFail || (!signal && code !== 0)) { + return reject(new Error(`xcodebuild failed with code ${code}\n` + + `xcodebuild error message:\n${xcodeErrorMessage}`)); } // in the case of just building, the process will exit and that is our finish if (buildOnly) { @@ -399,8 +402,7 @@ class XcodeBuild { try { let retries = parseInt(`${this.launchTimeout / 500}`, 10); await retryInterval(retries, 1000, async () => { - // @ts-ignore processExited is a custom property - if (this.xcodebuild.processExited) { + if (this._didProcessExit) { // there has been an error elsewhere and we need to short-circuit return; } @@ -420,8 +422,7 @@ class XcodeBuild { } }); - // @ts-ignore processExited is a custom property - if (this.xcodebuild.processExited) { + if (this._didProcessExit) { // there has been an error elsewhere and we need to short-circuit return currentStatus; } From 9773d1b7b432736a813bced9bf26efefecdf066f Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 1 Sep 2023 07:32:23 +0200 Subject: [PATCH 069/133] tests: Fix unit tests --- .github/workflows/unit-test.yml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 665cf2e5d..ef98e4ca6 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -9,17 +9,9 @@ jobs: outputs: versions: ${{ steps.generate-matrix.outputs.versions }} steps: - - name: Generate Node.js versions matrix + - name: Select 3 most recent LTS versions of Node.js id: generate-matrix - run: | - sudo apt-get install -y lynx - lynx -dump https://endoflife.date/nodejs | grep -E -o '[0-9]+[( a-zA-Z]+LTS\)' | grep -E -o '([0-9]+)' > eol.list - cat eol.list - lts1=$(cat eol.list | head -1) - lts2=$(cat eol.list | head -2 | tail -1) - lts3=$(cat eol.list | head -3 | tail -1) - VERSIONS="[$lts1, $lts2, $lts3]" - echo "versions=${VERSIONS}" >> "$GITHUB_OUTPUT" + run: echo "versions=$(curl -s https://endoflife.date/api/nodejs.json | jq -c '[[.[] | select(.lts != false)][:3] | .[].cycle | tonumber]')" >> "$GITHUB_OUTPUT" test: needs: @@ -33,8 +25,6 @@ jobs: - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - - run: npm i -g npm - name: Update NPM - run: npm install --no-package-lock name: Install dev dependencies - run: npm run lint From 7168159cabdd19b31913a2e4b401f07143f5a732 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 1 Sep 2023 05:41:29 +0000 Subject: [PATCH 070/133] chore(release): 5.8.3 [skip ci] ## [5.8.3](https://github.com/appium/WebDriverAgent/compare/v5.8.2...v5.8.3) (2023-09-01) ### Bug Fixes * Address some typing-related issues ([#759](https://github.com/appium/WebDriverAgent/issues/759)) ([87e8704](https://github.com/appium/WebDriverAgent/commit/87e87044d6216513f755c5184d61514a76cb0179)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96e1453c2..311f82c73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.8.3](https://github.com/appium/WebDriverAgent/compare/v5.8.2...v5.8.3) (2023-09-01) + + +### Bug Fixes + +* Address some typing-related issues ([#759](https://github.com/appium/WebDriverAgent/issues/759)) ([87e8704](https://github.com/appium/WebDriverAgent/commit/87e87044d6216513f755c5184d61514a76cb0179)) + ## [5.8.2](https://github.com/appium/WebDriverAgent/compare/v5.8.1...v5.8.2) (2023-08-28) diff --git a/package.json b/package.json index b35df82fb..a1c2045ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.8.2", + "version": "5.8.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 1af64b8834371a3fdb3d0aab82fdfdeff6194555 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 10:21:40 -0700 Subject: [PATCH 071/133] chore(deps-dev): bump @types/teen_process from 2.0.0 to 2.0.1 (#765) Bumps [@types/teen_process](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/teen_process) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/teen_process) --- updated-dependencies: - dependency-name: "@types/teen_process" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a1c2045ac..4b3a65883 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@types/node": "^20.4.7", "@types/sinon": "^10.0.16", "@types/sinon-chai": "^3.2.9", - "@types/teen_process": "2.0.0", + "@types/teen_process": "2.0.1", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "appium-xcode": "^5.0.0", From 10ac5a5ec473c33e4e21791161e3686aa241e3a2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 14 Sep 2023 17:29:44 +0000 Subject: [PATCH 072/133] chore(release): 5.8.4 [skip ci] ## [5.8.4](https://github.com/appium/WebDriverAgent/compare/v5.8.3...v5.8.4) (2023-09-14) ### Miscellaneous Chores * **deps-dev:** bump @types/teen_process from 2.0.0 to 2.0.1 ([#765](https://github.com/appium/WebDriverAgent/issues/765)) ([1af64b8](https://github.com/appium/WebDriverAgent/commit/1af64b8834371a3fdb3d0aab82fdfdeff6194555)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 311f82c73..57efb91e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.8.4](https://github.com/appium/WebDriverAgent/compare/v5.8.3...v5.8.4) (2023-09-14) + + +### Miscellaneous Chores + +* **deps-dev:** bump @types/teen_process from 2.0.0 to 2.0.1 ([#765](https://github.com/appium/WebDriverAgent/issues/765)) ([1af64b8](https://github.com/appium/WebDriverAgent/commit/1af64b8834371a3fdb3d0aab82fdfdeff6194555)) + ## [5.8.3](https://github.com/appium/WebDriverAgent/compare/v5.8.2...v5.8.3) (2023-09-01) diff --git a/package.json b/package.json index 4b3a65883..052bfd598 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.8.3", + "version": "5.8.4", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 2ffd187b2e8b3c1ed04537320179bdfe9f9635df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:38:13 -0700 Subject: [PATCH 073/133] chore(deps-dev): bump sinon from 15.2.0 to 16.0.0 (#766) Bumps [sinon](https://github.com/sinonjs/sinon) from 15.2.0 to 16.0.0. - [Release notes](https://github.com/sinonjs/sinon/releases) - [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md) - [Commits](https://github.com/sinonjs/sinon/compare/v15.2.0...v16.0.0) --- updated-dependencies: - dependency-name: sinon dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 052bfd598..2c9cf024a 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "pre-commit": "^1.2.2", "prettier": "^3.0.0", "semantic-release": "^21.1.0", - "sinon": "^15.0.0", + "sinon": "^16.0.0", "ts-node": "^10.9.1", "typescript": "^5.1.6" }, From 224cfbbb0a3cf6c2f6a593a5c60fb8dd424f5fe5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 15 Sep 2023 16:45:31 +0000 Subject: [PATCH 074/133] chore(release): 5.8.5 [skip ci] ## [5.8.5](https://github.com/appium/WebDriverAgent/compare/v5.8.4...v5.8.5) (2023-09-15) ### Miscellaneous Chores * **deps-dev:** bump sinon from 15.2.0 to 16.0.0 ([#766](https://github.com/appium/WebDriverAgent/issues/766)) ([2ffd187](https://github.com/appium/WebDriverAgent/commit/2ffd187b2e8b3c1ed04537320179bdfe9f9635df)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57efb91e0..dba290295 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.8.5](https://github.com/appium/WebDriverAgent/compare/v5.8.4...v5.8.5) (2023-09-15) + + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 15.2.0 to 16.0.0 ([#766](https://github.com/appium/WebDriverAgent/issues/766)) ([2ffd187](https://github.com/appium/WebDriverAgent/commit/2ffd187b2e8b3c1ed04537320179bdfe9f9635df)) + ## [5.8.4](https://github.com/appium/WebDriverAgent/compare/v5.8.3...v5.8.4) (2023-09-14) diff --git a/package.json b/package.json index 2c9cf024a..b8dd1fcd9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.8.4", + "version": "5.8.5", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 3ec962842f121bb6dbfc28ab1b30f69d0adc0123 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 19 Sep 2023 04:07:47 -0400 Subject: [PATCH 075/133] ci: use Xcode 14.3 to build WDA (#770) * ci: use Xcode 14.3 to build WDA * use the same one in release --- .github/workflows/publish.js.yml | 4 ++-- .github/workflows/wda-package.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.js.yml b/.github/workflows/publish.js.yml index 6d1915ca7..6cd3a0276 100644 --- a/.github/workflows/publish.js.yml +++ b/.github/workflows/publish.js.yml @@ -10,10 +10,10 @@ on: jobs: build: - runs-on: macos-12 + runs-on: macos-13 env: - XCODE_VERSION: 14.2 + XCODE_VERSION: 14.3.1 ZIP_PKG_NAME_IOS: "WebDriverAgentRunner-Runner.zip" PKG_PATH_IOS: "appium_wda_ios" ZIP_PKG_NAME_TVOS: "WebDriverAgentRunner_tvOS-Runner.zip" diff --git a/.github/workflows/wda-package.yml b/.github/workflows/wda-package.yml index d544e927e..b4b4223f2 100644 --- a/.github/workflows/wda-package.yml +++ b/.github/workflows/wda-package.yml @@ -8,8 +8,8 @@ on: - completed env: - HOST: macos-12 - XCODE_VERSION: 14.2 + HOST: macos-13 + XCODE_VERSION: 14.3.1 DESTINATION_SIM: platform=iOS Simulator,name=iPhone 14 Pro DESTINATION_SIM_tvOS: platform=tvOS Simulator,name=Apple TV From 012af21383829397c7265daa0513829cc4e93aee Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 21 Sep 2023 16:38:50 -0700 Subject: [PATCH 076/133] chore: add log to leave it in the system log (#772) --- WebDriverAgentLib/Commands/FBSessionCommands.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 565939080..17153b8b5 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -421,6 +421,8 @@ + (NSDictionary *)sessionInformation + (NSDictionary *)currentCapabilities { FBApplication *application = [FBSession activeSession].activeApplication; + // to log the info in the system + [FBLogger logFmt:@"Current active application bundle id is %@", application.bundleID]; return @{ @"device": ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ? @"ipad" : @"iphone", From 49c135c7ee19336e68c4dca70e4e9eb0e1b2f56f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 21 Sep 2023 23:45:14 +0000 Subject: [PATCH 077/133] chore(release): 5.8.6 [skip ci] ## [5.8.6](https://github.com/appium/WebDriverAgent/compare/v5.8.5...v5.8.6) (2023-09-21) ### Miscellaneous Chores * add log to leave it in the system log ([#772](https://github.com/appium/WebDriverAgent/issues/772)) ([012af21](https://github.com/appium/WebDriverAgent/commit/012af21383829397c7265daa0513829cc4e93aee)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dba290295..12bb43640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.8.6](https://github.com/appium/WebDriverAgent/compare/v5.8.5...v5.8.6) (2023-09-21) + + +### Miscellaneous Chores + +* add log to leave it in the system log ([#772](https://github.com/appium/WebDriverAgent/issues/772)) ([012af21](https://github.com/appium/WebDriverAgent/commit/012af21383829397c7265daa0513829cc4e93aee)) + ## [5.8.5](https://github.com/appium/WebDriverAgent/compare/v5.8.4...v5.8.5) (2023-09-15) diff --git a/package.json b/package.json index b8dd1fcd9..fb268bf9e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.8.5", + "version": "5.8.6", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 8481b02fc84de1147e1254ea7fd114f8735b0226 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 21 Sep 2023 18:36:57 -0700 Subject: [PATCH 078/133] chore: tweak device in currentCapabilities (#773) * chore: tweak device * chore: tweak * keep lower case * Update FBSessionCommands.m --- .../Commands/FBSessionCommands.m | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 17153b8b5..7d8d3e077 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -257,7 +257,8 @@ + (NSArray *)routes #endif @"ip" : [XCUIDevice sharedDevice].fb_wifiIPAddress ?: [NSNull null] }, - @"build" : buildInfo.copy + @"build" : buildInfo.copy, + @"device": [self.class deviceNameByUserInterfaceIdiom:[UIDevice currentDevice].userInterfaceIdiom] } ); } @@ -418,6 +419,23 @@ + (NSDictionary *)sessionInformation }; } +/* + Return the device kind as lower case +*/ ++ (NSString *)deviceNameByUserInterfaceIdiom:(UIUserInterfaceIdiom) userInterfaceIdiom +{ + if (userInterfaceIdiom == UIUserInterfaceIdiomPad) { + return @"ipad"; + } else if (userInterfaceIdiom == UIUserInterfaceIdiomTV) { + return @"apple tv"; + } else if (userInterfaceIdiom == UIUserInterfaceIdiomPhone) { + return @"iphone"; + } + // CarPlay, Mac, Vision UI or unknown are possible + return @"Unknown"; + +} + + (NSDictionary *)currentCapabilities { FBApplication *application = [FBSession activeSession].activeApplication; @@ -425,7 +443,7 @@ + (NSDictionary *)currentCapabilities [FBLogger logFmt:@"Current active application bundle id is %@", application.bundleID]; return @{ - @"device": ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ? @"ipad" : @"iphone", + @"device": [self.class deviceNameByUserInterfaceIdiom:[UIDevice currentDevice].userInterfaceIdiom], @"sdkVersion": [[UIDevice currentDevice] systemVersion], @"browserName": application.label ?: [NSNull null], @"CFBundleIdentifier": application.bundleID ?: [NSNull null], From 5d2bd5fe4228cfa624f8700619879b62012ceca8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 22 Sep 2023 01:42:06 +0000 Subject: [PATCH 079/133] chore(release): 5.8.7 [skip ci] ## [5.8.7](https://github.com/appium/WebDriverAgent/compare/v5.8.6...v5.8.7) (2023-09-22) ### Miscellaneous Chores * tweak device in currentCapabilities ([#773](https://github.com/appium/WebDriverAgent/issues/773)) ([8481b02](https://github.com/appium/WebDriverAgent/commit/8481b02fc84de1147e1254ea7fd114f8735b0226)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12bb43640..946a76c6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.8.7](https://github.com/appium/WebDriverAgent/compare/v5.8.6...v5.8.7) (2023-09-22) + + +### Miscellaneous Chores + +* tweak device in currentCapabilities ([#773](https://github.com/appium/WebDriverAgent/issues/773)) ([8481b02](https://github.com/appium/WebDriverAgent/commit/8481b02fc84de1147e1254ea7fd114f8735b0226)) + ## [5.8.6](https://github.com/appium/WebDriverAgent/compare/v5.8.5...v5.8.6) (2023-09-21) diff --git a/package.json b/package.json index fb268bf9e..177169744 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.8.6", + "version": "5.8.7", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 2784ce440f8b5ab9710db08d9ffda704697ac07c Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 22 Sep 2023 11:18:11 -0700 Subject: [PATCH 080/133] feat: do not get active process information in a new session request (#774) * fix: improve new session creation performance * Update FBSessionCommands.m --- WebDriverAgentLib/Commands/FBSessionCommands.m | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 7d8d3e077..7bd87a768 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -410,6 +410,10 @@ + (NSString *)buildTimestamp ]; } +/** + Return current session information. + This response does not have any active application information. +*/ + (NSDictionary *)sessionInformation { return @@ -438,15 +442,10 @@ + (NSString *)deviceNameByUserInterfaceIdiom:(UIUserInterfaceIdiom) userInterfac + (NSDictionary *)currentCapabilities { - FBApplication *application = [FBSession activeSession].activeApplication; - // to log the info in the system - [FBLogger logFmt:@"Current active application bundle id is %@", application.bundleID]; return @{ @"device": [self.class deviceNameByUserInterfaceIdiom:[UIDevice currentDevice].userInterfaceIdiom], - @"sdkVersion": [[UIDevice currentDevice] systemVersion], - @"browserName": application.label ?: [NSNull null], - @"CFBundleIdentifier": application.bundleID ?: [NSNull null], + @"sdkVersion": [[UIDevice currentDevice] systemVersion] }; } From 40a81ebed7730b510b0eacb20d830687276ffb17 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 22 Sep 2023 18:41:08 +0000 Subject: [PATCH 081/133] chore(release): 5.9.0 [skip ci] ## [5.9.0](https://github.com/appium/WebDriverAgent/compare/v5.8.7...v5.9.0) (2023-09-22) ### Features * do not get active process information in a new session request ([#774](https://github.com/appium/WebDriverAgent/issues/774)) ([2784ce4](https://github.com/appium/WebDriverAgent/commit/2784ce440f8b5ab9710db08d9ffda704697ac07c)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 946a76c6f..aadb3e23c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.9.0](https://github.com/appium/WebDriverAgent/compare/v5.8.7...v5.9.0) (2023-09-22) + + +### Features + +* do not get active process information in a new session request ([#774](https://github.com/appium/WebDriverAgent/issues/774)) ([2784ce4](https://github.com/appium/WebDriverAgent/commit/2784ce440f8b5ab9710db08d9ffda704697ac07c)) + ## [5.8.7](https://github.com/appium/WebDriverAgent/compare/v5.8.6...v5.8.7) (2023-09-22) diff --git a/package.json b/package.json index 177169744..4559104ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.8.7", + "version": "5.9.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 51ba527b6cde3773ebcd5323cfa7e0890b2563aa Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 23 Sep 2023 01:03:00 +0200 Subject: [PATCH 082/133] fix: Provide signing arguments as command line parameters (#779) --- lib/utils.js | 16 ++-------------- lib/xcodebuild.js | 19 ++++++++++++------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 4a1191600..1474d929f 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,4 +1,4 @@ -import { fs, tempDir, plist } from '@appium/support'; +import { fs, plist } from '@appium/support'; import { exec } from 'teen_process'; import path from 'path'; import log from './logger'; @@ -157,18 +157,6 @@ async function setRealDeviceSecurity (keychainPath, keychainPassword) { await exec('security', ['set-keychain-settings', '-t', '3600', '-l', keychainPath]); } -async function generateXcodeConfigFile (orgId, signingId) { - log.debug(`Generating xcode config file for orgId '${orgId}' and signingId ` + - `'${signingId}'`); - const contents = `DEVELOPMENT_TEAM = ${orgId} -CODE_SIGN_IDENTITY = ${signingId} -`; - const xcconfigPath = await tempDir.path('appium-temp.xcconfig'); - log.debug(`Writing xcode config file to ${xcconfigPath}`); - await fs.writeFile(xcconfigPath, contents, 'utf8'); - return xcconfigPath; -} - /** * Information of the device under test * @typedef {Object} DeviceInfo @@ -394,7 +382,7 @@ async function getPIDsListeningOnPort (port, filteringFunc = null) { } export { updateProjectFile, resetProjectFile, setRealDeviceSecurity, - getAdditionalRunContent, getXctestrunFileName, generateXcodeConfigFile, + getAdditionalRunContent, getXctestrunFileName, setXctestrunFile, getXctestrunFilePath, killProcess, randomInt, getWDAUpgradeTimestamp, resetTestProcesses, getPIDsListeningOnPort, killAppUsingPattern, isTvOS diff --git a/lib/xcodebuild.js b/lib/xcodebuild.js index 23f365417..de6b58818 100644 --- a/lib/xcodebuild.js +++ b/lib/xcodebuild.js @@ -4,7 +4,7 @@ import { fs, logger, timing } from '@appium/support'; import defaultLogger from './logger'; import B from 'bluebird'; import { - setRealDeviceSecurity, generateXcodeConfigFile, setXctestrunFile, + setRealDeviceSecurity, setXctestrunFile, updateProjectFile, resetProjectFile, killProcess, getWDAUpgradeTimestamp, isTvOS } from './utils'; import _ from 'lodash'; @@ -238,9 +238,17 @@ class XcodeBuild { 'Will build for the default platform instead'); } - if (this.realDevice && this.xcodeConfigFile) { - this.log.debug(`Using Xcode configuration file: '${this.xcodeConfigFile}'`); - args.push('-xcconfig', this.xcodeConfigFile); + if (this.realDevice) { + if (this.xcodeConfigFile) { + this.log.debug(`Using Xcode configuration file: '${this.xcodeConfigFile}'`); + args.push('-xcconfig', this.xcodeConfigFile); + } + if (this.xcodeOrgId && this.xcodeSigningId) { + args.push( + `DEVELOPMENT_TEAM=${this.xcodeOrgId}`, + `CODE_SIGN_IDENTITY=${this.xcodeSigningId}`, + ); + } } if (!process.env.APPIUM_XCUITEST_TREAT_WARNINGS_AS_ERRORS) { @@ -260,9 +268,6 @@ class XcodeBuild { if (this.keychainPath && this.keychainPassword) { await setRealDeviceSecurity(this.keychainPath, this.keychainPassword); } - if (this.xcodeOrgId && this.xcodeSigningId && !this.xcodeConfigFile) { - this.xcodeConfigFile = await generateXcodeConfigFile(this.xcodeOrgId, this.xcodeSigningId); - } } const {cmd, args} = this.getCommand(buildOnly); From adf14cc7f6e3a26448315e07a3621bdac7c4aa24 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 22 Sep 2023 23:09:21 +0000 Subject: [PATCH 083/133] chore(release): 5.9.1 [skip ci] ## [5.9.1](https://github.com/appium/WebDriverAgent/compare/v5.9.0...v5.9.1) (2023-09-22) ### Bug Fixes * Provide signing arguments as command line parameters ([#779](https://github.com/appium/WebDriverAgent/issues/779)) ([51ba527](https://github.com/appium/WebDriverAgent/commit/51ba527b6cde3773ebcd5323cfa7e0890b2563aa)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aadb3e23c..26faf0900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.9.1](https://github.com/appium/WebDriverAgent/compare/v5.9.0...v5.9.1) (2023-09-22) + + +### Bug Fixes + +* Provide signing arguments as command line parameters ([#779](https://github.com/appium/WebDriverAgent/issues/779)) ([51ba527](https://github.com/appium/WebDriverAgent/commit/51ba527b6cde3773ebcd5323cfa7e0890b2563aa)) + ## [5.9.0](https://github.com/appium/WebDriverAgent/compare/v5.8.7...v5.9.0) (2023-09-22) diff --git a/package.json b/package.json index 4559104ad..04337817f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.9.0", + "version": "5.9.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From ae6c842f3c4e7deb51fcc7a1a1045d4eeede69fd Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 25 Sep 2023 16:52:16 -0700 Subject: [PATCH 084/133] feat: remove test frameworks in Frameworks and add device local references as rpath for real devices (#780) * ci: use xcode 15 * Remove embedded frameworks * Update wda-package.yml * tweak * keep using 14.3.1 * explicitly set ENABLE_TESTING_SEARCH_PATHS as YES * add system reference * add FBUtf8SafeDictionary for tv as well * Update publish.js.yml --- .github/workflows/publish.js.yml | 6 ++- Scripts/ci/build-real.sh | 6 +++ WebDriverAgent.xcodeproj/project.pbxproj | 47 ++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish.js.yml b/.github/workflows/publish.js.yml index 6cd3a0276..92299e7a8 100644 --- a/.github/workflows/publish.js.yml +++ b/.github/workflows/publish.js.yml @@ -44,9 +44,10 @@ jobs: -scheme WebDriverAgentRunner \ -destination generic/platform=iOS \ CODE_SIGNING_ALLOWED=NO ARCHS=arm64 - - name: Creating a zip of WebDriverAgentRunner-Runner.app for iOS + - name: Creating a zip of WebDriverAgentRunner-Runner.app for iOS after removing test frameworks run: | pushd appium_wda_ios/Build/Products/Debug-iphoneos + rm -rf WebDriverAgentRunner-Runner.app/Frameworks/XC*.framework zip -r $ZIP_PKG_NAME_IOS WebDriverAgentRunner-Runner.app popd mv $PKG_PATH_IOS/Build/Products/Debug-iphoneos/$ZIP_PKG_NAME_IOS ./ @@ -58,9 +59,10 @@ jobs: -scheme WebDriverAgentRunner_tvOS \ -destination generic/platform=tvOS \ CODE_SIGNING_ALLOWED=NO ARCHS=arm64 - - name: Creating a zip of WebDriverAgentRunner-Runner.app for tvOS + - name: Creating a zip of WebDriverAgentRunner-Runner.app for tvOS after removing test frameworks run: | pushd appium_wda_tvos/Build/Products/Debug-appletvos + rm -rf WebDriverAgentRunner_tvOS-Runner.app/Frameworks/XC*.framework zip -r $ZIP_PKG_NAME_TVOS WebDriverAgentRunner_tvOS-Runner.app popd mv $PKG_PATH_TVOS/Build/Products/Debug-appletvos/$ZIP_PKG_NAME_TVOS ./ diff --git a/Scripts/ci/build-real.sh b/Scripts/ci/build-real.sh index 9303ffe3b..93eec1145 100755 --- a/Scripts/ci/build-real.sh +++ b/Scripts/ci/build-real.sh @@ -12,6 +12,12 @@ xcodebuild clean build-for-testing \ # Only .app is needed. pushd $WD + +# to remove test packages to refer to the device local instead of embedded ones +# XCTAutomationSupport.framework, XCTest.framewor, XCTestCore.framework, +# XCUIAutomation.framework, XCUnit.framework +rm -rf $SCHEME-Runner.app/Frameworks/XC*.framework + zip -r $ZIP_PKG_NAME $SCHEME-Runner.app popd mv $WD/$ZIP_PKG_NAME ./ diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index a5b933127..3630797a6 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -312,6 +312,8 @@ 64B26508228C5514002A5025 /* XCUIElementDouble.m in Sources */ = {isa = PBXBuildFile; fileRef = 64B26507228C5514002A5025 /* XCUIElementDouble.m */; }; 64B2650A228CE4FF002A5025 /* FBTVNavigationTracker-Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 64B26509228CE4FF002A5025 /* FBTVNavigationTracker-Private.h */; }; 64B2650B228CE4FF002A5025 /* FBTVNavigationTracker-Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 64B26509228CE4FF002A5025 /* FBTVNavigationTracker-Private.h */; }; + 64E3502E2AC0B6EB005F3ACB /* NSDictionary+FBUtf8SafeDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 716F0DA02A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m */; }; + 64E3502F2AC0B6FE005F3ACB /* NSDictionary+FBUtf8SafeDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */; }; 711084441DA3AA7500F913D6 /* FBXPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 711084421DA3AA7500F913D6 /* FBXPath.h */; settings = {ATTRIBUTES = (Public, ); }; }; 711084451DA3AA7500F913D6 /* FBXPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 711084431DA3AA7500F913D6 /* FBXPath.m */; }; 7119097C2152580600BA3C7E /* XCUIScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 7119097B2152580600BA3C7E /* XCUIScreen.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -2382,6 +2384,7 @@ 641EE6A62240C5CA00173FCB /* FBImageIOScaler.h in Headers */, 641EE6A72240C5CA00173FCB /* FBSession-Private.h in Headers */, 641EE6A82240C5CA00173FCB /* NSString+FBXMLSafeString.h in Headers */, + 64E3502F2AC0B6FE005F3ACB /* NSDictionary+FBUtf8SafeDictionary.h in Headers */, 641EE6A92240C5CA00173FCB /* FBCommandStatus.h in Headers */, 71822702258744A400661B83 /* HTTPResponseProxy.h in Headers */, 71822741258744BB00661B83 /* HTTPLogging.h in Headers */, @@ -2414,7 +2417,6 @@ 641EE6C02240C5CA00173FCB /* XCUIApplication+FBHelpers.h in Headers */, 641EE6C12240C5CA00173FCB /* _XCTestObservationCenterImplementation.h in Headers */, 714EAA0E2673FDFE005C5B47 /* FBCapabilities.h in Headers */, - 716F0DA22A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h in Headers */, 641EE6C22240C5CA00173FCB /* XCUIDevice+FBHelpers.h in Headers */, 71D3B3D6267FC7260076473D /* XCUIElement+FBResolve.h in Headers */, 641EE6C32240C5CA00173FCB /* FBClassChainQueryParser.h in Headers */, @@ -3049,6 +3051,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 64E3502E2AC0B6EB005F3ACB /* NSDictionary+FBUtf8SafeDictionary.m in Sources */, 718226CF2587443700661B83 /* GCDAsyncSocket.m in Sources */, E444DCBC24917A5E0060D7EB /* HTTPResponseProxy.m in Sources */, 71D3B3D8267FC7260076473D /* XCUIElement+FBResolve.m in Sources */, @@ -3117,7 +3120,6 @@ 641EE5FF2240C5CA00173FCB /* XCUIElement+FBForceTouch.m in Sources */, 716C9E0327315EFF005AD475 /* XCUIApplication+FBUIInterruptions.m in Sources */, 641EE6002240C5CA00173FCB /* FBTouchActionCommands.m in Sources */, - 716F0DA42A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m in Sources */, 719DCF182601EAFB000E765F /* FBNotificationsHelper.m in Sources */, 714EAA102673FDFE005C5B47 /* FBCapabilities.m in Sources */, 641EE6012240C5CA00173FCB /* FBImageIOScaler.m in Sources */, @@ -3172,7 +3174,6 @@ buildActionMask = 2147483647; files = ( 64B26508228C5514002A5025 /* XCUIElementDouble.m in Sources */, - 716F0DA72A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m in Sources */, 64B26504228C5299002A5025 /* FBTVNavigationTrackerTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3496,12 +3497,17 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_TESTING_SEARCH_PATHS = YES; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = WebDriverAgentRunner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + /System/Developer/Library/Frameworks, + /System/Developer/Library/PrivateFrameworks, + /Developer/Library/PrivateFrameworks, + /Developer/Library/Frameworks, ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -3551,12 +3557,17 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_TESTING_SEARCH_PATHS = YES; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = WebDriverAgentRunner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + /System/Developer/Library/Frameworks, + /System/Developer/Library/PrivateFrameworks, + /Developer/Library/PrivateFrameworks, + /Developer/Library/Frameworks, ); MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -3603,6 +3614,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_TESTING_SEARCH_PATHS = YES; FRAMEWORK_SEARCH_PATHS = ( "$(PLATFORM_DIR)/Developer/Library/Frameworks", "$(PLATFORM_DIR)/Developer/Library/PrivateFrameworks", @@ -3614,6 +3626,10 @@ "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + /System/Developer/Library/Frameworks, + /System/Developer/Library/PrivateFrameworks, + /Developer/Library/PrivateFrameworks, + /Developer/Library/Frameworks, ); OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.WebDriverAgentLib; @@ -3664,6 +3680,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_TESTING_SEARCH_PATHS = YES; FRAMEWORK_SEARCH_PATHS = ( "$(PLATFORM_DIR)/Developer/Library/Frameworks", "$(PLATFORM_DIR)/Developer/Library/PrivateFrameworks", @@ -3675,6 +3692,10 @@ "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + /System/Developer/Library/Frameworks, + /System/Developer/Library/PrivateFrameworks, + /Developer/Library/PrivateFrameworks, + /Developer/Library/Frameworks, ); ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; @@ -3915,6 +3936,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_TESTING_SEARCH_PATHS = YES; FRAMEWORK_SEARCH_PATHS = ( "$(PLATFORM_DIR)/Developer/Library/Frameworks", "$(PLATFORM_DIR)/Developer/Library/PrivateFrameworks", @@ -3926,6 +3948,10 @@ "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + /Developer/Library/Frameworks, + /Developer/Library/PrivateFrameworks, + /System/Developer/Library/PrivateFrameworks, + /System/Developer/Library/Frameworks, ); OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.WebDriverAgentLib; @@ -3974,6 +4000,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_TESTING_SEARCH_PATHS = YES; FRAMEWORK_SEARCH_PATHS = ( "$(PLATFORM_DIR)/Developer/Library/Frameworks", "$(PLATFORM_DIR)/Developer/Library/PrivateFrameworks", @@ -3985,6 +4012,10 @@ "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + /Developer/Library/Frameworks, + /Developer/Library/PrivateFrameworks, + /System/Developer/Library/PrivateFrameworks, + /System/Developer/Library/Frameworks, ); ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; @@ -4212,12 +4243,17 @@ buildSettings = { CLANG_STATIC_ANALYZER_MODE = deep; DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTING_SEARCH_PATHS = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = WebDriverAgentRunner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + /Developer/Library/Frameworks, + /Developer/Library/PrivateFrameworks, + /System/Developer/Library/PrivateFrameworks, + /System/Developer/Library/Frameworks, ); OTHER_LDFLAGS = ( "$(inherited)", @@ -4259,12 +4295,17 @@ baseConfigurationReference = EEE5CABF1C80361500CBBDD9 /* IOSSettings.xcconfig */; buildSettings = { CLANG_STATIC_ANALYZER_MODE = deep; + ENABLE_TESTING_SEARCH_PATHS = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = WebDriverAgentRunner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", + /Developer/Library/Frameworks, + /Developer/Library/PrivateFrameworks, + /System/Developer/Library/PrivateFrameworks, + /System/Developer/Library/Frameworks, ); ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( From 7b2c1e58a91c69e66e7403b4b9d262537e164c3b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 25 Sep 2023 23:58:30 +0000 Subject: [PATCH 085/133] chore(release): 5.10.0 [skip ci] ## [5.10.0](https://github.com/appium/WebDriverAgent/compare/v5.9.1...v5.10.0) (2023-09-25) ### Features * remove test frameworks in Frameworks and add device local references as rpath for real devices ([#780](https://github.com/appium/WebDriverAgent/issues/780)) ([ae6c842](https://github.com/appium/WebDriverAgent/commit/ae6c842f3c4e7deb51fcc7a1a1045d4eeede69fd)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26faf0900..2f1e109ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.10.0](https://github.com/appium/WebDriverAgent/compare/v5.9.1...v5.10.0) (2023-09-25) + + +### Features + +* remove test frameworks in Frameworks and add device local references as rpath for real devices ([#780](https://github.com/appium/WebDriverAgent/issues/780)) ([ae6c842](https://github.com/appium/WebDriverAgent/commit/ae6c842f3c4e7deb51fcc7a1a1045d4eeede69fd)) + ## [5.9.1](https://github.com/appium/WebDriverAgent/compare/v5.9.0...v5.9.1) (2023-09-22) diff --git a/package.json b/package.json index 04337817f..d29c29436 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.9.1", + "version": "5.10.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From f043d67dd90fbfca00b8cf53ccae63dbd67fa150 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 5 Oct 2023 10:36:30 +0200 Subject: [PATCH 086/133] chore: Remove the hardcoded keyboard wait delay from handleKeys (#784) --- WebDriverAgentLib/Commands/FBElementCommands.m | 5 ----- 1 file changed, 5 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index adb5f6092..0f163521b 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -557,11 +557,6 @@ + (NSArray *)routes { NSString *textToType = [request.arguments[@"value"] componentsJoinedByString:@""]; NSUInteger frequency = [request.arguments[@"frequency"] unsignedIntegerValue] ?: [FBConfiguration maxTypingFrequency]; - if (![FBKeyboard waitUntilVisibleForApplication:request.session.activeApplication - timeout:1 - error:nil]) { - [FBLogger log:@"The on-screen keyboard seems to not exist. Continuing with typing anyway"]; - } NSError *error; if (![FBKeyboard typeText:textToType frequency:frequency error:&error]) { return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description From 570866edde713b344efb423b1e3eccf26c7ebab0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 5 Oct 2023 08:42:01 +0000 Subject: [PATCH 087/133] chore(release): 5.10.1 [skip ci] ## [5.10.1](https://github.com/appium/WebDriverAgent/compare/v5.10.0...v5.10.1) (2023-10-05) ### Miscellaneous Chores * Remove the hardcoded keyboard wait delay from handleKeys ([#784](https://github.com/appium/WebDriverAgent/issues/784)) ([f043d67](https://github.com/appium/WebDriverAgent/commit/f043d67dd90fbfca00b8cf53ccae63dbd67fa150)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f1e109ea..f679c40ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.10.1](https://github.com/appium/WebDriverAgent/compare/v5.10.0...v5.10.1) (2023-10-05) + + +### Miscellaneous Chores + +* Remove the hardcoded keyboard wait delay from handleKeys ([#784](https://github.com/appium/WebDriverAgent/issues/784)) ([f043d67](https://github.com/appium/WebDriverAgent/commit/f043d67dd90fbfca00b8cf53ccae63dbd67fa150)) + ## [5.10.0](https://github.com/appium/WebDriverAgent/compare/v5.9.1...v5.10.0) (2023-09-25) diff --git a/package.json b/package.json index d29c29436..b97e25626 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.10.0", + "version": "5.10.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From ae1603a3b5b5c4828ed4959c63d6274254f832a2 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 5 Oct 2023 22:13:00 +0200 Subject: [PATCH 088/133] feat: Add /calibrate endpoint (#785) --- WebDriverAgentLib/Routing/FBWebServer.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/WebDriverAgentLib/Routing/FBWebServer.m b/WebDriverAgentLib/Routing/FBWebServer.m index a9b9a0625..7e991e0e2 100644 --- a/WebDriverAgentLib/Routing/FBWebServer.m +++ b/WebDriverAgentLib/Routing/FBWebServer.m @@ -220,6 +220,16 @@ - (void)registerServerKeyRouteHandlers [response respondWithString:@"I-AM-ALIVE"]; }]; + NSString *calibrationPage = @"" + "{\"x\":null,\"y\":null}" + "
" + "" + "
" + ""; + [self.server get:@"/calibrate" withBlock:^(RouteRequest *request, RouteResponse *response) { + [response respondWithString:calibrationPage]; + }]; + [self.server get:@"/wda/shutdown" withBlock:^(RouteRequest *request, RouteResponse *response) { [response respondWithString:@"Shutting down"]; [self.delegate webServerDidRequestShutdown:self]; From a9ced34da71c80a7654358043be37f02af7a1508 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 5 Oct 2023 20:32:08 +0000 Subject: [PATCH 089/133] chore(release): 5.11.0 [skip ci] ## [5.11.0](https://github.com/appium/WebDriverAgent/compare/v5.10.1...v5.11.0) (2023-10-05) ### Features * Add /calibrate endpoint ([#785](https://github.com/appium/WebDriverAgent/issues/785)) ([ae1603a](https://github.com/appium/WebDriverAgent/commit/ae1603a3b5b5c4828ed4959c63d6274254f832a2)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f679c40ad..23f5fd036 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.11.0](https://github.com/appium/WebDriverAgent/compare/v5.10.1...v5.11.0) (2023-10-05) + + +### Features + +* Add /calibrate endpoint ([#785](https://github.com/appium/WebDriverAgent/issues/785)) ([ae1603a](https://github.com/appium/WebDriverAgent/commit/ae1603a3b5b5c4828ed4959c63d6274254f832a2)) + ## [5.10.1](https://github.com/appium/WebDriverAgent/compare/v5.10.0...v5.10.1) (2023-10-05) diff --git a/package.json b/package.json index b97e25626..67a6d23e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.10.1", + "version": "5.11.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 123eefba5e5e30100cb3cdff09a516179f78afe7 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 19 Oct 2023 15:39:14 +0200 Subject: [PATCH 090/133] chore: Use latest types version --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 67a6d23e6..62dee72a5 100644 --- a/package.json +++ b/package.json @@ -56,10 +56,10 @@ "homepage": "https://github.com/appium/WebDriverAgent#readme", "devDependencies": { "@appium/eslint-config-appium": "^8.0.4", - "@appium/eslint-config-appium-ts": "^0.3.1", + "@appium/eslint-config-appium-ts": "^0.x", "@appium/test-support": "^3.0.0", - "@appium/tsconfig": "^0.3.0", - "@appium/types": "^0.13.2", + "@appium/tsconfig": "^0.x", + "@appium/types": "^0.x", "@semantic-release/changelog": "^6.0.1", "@semantic-release/git": "^10.0.1", "@types/bluebird": "^3.5.38", From 1fb0c4fb7d8de0249dbafde3a563a275477bcd51 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 19 Oct 2023 15:33:00 +0000 Subject: [PATCH 091/133] chore(release): 5.11.1 [skip ci] ## [5.11.1](https://github.com/appium/WebDriverAgent/compare/v5.11.0...v5.11.1) (2023-10-19) ### Miscellaneous Chores * Use latest types version ([123eefb](https://github.com/appium/WebDriverAgent/commit/123eefba5e5e30100cb3cdff09a516179f78afe7)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23f5fd036..588587618 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.11.1](https://github.com/appium/WebDriverAgent/compare/v5.11.0...v5.11.1) (2023-10-19) + + +### Miscellaneous Chores + +* Use latest types version ([123eefb](https://github.com/appium/WebDriverAgent/commit/123eefba5e5e30100cb3cdff09a516179f78afe7)) + ## [5.11.0](https://github.com/appium/WebDriverAgent/compare/v5.10.1...v5.11.0) (2023-10-05) diff --git a/package.json b/package.json index 62dee72a5..bb8c4bcdb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.11.0", + "version": "5.11.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 895cdfc1a316117bb7c8b5be0265b439c1e911bc Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 19 Oct 2023 17:40:34 +0200 Subject: [PATCH 092/133] chore: Use latest teen_process types --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bb8c4bcdb..b1f5abf9a 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@types/node": "^20.4.7", "@types/sinon": "^10.0.16", "@types/sinon-chai": "^3.2.9", - "@types/teen_process": "2.0.1", + "@types/teen_process": "^2.0.1", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "appium-xcode": "^5.0.0", From 18e1dadf5bcdebeb18f25c683c317330af08d479 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 19 Oct 2023 23:09:42 +0000 Subject: [PATCH 093/133] chore(release): 5.11.2 [skip ci] ## [5.11.2](https://github.com/appium/WebDriverAgent/compare/v5.11.1...v5.11.2) (2023-10-19) ### Miscellaneous Chores * Use latest teen_process types ([895cdfc](https://github.com/appium/WebDriverAgent/commit/895cdfc1a316117bb7c8b5be0265b439c1e911bc)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 588587618..178875429 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.11.2](https://github.com/appium/WebDriverAgent/compare/v5.11.1...v5.11.2) (2023-10-19) + + +### Miscellaneous Chores + +* Use latest teen_process types ([895cdfc](https://github.com/appium/WebDriverAgent/commit/895cdfc1a316117bb7c8b5be0265b439c1e911bc)) + ## [5.11.1](https://github.com/appium/WebDriverAgent/compare/v5.11.0...v5.11.1) (2023-10-19) diff --git a/package.json b/package.json index b1f5abf9a..fccb85615 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.11.1", + "version": "5.11.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 543c49860d2d35148bcbaa33e14d3e1dab058cef Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 21 Oct 2023 11:44:58 -0700 Subject: [PATCH 094/133] chore: use PRODUCT_BUNDLE_IDENTIFIER to info.plist (#794) --- WebDriverAgentRunner/Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebDriverAgentRunner/Info.plist b/WebDriverAgentRunner/Info.plist index 70c8682fd..0b10cd4f3 100644 --- a/WebDriverAgentRunner/Info.plist +++ b/WebDriverAgentRunner/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.wda.runner + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName From 651d2bb06c9f901edb89b6f9c63ba600208ddaaf Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 21 Oct 2023 18:52:42 +0000 Subject: [PATCH 095/133] chore(release): 5.11.3 [skip ci] ## [5.11.3](https://github.com/appium/WebDriverAgent/compare/v5.11.2...v5.11.3) (2023-10-21) ### Miscellaneous Chores * use PRODUCT_BUNDLE_IDENTIFIER to info.plist ([#794](https://github.com/appium/WebDriverAgent/issues/794)) ([543c498](https://github.com/appium/WebDriverAgent/commit/543c49860d2d35148bcbaa33e14d3e1dab058cef)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 178875429..3b320b852 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.11.3](https://github.com/appium/WebDriverAgent/compare/v5.11.2...v5.11.3) (2023-10-21) + + +### Miscellaneous Chores + +* use PRODUCT_BUNDLE_IDENTIFIER to info.plist ([#794](https://github.com/appium/WebDriverAgent/issues/794)) ([543c498](https://github.com/appium/WebDriverAgent/commit/543c49860d2d35148bcbaa33e14d3e1dab058cef)) + ## [5.11.2](https://github.com/appium/WebDriverAgent/compare/v5.11.1...v5.11.2) (2023-10-19) diff --git a/package.json b/package.json index fccb85615..097d7ced6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.11.2", + "version": "5.11.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 4921899d96800dbcd59a9c27ba793ad16d0c715b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 20:17:16 +0200 Subject: [PATCH 096/133] chore(deps-dev): bump sinon from 16.1.3 to 17.0.0 (#795) Bumps [sinon](https://github.com/sinonjs/sinon) from 16.1.3 to 17.0.0. - [Release notes](https://github.com/sinonjs/sinon/releases) - [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md) - [Commits](https://github.com/sinonjs/sinon/compare/v16.1.3...v17.0.0) --- updated-dependencies: - dependency-name: sinon dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 097d7ced6..0b7d67eae 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "pre-commit": "^1.2.2", "prettier": "^3.0.0", "semantic-release": "^21.1.0", - "sinon": "^16.0.0", + "sinon": "^17.0.0", "ts-node": "^10.9.1", "typescript": "^5.1.6" }, From d99c79b254f4e83d9de85eac7dd5dd08aab85284 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 23 Oct 2023 20:41:43 +0000 Subject: [PATCH 097/133] chore(release): 5.11.4 [skip ci] ## [5.11.4](https://github.com/appium/WebDriverAgent/compare/v5.11.3...v5.11.4) (2023-10-23) ### Miscellaneous Chores * **deps-dev:** bump sinon from 16.1.3 to 17.0.0 ([#795](https://github.com/appium/WebDriverAgent/issues/795)) ([4921899](https://github.com/appium/WebDriverAgent/commit/4921899d96800dbcd59a9c27ba793ad16d0c715b)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b320b852..dc0c66b0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.11.4](https://github.com/appium/WebDriverAgent/compare/v5.11.3...v5.11.4) (2023-10-23) + + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 16.1.3 to 17.0.0 ([#795](https://github.com/appium/WebDriverAgent/issues/795)) ([4921899](https://github.com/appium/WebDriverAgent/commit/4921899d96800dbcd59a9c27ba793ad16d0c715b)) + ## [5.11.3](https://github.com/appium/WebDriverAgent/compare/v5.11.2...v5.11.3) (2023-10-21) diff --git a/package.json b/package.json index 0b7d67eae..90fe1b65b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.11.3", + "version": "5.11.4", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 440279d4f6d069e440180faf4bee8e5dc1758787 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 23:41:47 +0200 Subject: [PATCH 098/133] chore(deps-dev): bump lint-staged from 14.0.1 to 15.0.2 (#792) Bumps [lint-staged](https://github.com/okonet/lint-staged) from 14.0.1 to 15.0.2. - [Release notes](https://github.com/okonet/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/master/CHANGELOG.md) - [Commits](https://github.com/okonet/lint-staged/compare/v14.0.1...v15.0.2) --- updated-dependencies: - dependency-name: lint-staged dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 90fe1b65b..3fd1bb791 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "eslint-plugin-import": "^2.28.0", "eslint-plugin-mocha": "^10.1.0", "eslint-plugin-promise": "^6.1.1", - "lint-staged": "^14.0.0", + "lint-staged": "^15.0.2", "mocha": "^10.0.0", "pre-commit": "^1.2.2", "prettier": "^3.0.0", From f130961f189f2746d4a2b0a18105fc10203312ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 23:42:02 +0200 Subject: [PATCH 099/133] chore(deps-dev): bump eslint-config-prettier from 8.10.0 to 9.0.0 (#791) Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.10.0 to 9.0.0. - [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.10.0...v9.0.0) --- updated-dependencies: - dependency-name: eslint-config-prettier dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3fd1bb791..c09665648 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "chai-as-promised": "^7.1.1", "conventional-changelog-conventionalcommits": "^7.0.1", "eslint": "^8.46.0", - "eslint-config-prettier": "^8.9.0", + "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.28.0", "eslint-plugin-mocha": "^10.1.0", From a96718308dbd6b13feb30e6ce8f01a7d9b74b146 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 23:42:20 +0200 Subject: [PATCH 100/133] chore(deps-dev): bump semantic-release from 21.1.2 to 22.0.5 (#781) Bumps [semantic-release](https://github.com/semantic-release/semantic-release) from 21.1.2 to 22.0.5. - [Release notes](https://github.com/semantic-release/semantic-release/releases) - [Commits](https://github.com/semantic-release/semantic-release/compare/v21.1.2...v22.0.5) --- updated-dependencies: - dependency-name: semantic-release dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c09665648..0466d7f54 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "mocha": "^10.0.0", "pre-commit": "^1.2.2", "prettier": "^3.0.0", - "semantic-release": "^21.1.0", + "semantic-release": "^22.0.5", "sinon": "^17.0.0", "ts-node": "^10.9.1", "typescript": "^5.1.6" From 8f8e582c4f8b51e878791ddbd7f1dac47555ab23 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 23 Oct 2023 23:44:22 +0000 Subject: [PATCH 101/133] chore(release): 5.11.5 [skip ci] ## [5.11.5](https://github.com/appium/WebDriverAgent/compare/v5.11.4...v5.11.5) (2023-10-23) ### Miscellaneous Chores * **deps-dev:** bump eslint-config-prettier from 8.10.0 to 9.0.0 ([#791](https://github.com/appium/WebDriverAgent/issues/791)) ([f130961](https://github.com/appium/WebDriverAgent/commit/f130961f189f2746d4a2b0a18105fc10203312ca)) * **deps-dev:** bump lint-staged from 14.0.1 to 15.0.2 ([#792](https://github.com/appium/WebDriverAgent/issues/792)) ([440279d](https://github.com/appium/WebDriverAgent/commit/440279d4f6d069e440180faf4bee8e5dc1758787)) * **deps-dev:** bump semantic-release from 21.1.2 to 22.0.5 ([#781](https://github.com/appium/WebDriverAgent/issues/781)) ([a967183](https://github.com/appium/WebDriverAgent/commit/a96718308dbd6b13feb30e6ce8f01a7d9b74b146)) --- CHANGELOG.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc0c66b0b..01869dbf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [5.11.5](https://github.com/appium/WebDriverAgent/compare/v5.11.4...v5.11.5) (2023-10-23) + + +### Miscellaneous Chores + +* **deps-dev:** bump eslint-config-prettier from 8.10.0 to 9.0.0 ([#791](https://github.com/appium/WebDriverAgent/issues/791)) ([f130961](https://github.com/appium/WebDriverAgent/commit/f130961f189f2746d4a2b0a18105fc10203312ca)) +* **deps-dev:** bump lint-staged from 14.0.1 to 15.0.2 ([#792](https://github.com/appium/WebDriverAgent/issues/792)) ([440279d](https://github.com/appium/WebDriverAgent/commit/440279d4f6d069e440180faf4bee8e5dc1758787)) +* **deps-dev:** bump semantic-release from 21.1.2 to 22.0.5 ([#781](https://github.com/appium/WebDriverAgent/issues/781)) ([a967183](https://github.com/appium/WebDriverAgent/commit/a96718308dbd6b13feb30e6ce8f01a7d9b74b146)) + ## [5.11.4](https://github.com/appium/WebDriverAgent/compare/v5.11.3...v5.11.4) (2023-10-23) diff --git a/package.json b/package.json index 0466d7f54..1bdb2802e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.11.4", + "version": "5.11.5", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From e2f4405a3449f1f4d390eae06bf91a220e81b58b Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 25 Oct 2023 11:08:27 -0700 Subject: [PATCH 102/133] chore: disable debugger for wda (#768) --- .../xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme | 4 ++-- .../xcshareddata/xcschemes/WebDriverAgentRunner_tvOS.xcscheme | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme b/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme index 82f803a90..8857b934c 100644 --- a/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme +++ b/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme @@ -24,8 +24,8 @@ diff --git a/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner_tvOS.xcscheme b/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner_tvOS.xcscheme index 198d2e6cc..e55655225 100644 --- a/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner_tvOS.xcscheme +++ b/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner_tvOS.xcscheme @@ -24,8 +24,8 @@ From b2b6de43ab448d359f92adfb8dc0b6de302de827 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 25 Oct 2023 19:24:31 +0000 Subject: [PATCH 103/133] chore(release): 5.11.6 [skip ci] ## [5.11.6](https://github.com/appium/WebDriverAgent/compare/v5.11.5...v5.11.6) (2023-10-25) ### Miscellaneous Chores * disable debugger for wda ([#768](https://github.com/appium/WebDriverAgent/issues/768)) ([e2f4405](https://github.com/appium/WebDriverAgent/commit/e2f4405a3449f1f4d390eae06bf91a220e81b58b)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01869dbf2..161e35a0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.11.6](https://github.com/appium/WebDriverAgent/compare/v5.11.5...v5.11.6) (2023-10-25) + + +### Miscellaneous Chores + +* disable debugger for wda ([#768](https://github.com/appium/WebDriverAgent/issues/768)) ([e2f4405](https://github.com/appium/WebDriverAgent/commit/e2f4405a3449f1f4d390eae06bf91a220e81b58b)) + ## [5.11.5](https://github.com/appium/WebDriverAgent/compare/v5.11.4...v5.11.5) (2023-10-23) diff --git a/package.json b/package.json index 1bdb2802e..bd447f321 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.11.5", + "version": "5.11.6", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From dabf141acd3186b1c27231ef52826fa42208c980 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:44:50 +0200 Subject: [PATCH 104/133] chore(deps-dev): bump @typescript-eslint/eslint-plugin from 5.62.0 to 6.9.0 (#796) * chore(deps-dev): bump @typescript-eslint/eslint-plugin Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.62.0 to 6.9.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.9.0/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@typescript-eslint/eslint-plugin" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Bump parser --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mykola Mokhnach --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index bd447f321..8f668c0c0 100644 --- a/package.json +++ b/package.json @@ -71,8 +71,8 @@ "@types/sinon": "^10.0.16", "@types/sinon-chai": "^3.2.9", "@types/teen_process": "^2.0.1", - "@typescript-eslint/eslint-plugin": "^5.62.0", - "@typescript-eslint/parser": "^5.62.0", + "@typescript-eslint/eslint-plugin": "^6.9.0", + "@typescript-eslint/parser": "^6.9.0", "appium-xcode": "^5.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", From ea6fb73f4906f33697e2877361f800a69c0effbc Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 25 Oct 2023 20:52:59 +0000 Subject: [PATCH 105/133] chore(release): 5.11.7 [skip ci] ## [5.11.7](https://github.com/appium/WebDriverAgent/compare/v5.11.6...v5.11.7) (2023-10-25) ### Miscellaneous Chores * **deps-dev:** bump @typescript-eslint/eslint-plugin from 5.62.0 to 6.9.0 ([#796](https://github.com/appium/WebDriverAgent/issues/796)) ([dabf141](https://github.com/appium/WebDriverAgent/commit/dabf141acd3186b1c27231ef52826fa42208c980)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 161e35a0a..23456c82b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.11.7](https://github.com/appium/WebDriverAgent/compare/v5.11.6...v5.11.7) (2023-10-25) + + +### Miscellaneous Chores + +* **deps-dev:** bump @typescript-eslint/eslint-plugin from 5.62.0 to 6.9.0 ([#796](https://github.com/appium/WebDriverAgent/issues/796)) ([dabf141](https://github.com/appium/WebDriverAgent/commit/dabf141acd3186b1c27231ef52826fa42208c980)) + ## [5.11.6](https://github.com/appium/WebDriverAgent/compare/v5.11.5...v5.11.6) (2023-10-25) diff --git a/package.json b/package.json index 8f668c0c0..fd9ca5401 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.11.6", + "version": "5.11.7", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From aaf70c9196e4dcb2073da151cda23b2b221d4dae Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 26 Oct 2023 16:52:20 +0200 Subject: [PATCH 106/133] feat: Add an endpoint for keyboard input (#797) --- WebDriverAgentLib/Commands/FBCustomCommands.m | 45 +++++++++++++ WebDriverAgentLib/Utilities/FBKeyboard.h | 10 +++ WebDriverAgentLib/Utilities/FBKeyboard.m | 65 +++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index 9d8e324d7..934cdf73f 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -70,6 +70,9 @@ + (NSArray *)routes [[FBRoute GET:@"/wda/device/location"] respondWithTarget:self action:@selector(handleGetLocation:)], [[FBRoute GET:@"/wda/device/location"].withoutSession respondWithTarget:self action:@selector(handleGetLocation:)], #if !TARGET_OS_TV // tvOS does not provide relevant APIs +#if __clang_major__ >= 15 + [[FBRoute POST:@"/wda/element/:uuid/keyboardInput"] respondWithTarget:self action:@selector(handleKeyboardInput:)], +#endif [[FBRoute GET:@"/wda/simulatedLocation"] respondWithTarget:self action:@selector(handleGetSimulatedLocation:)], [[FBRoute GET:@"/wda/simulatedLocation"].withoutSession respondWithTarget:self action:@selector(handleGetSimulatedLocation:)], [[FBRoute POST:@"/wda/simulatedLocation"] respondWithTarget:self action:@selector(handleSetSimulatedLocation:)], @@ -543,6 +546,48 @@ + (NSString *)timeZone } return FBResponseWithOK(); } + +#if __clang_major__ >= 15 ++ (id)handleKeyboardInput:(FBRouteRequest *)request +{ + FBElementCache *elementCache = request.session.elementCache; + BOOL hasElement = nil != request.parameters[@"uuid"]; + XCUIElement *destination = hasElement + ? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]] + : request.session.activeApplication; + id keys = request.arguments[@"keys"]; + if (![keys isKindOfClass:NSArray.class]) { + NSString *message = @"The 'keys' argument must be an array"; + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:message + traceback:nil]); + } + for (id item in (NSArray *)keys) { + if ([item isKindOfClass:NSString.class]) { + NSString *keyValue = [FBKeyboard keyValueForName:item] ?: item; + [destination typeKey:keyValue modifierFlags:XCUIKeyModifierNone]; + } else if ([item isKindOfClass:NSDictionary.class]) { + id key = [(NSDictionary *)item objectForKey:@"key"]; + if (![key isKindOfClass:NSString.class]) { + NSString *message = [NSString stringWithFormat:@"All dictionaries of 'keys' array must have the 'key' item of type string. Got '%@' instead in the item %@", key, item]; + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:message + traceback:nil]); + } + id modifiers = [(NSDictionary *)item objectForKey:@"modifierFlags"]; + NSUInteger modifierFlags = XCUIKeyModifierNone; + if ([modifiers isKindOfClass:NSNumber.class]) { + modifierFlags = [(NSNumber *)modifiers unsignedIntValue]; + } + NSString *keyValue = [FBKeyboard keyValueForName:item] ?: key; + [destination typeKey:keyValue modifierFlags:modifierFlags]; + } else { + NSString *message = @"All items of the 'keys' array must be either dictionaries or strings"; + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:message + traceback:nil]); + } + } + return FBResponseWithOK(); +} +#endif #endif + (id)handlePerformAccessibilityAudit:(FBRouteRequest *)request diff --git a/WebDriverAgentLib/Utilities/FBKeyboard.h b/WebDriverAgentLib/Utilities/FBKeyboard.h index cbe1180cd..5a16e1aed 100644 --- a/WebDriverAgentLib/Utilities/FBKeyboard.h +++ b/WebDriverAgentLib/Utilities/FBKeyboard.h @@ -13,6 +13,16 @@ NS_ASSUME_NONNULL_BEGIN @interface FBKeyboard : NSObject +#if (!TARGET_OS_TV && __clang_major__ >= 15) +/** + Transforms key name to its string representation, which could be used with XCTest + + @param name one of available keyboard key names defined in https://developer.apple.com/documentation/xctest/xcuikeyboardkey?language=objc + @return Either the key value or nil if no matches have been found + */ ++ (nullable NSString *)keyValueForName:(NSString *)name; +#endif + /** Types a string into active element. There must be element with keyboard focus; otherwise an error is raised. diff --git a/WebDriverAgentLib/Utilities/FBKeyboard.m b/WebDriverAgentLib/Utilities/FBKeyboard.m index 7d474ac02..0cf9964c6 100644 --- a/WebDriverAgentLib/Utilities/FBKeyboard.m +++ b/WebDriverAgentLib/Utilities/FBKeyboard.m @@ -80,4 +80,69 @@ + (BOOL)waitUntilVisibleForApplication:(XCUIApplication *)app timeout:(NSTimeInt error:error]; } +#if (!TARGET_OS_TV && __clang_major__ >= 15) + ++ (NSString *)keyValueForName:(NSString *)name +{ + static dispatch_once_t onceKeys; + static NSDictionary *keysMapping; + dispatch_once(&onceKeys, ^{ + keysMapping = @{ + @"XCUIKeyboardKeyDelete": XCUIKeyboardKeyDelete, + @"XCUIKeyboardKeyReturn": XCUIKeyboardKeyReturn, + @"XCUIKeyboardKeyEnter": XCUIKeyboardKeyEnter, + @"XCUIKeyboardKeyTab": XCUIKeyboardKeyTab, + @"XCUIKeyboardKeySpace": XCUIKeyboardKeySpace, + @"XCUIKeyboardKeyEscape": XCUIKeyboardKeyEscape, + + @"XCUIKeyboardKeyUpArrow": XCUIKeyboardKeyUpArrow, + @"XCUIKeyboardKeyDownArrow": XCUIKeyboardKeyDownArrow, + @"XCUIKeyboardKeyLeftArrow": XCUIKeyboardKeyLeftArrow, + @"XCUIKeyboardKeyRightArrow": XCUIKeyboardKeyRightArrow, + + @"XCUIKeyboardKeyF1": XCUIKeyboardKeyF1, + @"XCUIKeyboardKeyF2": XCUIKeyboardKeyF2, + @"XCUIKeyboardKeyF3": XCUIKeyboardKeyF3, + @"XCUIKeyboardKeyF4": XCUIKeyboardKeyF4, + @"XCUIKeyboardKeyF5": XCUIKeyboardKeyF5, + @"XCUIKeyboardKeyF6": XCUIKeyboardKeyF6, + @"XCUIKeyboardKeyF7": XCUIKeyboardKeyF7, + @"XCUIKeyboardKeyF8": XCUIKeyboardKeyF8, + @"XCUIKeyboardKeyF9": XCUIKeyboardKeyF9, + @"XCUIKeyboardKeyF10": XCUIKeyboardKeyF10, + @"XCUIKeyboardKeyF11": XCUIKeyboardKeyF11, + @"XCUIKeyboardKeyF12": XCUIKeyboardKeyF12, + @"XCUIKeyboardKeyF13": XCUIKeyboardKeyF13, + @"XCUIKeyboardKeyF14": XCUIKeyboardKeyF14, + @"XCUIKeyboardKeyF15": XCUIKeyboardKeyF15, + @"XCUIKeyboardKeyF16": XCUIKeyboardKeyF16, + @"XCUIKeyboardKeyF17": XCUIKeyboardKeyF17, + @"XCUIKeyboardKeyF18": XCUIKeyboardKeyF18, + @"XCUIKeyboardKeyF19": XCUIKeyboardKeyF19, + + @"XCUIKeyboardKeyForwardDelete": XCUIKeyboardKeyForwardDelete, + @"XCUIKeyboardKeyHome": XCUIKeyboardKeyHome, + @"XCUIKeyboardKeyEnd": XCUIKeyboardKeyEnd, + @"XCUIKeyboardKeyPageUp": XCUIKeyboardKeyPageUp, + @"XCUIKeyboardKeyPageDown": XCUIKeyboardKeyPageDown, + @"XCUIKeyboardKeyClear": XCUIKeyboardKeyClear, + @"XCUIKeyboardKeyHelp": XCUIKeyboardKeyHelp, + + @"XCUIKeyboardKeyCapsLock": XCUIKeyboardKeyCapsLock, + @"XCUIKeyboardKeyShift": XCUIKeyboardKeyShift, + @"XCUIKeyboardKeyControl": XCUIKeyboardKeyControl, + @"XCUIKeyboardKeyOption": XCUIKeyboardKeyOption, + @"XCUIKeyboardKeyCommand": XCUIKeyboardKeyCommand, + @"XCUIKeyboardKeyRightShift": XCUIKeyboardKeyRightShift, + @"XCUIKeyboardKeyRightControl": XCUIKeyboardKeyRightControl, + @"XCUIKeyboardKeyRightOption": XCUIKeyboardKeyRightOption, + @"XCUIKeyboardKeyRightCommand": XCUIKeyboardKeyRightCommand, + @"XCUIKeyboardKeySecondaryFn": XCUIKeyboardKeySecondaryFn + }; + }); + return keysMapping[name]; +} + +#endif + @end From beb413e37a22d6802f8096b18a68427307caacfd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 26 Oct 2023 15:03:58 +0000 Subject: [PATCH 107/133] chore(release): 5.12.0 [skip ci] ## [5.12.0](https://github.com/appium/WebDriverAgent/compare/v5.11.7...v5.12.0) (2023-10-26) ### Features * Add an endpoint for keyboard input ([#797](https://github.com/appium/WebDriverAgent/issues/797)) ([aaf70c9](https://github.com/appium/WebDriverAgent/commit/aaf70c9196e4dcb2073da151cda23b2b221d4dae)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23456c82b..77b02b2f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.12.0](https://github.com/appium/WebDriverAgent/compare/v5.11.7...v5.12.0) (2023-10-26) + + +### Features + +* Add an endpoint for keyboard input ([#797](https://github.com/appium/WebDriverAgent/issues/797)) ([aaf70c9](https://github.com/appium/WebDriverAgent/commit/aaf70c9196e4dcb2073da151cda23b2b221d4dae)) + ## [5.11.7](https://github.com/appium/WebDriverAgent/compare/v5.11.6...v5.11.7) (2023-10-25) diff --git a/package.json b/package.json index fd9ca5401..aa2b8e157 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.11.7", + "version": "5.12.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 58ebe8eb52966963ee30a5c066beb3bf9fed3161 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 28 Oct 2023 15:02:37 -0700 Subject: [PATCH 108/133] fix: when 0 is given for handleKeyboardInput (#798) --- WebDriverAgentLib/Commands/FBCustomCommands.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index 934cdf73f..21b67173f 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -551,7 +551,7 @@ + (NSString *)timeZone + (id)handleKeyboardInput:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - BOOL hasElement = nil != request.parameters[@"uuid"]; + BOOL hasElement = ![request.parameters[@"uuid"] isEqual:@"0"]; XCUIElement *destination = hasElement ? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]] : request.session.activeApplication; From deb3c05998d100c0eece079e8d8662ad23ae7c5d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 28 Oct 2023 23:00:37 +0000 Subject: [PATCH 109/133] chore(release): 5.12.1 [skip ci] ## [5.12.1](https://github.com/appium/WebDriverAgent/compare/v5.12.0...v5.12.1) (2023-10-28) ### Bug Fixes * when 0 is given for handleKeyboardInput ([#798](https://github.com/appium/WebDriverAgent/issues/798)) ([58ebe8e](https://github.com/appium/WebDriverAgent/commit/58ebe8eb52966963ee30a5c066beb3bf9fed3161)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77b02b2f4..7fd267cc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.12.1](https://github.com/appium/WebDriverAgent/compare/v5.12.0...v5.12.1) (2023-10-28) + + +### Bug Fixes + +* when 0 is given for handleKeyboardInput ([#798](https://github.com/appium/WebDriverAgent/issues/798)) ([58ebe8e](https://github.com/appium/WebDriverAgent/commit/58ebe8eb52966963ee30a5c066beb3bf9fed3161)) + ## [5.12.0](https://github.com/appium/WebDriverAgent/compare/v5.11.7...v5.12.0) (2023-10-26) diff --git a/package.json b/package.json index aa2b8e157..d95bb937e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.12.0", + "version": "5.12.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 247ace68f373c09054fabc3be088061089946806 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 29 Oct 2023 15:25:18 -0700 Subject: [PATCH 110/133] chore: return operation error in `handleKeyboardInput` (#799) * fix: when 0 is given * chore: return explicit unsupported error * Update FBCustomCommands.m --- WebDriverAgentLib/Commands/FBCustomCommands.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index 21b67173f..5b1ce72ae 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -556,6 +556,13 @@ + (NSString *)timeZone ? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]] : request.session.activeApplication; id keys = request.arguments[@"keys"]; + + if (![destination respondsToSelector:@selector(typeKey:modifierFlags:)]) { + NSString *message = @"typeKey API is only supported since Xcode15 and iPadOS 17"; + return FBResponseWithStatus([FBCommandStatus unsupportedOperationErrorWithMessage:message + traceback:nil]); + } + if (![keys isKindOfClass:NSArray.class]) { NSString *message = @"The 'keys' argument must be an array"; return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:message From 2aa2a28631a7731d3a6951b1378c042cfcdda59f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 29 Oct 2023 22:31:33 +0000 Subject: [PATCH 111/133] chore(release): 5.12.2 [skip ci] ## [5.12.2](https://github.com/appium/WebDriverAgent/compare/v5.12.1...v5.12.2) (2023-10-29) ### Miscellaneous Chores * return operation error in `handleKeyboardInput` ([#799](https://github.com/appium/WebDriverAgent/issues/799)) ([247ace6](https://github.com/appium/WebDriverAgent/commit/247ace68f373c09054fabc3be088061089946806)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fd267cc7..421164cf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.12.2](https://github.com/appium/WebDriverAgent/compare/v5.12.1...v5.12.2) (2023-10-29) + + +### Miscellaneous Chores + +* return operation error in `handleKeyboardInput` ([#799](https://github.com/appium/WebDriverAgent/issues/799)) ([247ace6](https://github.com/appium/WebDriverAgent/commit/247ace68f373c09054fabc3be088061089946806)) + ## [5.12.1](https://github.com/appium/WebDriverAgent/compare/v5.12.0...v5.12.1) (2023-10-28) diff --git a/package.json b/package.json index d95bb937e..571d5d356 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.12.1", + "version": "5.12.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 796d5e743676b174221e27e739a0164f4b91533c Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 31 Oct 2023 08:50:43 +0100 Subject: [PATCH 112/133] chore: Return better error on WDA startup timeout (#801) --- lib/xcodebuild.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/xcodebuild.js b/lib/xcodebuild.js index de6b58818..8194d1984 100644 --- a/lib/xcodebuild.js +++ b/lib/xcodebuild.js @@ -405,12 +405,13 @@ class XcodeBuild { this.log.debug(`Waiting up to ${this.launchTimeout}ms for WebDriverAgent to start`); let currentStatus = null; try { - let retries = parseInt(`${this.launchTimeout / 500}`, 10); + const retries = Math.trunc(this.launchTimeout / 500); await retryInterval(retries, 1000, async () => { if (this._didProcessExit) { // there has been an error elsewhere and we need to short-circuit - return; + return currentStatus; } + const proxyTimeout = this.noSessionProxy.timeout; this.noSessionProxy.timeout = 1000; try { @@ -434,10 +435,11 @@ class XcodeBuild { this.log.debug(`WebDriverAgent successfully started after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`); } catch (err) { - // at this point, if we have not had any errors from xcode itself (reported - // elsewhere), we can let this go through and try to create the session - this.log.debug(err.message); - this.log.warn(`Getting status of WebDriverAgent on device timed out. Continuing`); + this.log.debug(err.stack); + throw new Error( + `We were not able to retrieve the /status response from the WebDriverAgent server after ${this.launchTimeout}ms timeout.` + + `Try to increase the value of 'appium:wdaLaunchTimeout' capability as a possible workaround.` + ); } return currentStatus; } From d92c98535f5bde04a4c89a1843aea690ded8e286 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 31 Oct 2023 07:56:58 +0000 Subject: [PATCH 113/133] chore(release): 5.12.3 [skip ci] ## [5.12.3](https://github.com/appium/WebDriverAgent/compare/v5.12.2...v5.12.3) (2023-10-31) ### Miscellaneous Chores * Return better error on WDA startup timeout ([#801](https://github.com/appium/WebDriverAgent/issues/801)) ([796d5e7](https://github.com/appium/WebDriverAgent/commit/796d5e743676b174221e27e739a0164f4b91533c)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 421164cf9..bcd3ee38f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.12.3](https://github.com/appium/WebDriverAgent/compare/v5.12.2...v5.12.3) (2023-10-31) + + +### Miscellaneous Chores + +* Return better error on WDA startup timeout ([#801](https://github.com/appium/WebDriverAgent/issues/801)) ([796d5e7](https://github.com/appium/WebDriverAgent/commit/796d5e743676b174221e27e739a0164f4b91533c)) + ## [5.12.2](https://github.com/appium/WebDriverAgent/compare/v5.12.1...v5.12.2) (2023-10-29) diff --git a/package.json b/package.json index 571d5d356..7696d13c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.12.2", + "version": "5.12.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 9925af44ec5fbfb66e6f034dfd93a6c25de48661 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 31 Oct 2023 20:24:12 +0100 Subject: [PATCH 114/133] feat: Add "elementDescription" property to audit issues containing the debug description of an element (#802) --- WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m | 1 + 1 file changed, 1 insertion(+) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 7c9ff9967..4faaed1ae 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -374,6 +374,7 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames @"compactDescription": extractIssueProperty(issue, @"compactDescription") ?: @"", @"auditType": auditType, @"element": [extractIssueProperty(issue, @"element") description] ?: @"", + @"elementDescription": [extractIssueProperty(issue, @"element") debugDescription] ?: @"", }]; return YES; }; From d3d9107139bb9d7a6149b224b75edc184a8180a6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 31 Oct 2023 19:32:28 +0000 Subject: [PATCH 115/133] chore(release): 5.13.0 [skip ci] ## [5.13.0](https://github.com/appium/WebDriverAgent/compare/v5.12.3...v5.13.0) (2023-10-31) ### Features * Add "elementDescription" property to audit issues containing the debug description of an element ([#802](https://github.com/appium/WebDriverAgent/issues/802)) ([9925af4](https://github.com/appium/WebDriverAgent/commit/9925af44ec5fbfb66e6f034dfd93a6c25de48661)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcd3ee38f..ed392b5b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.13.0](https://github.com/appium/WebDriverAgent/compare/v5.12.3...v5.13.0) (2023-10-31) + + +### Features + +* Add "elementDescription" property to audit issues containing the debug description of an element ([#802](https://github.com/appium/WebDriverAgent/issues/802)) ([9925af4](https://github.com/appium/WebDriverAgent/commit/9925af44ec5fbfb66e6f034dfd93a6c25de48661)) + ## [5.12.3](https://github.com/appium/WebDriverAgent/compare/v5.12.2...v5.12.3) (2023-10-31) diff --git a/package.json b/package.json index 7696d13c9..bec7dbf83 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.12.3", + "version": "5.13.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 0f2305d2559dc0807d7df0d0e06f7fc3c549701c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:41:52 +0100 Subject: [PATCH 116/133] chore(deps): bump asyncbox from 2.9.4 to 3.0.0 (#803) Bumps [asyncbox](https://github.com/jlipps/asyncbox) from 2.9.4 to 3.0.0. - [Commits](https://github.com/jlipps/asyncbox/commits/v3.0.0) --- updated-dependencies: - dependency-name: asyncbox dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bec7dbf83..50ec457f1 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "appium-ios-device": "^2.5.0", "appium-ios-simulator": "^5.0.1", "async-lock": "^1.0.0", - "asyncbox": "^2.5.3", + "asyncbox": "^3.0.0", "axios": "^1.4.0", "bluebird": "^3.5.5", "lodash": "^4.17.11", From 29fd2e2b7060182e9aa21a40da335d76fcfe0546 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 1 Nov 2023 16:53:48 +0000 Subject: [PATCH 117/133] chore(release): 5.13.1 [skip ci] ## [5.13.1](https://github.com/appium/WebDriverAgent/compare/v5.13.0...v5.13.1) (2023-11-01) ### Miscellaneous Chores * **deps:** bump asyncbox from 2.9.4 to 3.0.0 ([#803](https://github.com/appium/WebDriverAgent/issues/803)) ([0f2305d](https://github.com/appium/WebDriverAgent/commit/0f2305d2559dc0807d7df0d0e06f7fc3c549701c)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed392b5b4..c503cf2dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.13.1](https://github.com/appium/WebDriverAgent/compare/v5.13.0...v5.13.1) (2023-11-01) + + +### Miscellaneous Chores + +* **deps:** bump asyncbox from 2.9.4 to 3.0.0 ([#803](https://github.com/appium/WebDriverAgent/issues/803)) ([0f2305d](https://github.com/appium/WebDriverAgent/commit/0f2305d2559dc0807d7df0d0e06f7fc3c549701c)) + ## [5.13.0](https://github.com/appium/WebDriverAgent/compare/v5.12.3...v5.13.0) (2023-10-31) diff --git a/package.json b/package.json index 50ec457f1..349f6a3cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.13.0", + "version": "5.13.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 824f74c69769973858350bd5db0061510c546b09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 17:50:18 +0100 Subject: [PATCH 118/133] chore(deps-dev): bump @types/sinon from 10.0.20 to 17.0.0 (#805) Bumps [@types/sinon](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/sinon) from 10.0.20 to 17.0.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/sinon) --- updated-dependencies: - dependency-name: "@types/sinon" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 349f6a3cb..4097a0993 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@types/lodash": "^4.14.196", "@types/mocha": "^10.0.1", "@types/node": "^20.4.7", - "@types/sinon": "^10.0.16", + "@types/sinon": "^17.0.0", "@types/sinon-chai": "^3.2.9", "@types/teen_process": "^2.0.1", "@typescript-eslint/eslint-plugin": "^6.9.0", From c6c5df1851b30285696a0ac3fd1945955d1cf0eb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 6 Nov 2023 17:14:37 +0000 Subject: [PATCH 119/133] chore(release): 5.13.2 [skip ci] ## [5.13.2](https://github.com/appium/WebDriverAgent/compare/v5.13.1...v5.13.2) (2023-11-06) ### Miscellaneous Chores * **deps-dev:** bump @types/sinon from 10.0.20 to 17.0.0 ([#805](https://github.com/appium/WebDriverAgent/issues/805)) ([824f74c](https://github.com/appium/WebDriverAgent/commit/824f74c69769973858350bd5db0061510c546b09)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c503cf2dd..c862368a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.13.2](https://github.com/appium/WebDriverAgent/compare/v5.13.1...v5.13.2) (2023-11-06) + + +### Miscellaneous Chores + +* **deps-dev:** bump @types/sinon from 10.0.20 to 17.0.0 ([#805](https://github.com/appium/WebDriverAgent/issues/805)) ([824f74c](https://github.com/appium/WebDriverAgent/commit/824f74c69769973858350bd5db0061510c546b09)) + ## [5.13.1](https://github.com/appium/WebDriverAgent/compare/v5.13.0...v5.13.1) (2023-11-01) diff --git a/package.json b/package.json index 4097a0993..762e03f5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.13.1", + "version": "5.13.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 79832bc6c69e289091fbbb97aee6a1f1d17ca4c3 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 9 Nov 2023 23:05:55 -0800 Subject: [PATCH 120/133] fix: unrecognized selector sent to instance 0x2829adb20 error in clear (#809) --- WebDriverAgentLib/Categories/XCUIElement+FBTyping.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m index a538be380..54b0d5362 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m @@ -143,7 +143,12 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot do { if (retry >= MAX_CLEAR_RETRIES - 1) { // Last chance retry. Tripple-tap the field to select its content - [self tapWithNumberOfTaps:3 numberOfTouches:1]; + + if ([self respondsToSelector:@selector(tapWithNumberOfTaps:numberOfTouches:)]) { + // e.g. tvOS 17 raised unrecognized selector error for XCUIElementTypeSearchField + // while following typeText worked. + [self tapWithNumberOfTaps:3 numberOfTouches:1]; + } return [FBKeyboard typeText:backspaceDeleteSequence error:error]; } From 518858a8eee914e35c3d4e3c3783611bdedc4577 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 10 Nov 2023 07:11:28 +0000 Subject: [PATCH 121/133] chore(release): 5.13.3 [skip ci] ## [5.13.3](https://github.com/appium/WebDriverAgent/compare/v5.13.2...v5.13.3) (2023-11-10) ### Bug Fixes * unrecognized selector sent to instance 0x2829adb20 error in clear ([#809](https://github.com/appium/WebDriverAgent/issues/809)) ([79832bc](https://github.com/appium/WebDriverAgent/commit/79832bc6c69e289091fbbb97aee6a1f1d17ca4c3)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c862368a2..e93f006e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.13.3](https://github.com/appium/WebDriverAgent/compare/v5.13.2...v5.13.3) (2023-11-10) + + +### Bug Fixes + +* unrecognized selector sent to instance 0x2829adb20 error in clear ([#809](https://github.com/appium/WebDriverAgent/issues/809)) ([79832bc](https://github.com/appium/WebDriverAgent/commit/79832bc6c69e289091fbbb97aee6a1f1d17ca4c3)) + ## [5.13.2](https://github.com/appium/WebDriverAgent/compare/v5.13.1...v5.13.2) (2023-11-06) diff --git a/package.json b/package.json index 762e03f5e..e59934abe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.13.2", + "version": "5.13.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From dd093ea0b7209c3d2f3d0b1fa7f3a7b58507dd2d Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 10 Nov 2023 14:50:59 -0800 Subject: [PATCH 122/133] feat: use khidusage_keyboardclear to `clear` for iOS/iPad as the 1st attempt, tune tvOS (#811) * feat: Add khidusage_keyboardclear as possible option for text field clear on iOS * feat: tune clear text * revert * revert another place * tune for tvOS * leave testing note * remove unnecessary MAX_CLEAR_RETRIES * Update XCUIElement+FBTyping.m * Update XCUIElement+FBTyping.m --------- Co-authored-by: Mykola Mokhnach --- .../Categories/XCUIElement+FBTyping.m | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m index 54b0d5362..c6e31f4fc 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m @@ -15,11 +15,12 @@ #import "NSString+FBVisualLength.h" #import "FBXCElementSnapshotWrapper.h" #import "FBXCElementSnapshotWrapper+Helpers.h" +#import "XCUIDevice+FBHelpers.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBUtilities.h" #import "FBXCodeCompatibility.h" -#define MAX_CLEAR_RETRIES 2 +#define MAX_CLEAR_RETRIES 3 @interface NSString (FBRepeat) @@ -136,27 +137,32 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot backspaceDeleteSequence = [[NSString alloc] initWithData:(NSData *)[@"\\u0008\\u007F" dataUsingEncoding:NSASCIIStringEncoding] encoding:NSNonLossyASCIIStringEncoding]; }); - + + NSUInteger preClearTextLength = [currentValue fb_visualLength]; + NSString *backspacesToType = [backspaceDeleteSequence fb_repeatTimes:preClearTextLength]; + +#if TARGET_OS_IOS NSUInteger retry = 0; NSString *placeholderValue = snapshot.placeholderValue; - NSUInteger preClearTextLength = [currentValue fb_visualLength]; do { - if (retry >= MAX_CLEAR_RETRIES - 1) { - // Last chance retry. Tripple-tap the field to select its content - - if ([self respondsToSelector:@selector(tapWithNumberOfTaps:numberOfTouches:)]) { - // e.g. tvOS 17 raised unrecognized selector error for XCUIElementTypeSearchField - // while following typeText worked. - [self tapWithNumberOfTaps:3 numberOfTouches:1]; - } - return [FBKeyboard typeText:backspaceDeleteSequence error:error]; - } - - NSString *textToType = [backspaceDeleteSequence fb_repeatTimes:preClearTextLength]; + // the ios needs to have keyboard focus to clear text if (shouldPrepareForInput && 0 == retry) { [self fb_prepareForTextInputWithSnapshot:snapshot]; } - if (![FBKeyboard typeText:textToType error:error]) { + + if (retry == 0) { + // 1st attempt is via the IOHIDEvent as the fastest operation + // https://github.com/appium/appium/issues/19389 + [[XCUIDevice sharedDevice] fb_performIOHIDEventWithPage:0x07 // kHIDPage_KeyboardOrKeypad + usage:0x9c // kHIDUsage_KeyboardClear + duration:0.01 + error:nil]; + } else if (retry >= MAX_CLEAR_RETRIES - 1) { + // Last chance retry. Tripple-tap the field to select its content + [self tapWithNumberOfTaps:3 numberOfTouches:1]; + return [FBKeyboard typeText:backspaceDeleteSequence error:error]; + } else if (![FBKeyboard typeText:backspacesToType error:error]) { + // 2nd operation return NO; } @@ -170,6 +176,13 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot retry++; } while (preClearTextLength > 0); return YES; +#else + // tvOS does not need a focus. + // kHIDPage_KeyboardOrKeypad did not work for tvOS's search field. (tvOS 17 at least) + // Tested XCUIElementTypeSearchField and XCUIElementTypeTextView whch were + // common search field and email/passowrd input in tvOS apps. + return [FBKeyboard typeText:backspacesToType error:error]; +#endif } @end From b67222eac62a828a4b42fce80819281035830e7c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 10 Nov 2023 22:58:13 +0000 Subject: [PATCH 123/133] chore(release): 5.14.0 [skip ci] ## [5.14.0](https://github.com/appium/WebDriverAgent/compare/v5.13.3...v5.14.0) (2023-11-10) ### Features * use khidusage_keyboardclear to `clear` for iOS/iPad as the 1st attempt, tune tvOS ([#811](https://github.com/appium/WebDriverAgent/issues/811)) ([dd093ea](https://github.com/appium/WebDriverAgent/commit/dd093ea0b7209c3d2f3d0b1fa7f3a7b58507dd2d)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e93f006e4..69b8f87f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.14.0](https://github.com/appium/WebDriverAgent/compare/v5.13.3...v5.14.0) (2023-11-10) + + +### Features + +* use khidusage_keyboardclear to `clear` for iOS/iPad as the 1st attempt, tune tvOS ([#811](https://github.com/appium/WebDriverAgent/issues/811)) ([dd093ea](https://github.com/appium/WebDriverAgent/commit/dd093ea0b7209c3d2f3d0b1fa7f3a7b58507dd2d)) + ## [5.13.3](https://github.com/appium/WebDriverAgent/compare/v5.13.2...v5.13.3) (2023-11-10) diff --git a/package.json b/package.json index e59934abe..77f598f2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.13.3", + "version": "5.14.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 0d7e4a697adb7355279583eaa05118f396056e6f Mon Sep 17 00:00:00 2001 From: Ilya Kharebashvili Date: Thu, 16 Nov 2023 12:26:43 +0200 Subject: [PATCH 124/133] feat: Add element attributes to the performAccessibilityAudit output (#808) --- .../Categories/XCUIApplication+FBHelpers.m | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 4faaed1ae..2656de7d6 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -369,12 +369,19 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames if (nil != auditTypeValue) { auditType = valuesToNamesMap[auditTypeValue] ?: [auditTypeValue stringValue]; } + + id extractedElement = extractIssueProperty(issue, @"element"); + + id elementSnapshot = [extractedElement fb_takeSnapshot]; + NSDictionary *elementAttributes = elementSnapshot ? [self.class dictionaryForElement:elementSnapshot recursive:NO] : @{}; + [resultArray addObject:@{ @"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"", @"compactDescription": extractIssueProperty(issue, @"compactDescription") ?: @"", @"auditType": auditType, - @"element": [extractIssueProperty(issue, @"element") description] ?: @"", - @"elementDescription": [extractIssueProperty(issue, @"element") debugDescription] ?: @"", + @"element": [extractedElement description] ?: @"", + @"elementDescription": [extractedElement debugDescription] ?: @"", + @"elementAttributes": elementAttributes ?: @{}, }]; return YES; }; From 1e1905c5bf94cdd4dc4a2a917ac0a3bf9890a7c7 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 16 Nov 2023 10:32:25 +0000 Subject: [PATCH 125/133] chore(release): 5.15.0 [skip ci] ## [5.15.0](https://github.com/appium/WebDriverAgent/compare/v5.14.0...v5.15.0) (2023-11-16) ### Features * Add element attributes to the performAccessibilityAudit output ([#808](https://github.com/appium/WebDriverAgent/issues/808)) ([0d7e4a6](https://github.com/appium/WebDriverAgent/commit/0d7e4a697adb7355279583eaa05118f396056e6f)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69b8f87f7..539251658 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.15.0](https://github.com/appium/WebDriverAgent/compare/v5.14.0...v5.15.0) (2023-11-16) + + +### Features + +* Add element attributes to the performAccessibilityAudit output ([#808](https://github.com/appium/WebDriverAgent/issues/808)) ([0d7e4a6](https://github.com/appium/WebDriverAgent/commit/0d7e4a697adb7355279583eaa05118f396056e6f)) + ## [5.14.0](https://github.com/appium/WebDriverAgent/compare/v5.13.3...v5.14.0) (2023-11-10) diff --git a/package.json b/package.json index 77f598f2f..d5568caef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.14.0", + "version": "5.15.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 0b41757c0d21004afab32860b4e510d4bc426018 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 16 Nov 2023 15:59:31 +0100 Subject: [PATCH 126/133] refactor: Optimize screenshots preprocessing (#812) --- WebDriverAgent.xcodeproj/project.pbxproj | 40 ++-- .../Commands/FBSessionCommands.m | 4 + WebDriverAgentLib/Utilities/FBConfiguration.h | 17 +- WebDriverAgentLib/Utilities/FBConfiguration.m | 10 + WebDriverAgentLib/Utilities/FBImageIOScaler.m | 195 ------------------ .../{FBImageIOScaler.h => FBImageProcessor.h} | 25 +-- .../Utilities/FBImageProcessor.m | 171 +++++++++++++++ WebDriverAgentLib/Utilities/FBImageUtils.h | 6 + WebDriverAgentLib/Utilities/FBImageUtils.m | 34 +++ WebDriverAgentLib/Utilities/FBMjpegServer.m | 33 ++- WebDriverAgentLib/Utilities/FBScreenshot.h | 13 -- WebDriverAgentLib/Utilities/FBScreenshot.m | 16 +- WebDriverAgentLib/Utilities/FBSettings.h | 1 + WebDriverAgentLib/Utilities/FBSettings.m | 1 + ...OScalerTests.m => FBImageProcessorTests.m} | 44 ++-- .../IntegrationTests/XCUIDeviceHelperTests.m | 12 +- 16 files changed, 313 insertions(+), 309 deletions(-) delete mode 100644 WebDriverAgentLib/Utilities/FBImageIOScaler.m rename WebDriverAgentLib/Utilities/{FBImageIOScaler.h => FBImageProcessor.h} (64%) create mode 100644 WebDriverAgentLib/Utilities/FBImageProcessor.m rename WebDriverAgentTests/IntegrationTests/{FBImageIOScalerTests.m => FBImageProcessorTests.m} (59%) diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index 3630797a6..836267cce 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -38,11 +38,11 @@ 315A15072518CC2800A3A064 /* TouchSpotView.m in Sources */ = {isa = PBXBuildFile; fileRef = 315A15062518CC2800A3A064 /* TouchSpotView.m */; }; 315A150A2518D6F400A3A064 /* TouchViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 315A15092518D6F400A3A064 /* TouchViewController.m */; }; 6385F4A7220A40760095BBDB /* XCUIApplicationProcessDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */; }; - 63CCF91221ECE4C700E94ABD /* FBImageIOScaler.h in Headers */ = {isa = PBXBuildFile; fileRef = 63CCF91021ECE4C700E94ABD /* FBImageIOScaler.h */; }; - 63CCF91321ECE4C700E94ABD /* FBImageIOScaler.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CCF91121ECE4C700E94ABD /* FBImageIOScaler.m */; }; - 63FD950221F9D06100A3E356 /* FBImageIOScalerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 631B523421F6174300625362 /* FBImageIOScalerTests.m */; }; - 63FD950321F9D06100A3E356 /* FBImageIOScalerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 631B523421F6174300625362 /* FBImageIOScalerTests.m */; }; - 63FD950421F9D06200A3E356 /* FBImageIOScalerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 631B523421F6174300625362 /* FBImageIOScalerTests.m */; }; + 63CCF91221ECE4C700E94ABD /* FBImageProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 63CCF91021ECE4C700E94ABD /* FBImageProcessor.h */; }; + 63CCF91321ECE4C700E94ABD /* FBImageProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CCF91121ECE4C700E94ABD /* FBImageProcessor.m */; }; + 63FD950221F9D06100A3E356 /* FBImageProcessorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 631B523421F6174300625362 /* FBImageProcessorTests.m */; }; + 63FD950321F9D06100A3E356 /* FBImageProcessorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 631B523421F6174300625362 /* FBImageProcessorTests.m */; }; + 63FD950421F9D06200A3E356 /* FBImageProcessorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 631B523421F6174300625362 /* FBImageProcessorTests.m */; }; 641EE3452240C1C800173FCB /* UITestingUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7FD1CAEE048008C271F /* UITestingUITests.m */; }; 641EE5D72240C5CA00173FCB /* FBScreenshotCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB75F1CAEDF0C008C271F /* FBScreenshotCommands.m */; }; 641EE5D92240C5CA00173FCB /* XCUIElement+FBPickerWheel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7136A4781E8918E60024FC3D /* XCUIElement+FBPickerWheel.m */; }; @@ -80,7 +80,7 @@ 641EE5FE2240C5CA00173FCB /* XCUIElement+FBWebDriverAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE376481D59FAE900ED88DD /* XCUIElement+FBWebDriverAttributes.m */; }; 641EE5FF2240C5CA00173FCB /* XCUIElement+FBForceTouch.m in Sources */ = {isa = PBXBuildFile; fileRef = EE8DDD7C20C5733B004D4925 /* XCUIElement+FBForceTouch.m */; }; 641EE6002240C5CA00173FCB /* FBTouchActionCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 71241D7A1FAE3D2500B9559F /* FBTouchActionCommands.m */; }; - 641EE6012240C5CA00173FCB /* FBImageIOScaler.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CCF91121ECE4C700E94ABD /* FBImageIOScaler.m */; }; + 641EE6012240C5CA00173FCB /* FBImageProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CCF91121ECE4C700E94ABD /* FBImageProcessor.m */; }; 641EE6022240C5CA00173FCB /* FBTouchIDCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7631CAEDF0C008C271F /* FBTouchIDCommands.m */; }; 641EE6032240C5CA00173FCB /* FBDebugCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7551CAEDF0C008C271F /* FBDebugCommands.m */; }; 641EE6042240C5CA00173FCB /* NSString+FBXMLSafeString.m in Sources */ = {isa = PBXBuildFile; fileRef = 716E0BCD1E917E810087A825 /* NSString+FBXMLSafeString.m */; }; @@ -222,7 +222,7 @@ 641EE6A32240C5CA00173FCB /* XCUIApplication+FBTouchAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BD20711F86116100B36EC2 /* XCUIApplication+FBTouchAction.h */; }; 641EE6A42240C5CA00173FCB /* FBCommandHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7751CAEDF0C008C271F /* FBCommandHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6A52240C5CA00173FCB /* FBSessionCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7601CAEDF0C008C271F /* FBSessionCommands.h */; }; - 641EE6A62240C5CA00173FCB /* FBImageIOScaler.h in Headers */ = {isa = PBXBuildFile; fileRef = 63CCF91021ECE4C700E94ABD /* FBImageIOScaler.h */; }; + 641EE6A62240C5CA00173FCB /* FBImageProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 63CCF91021ECE4C700E94ABD /* FBImageProcessor.h */; }; 641EE6A72240C5CA00173FCB /* FBSession-Private.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7891CAEDF0C008C271F /* FBSession-Private.h */; }; 641EE6A82240C5CA00173FCB /* NSString+FBXMLSafeString.h in Headers */ = {isa = PBXBuildFile; fileRef = 716E0BCC1E917E810087A825 /* NSString+FBXMLSafeString.h */; }; 641EE6A92240C5CA00173FCB /* FBCommandStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7761CAEDF0C008C271F /* FBCommandStatus.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -918,11 +918,11 @@ 315A15082518D6F400A3A064 /* TouchViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchViewController.h; sourceTree = ""; }; 315A15092518D6F400A3A064 /* TouchViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TouchViewController.m; sourceTree = ""; }; 44757A831D42CE8300ECF35E /* XCUIDeviceRotationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XCUIDeviceRotationTests.m; sourceTree = ""; }; - 631B523421F6174300625362 /* FBImageIOScalerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBImageIOScalerTests.m; sourceTree = ""; }; + 631B523421F6174300625362 /* FBImageProcessorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBImageProcessorTests.m; sourceTree = ""; }; 633E904A220DEE7F007CADF9 /* XCUIApplicationProcessDelay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCUIApplicationProcessDelay.h; sourceTree = ""; }; 6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XCUIApplicationProcessDelay.m; sourceTree = ""; }; - 63CCF91021ECE4C700E94ABD /* FBImageIOScaler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBImageIOScaler.h; sourceTree = ""; }; - 63CCF91121ECE4C700E94ABD /* FBImageIOScaler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBImageIOScaler.m; sourceTree = ""; }; + 63CCF91021ECE4C700E94ABD /* FBImageProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBImageProcessor.h; sourceTree = ""; }; + 63CCF91121ECE4C700E94ABD /* FBImageProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBImageProcessor.m; sourceTree = ""; }; 641EE2DA2240BBE300173FCB /* WebDriverAgentRunner_tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WebDriverAgentRunner_tvOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 641EE6F82240C5CA00173FCB /* WebDriverAgentLib_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WebDriverAgentLib_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 641EE7042240CDCF00173FCB /* XCUIElement+FBTVFocuse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBTVFocuse.h"; sourceTree = ""; }; @@ -1890,8 +1890,8 @@ EE3A18611CDE618F00DE4205 /* FBErrorBuilder.m */, EE6A89381D0B38640083E92B /* FBFailureProofTestCase.h */, EE6A89391D0B38640083E92B /* FBFailureProofTestCase.m */, - 63CCF91021ECE4C700E94ABD /* FBImageIOScaler.h */, - 63CCF91121ECE4C700E94ABD /* FBImageIOScaler.m */, + 63CCF91021ECE4C700E94ABD /* FBImageProcessor.h */, + 63CCF91121ECE4C700E94ABD /* FBImageProcessor.m */, 7150348521A6DAD600A0F4BA /* FBImageUtils.h */, 7150348621A6DAD600A0F4BA /* FBImageUtils.m */, EE9B76A31CF7A43900275851 /* FBLogger.h */, @@ -2004,7 +2004,7 @@ 71E504941DF59BAD0020C32A /* XCUIElementAttributesTests.m */, EEBBD48D1D4785FC00656A81 /* XCUIElementFBFindTests.m */, EE1E06E11D181CC9007CF043 /* XCUIElementHelperIntegrationTests.m */, - 631B523421F6174300625362 /* FBImageIOScalerTests.m */, + 631B523421F6174300625362 /* FBImageProcessorTests.m */, 644D9CCD230E1F1A00C90459 /* FBConfigurationTests.m */, ); path = IntegrationTests; @@ -2381,7 +2381,7 @@ 641EE6A42240C5CA00173FCB /* FBCommandHandler.h in Headers */, 641EE6A52240C5CA00173FCB /* FBSessionCommands.h in Headers */, 641EE70C2240CE2D00173FCB /* FBTVNavigationTracker.h in Headers */, - 641EE6A62240C5CA00173FCB /* FBImageIOScaler.h in Headers */, + 641EE6A62240C5CA00173FCB /* FBImageProcessor.h in Headers */, 641EE6A72240C5CA00173FCB /* FBSession-Private.h in Headers */, 641EE6A82240C5CA00173FCB /* NSString+FBXMLSafeString.h in Headers */, 64E3502F2AC0B6FE005F3ACB /* NSDictionary+FBUtf8SafeDictionary.h in Headers */, @@ -2622,7 +2622,7 @@ EE158AC81CBD456F00A3E3F0 /* FBSessionCommands.h in Headers */, 71C8E55125399A6B008572C1 /* XCUIApplication+FBQuiescence.h in Headers */, 641EE70B2240CE2D00173FCB /* FBTVNavigationTracker.h in Headers */, - 63CCF91221ECE4C700E94ABD /* FBImageIOScaler.h in Headers */, + 63CCF91221ECE4C700E94ABD /* FBImageProcessor.h in Headers */, EE158AE31CBD456F00A3E3F0 /* FBSession-Private.h in Headers */, 716E0BCE1E917E810087A825 /* NSString+FBXMLSafeString.h in Headers */, EE158ACF1CBD456F00A3E3F0 /* FBCommandStatus.h in Headers */, @@ -3122,7 +3122,7 @@ 641EE6002240C5CA00173FCB /* FBTouchActionCommands.m in Sources */, 719DCF182601EAFB000E765F /* FBNotificationsHelper.m in Sources */, 714EAA102673FDFE005C5B47 /* FBCapabilities.m in Sources */, - 641EE6012240C5CA00173FCB /* FBImageIOScaler.m in Sources */, + 641EE6012240C5CA00173FCB /* FBImageProcessor.m in Sources */, 641EE6022240C5CA00173FCB /* FBTouchIDCommands.m in Sources */, 641EE6032240C5CA00173FCB /* FBDebugCommands.m in Sources */, 641EE6042240C5CA00173FCB /* NSString+FBXMLSafeString.m in Sources */, @@ -3236,7 +3236,7 @@ EEE3764A1D59FAE900ED88DD /* XCUIElement+FBWebDriverAttributes.m in Sources */, EE8DDD7E20C5733C004D4925 /* XCUIElement+FBForceTouch.m in Sources */, 71241D7C1FAE3D2500B9559F /* FBTouchActionCommands.m in Sources */, - 63CCF91321ECE4C700E94ABD /* FBImageIOScaler.m in Sources */, + 63CCF91321ECE4C700E94ABD /* FBImageProcessor.m in Sources */, EE158ACB1CBD456F00A3E3F0 /* FBTouchIDCommands.m in Sources */, 71F5BE51252F14EB00EE9EBA /* FBExceptions.m in Sources */, EE158ABD1CBD456F00A3E3F0 /* FBDebugCommands.m in Sources */, @@ -3307,7 +3307,7 @@ files = ( 71241D801FAF087500B9559F /* FBW3CMultiTouchActionsIntegrationTests.m in Sources */, 71241D7E1FAF084E00B9559F /* FBW3CTouchActionsIntegrationTests.m in Sources */, - 63FD950221F9D06100A3E356 /* FBImageIOScalerTests.m in Sources */, + 63FD950221F9D06100A3E356 /* FBImageProcessorTests.m in Sources */, 719CD8FF2126C90200C7D0C2 /* FBAutoAlertsHandlerTests.m in Sources */, EE2202131ECC612200A29571 /* FBIntegrationTestCase.m in Sources */, 71BD20781F869E0F00B36EC2 /* FBAppiumTouchActionsIntegrationTests.m in Sources */, @@ -3324,7 +3324,7 @@ buildActionMask = 2147483647; files = ( EE5095E51EBCC9090028E2FE /* FBTypingTest.m in Sources */, - 63FD950321F9D06100A3E356 /* FBImageIOScalerTests.m in Sources */, + 63FD950321F9D06100A3E356 /* FBImageProcessorTests.m in Sources */, EE5095EB1EBCC9090028E2FE /* XCElementSnapshotHitPointTests.m in Sources */, EE5095EC1EBCC9090028E2FE /* XCUIApplicationHelperTests.m in Sources */, 7136C0F9243A182400921C76 /* FBW3CTypeActionsTests.m in Sources */, @@ -3397,7 +3397,7 @@ 7119E1EC1E891F8600D0B125 /* FBPickerWheelSelectTests.m in Sources */, 71ACF5B8242F2FDC00F0AAD4 /* FBSafariAlertTests.m in Sources */, EE1E06DA1D1808C2007CF043 /* FBIntegrationTestCase.m in Sources */, - 63FD950421F9D06200A3E356 /* FBImageIOScalerTests.m in Sources */, + 63FD950421F9D06200A3E356 /* FBImageProcessorTests.m in Sources */, EE05BAFA1D13003C00A3EB00 /* FBKeyboardTests.m in Sources */, EE55B3271D1D54CF003AAAEC /* FBScrollingTests.m in Sources */, EE6A89371D0B35920083E92B /* FBFailureProofTestCaseTests.m in Sources */, diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 7bd87a768..4a7ae1a8d 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -280,6 +280,7 @@ + (NSArray *)routes FB_SETTING_MJPEG_SERVER_SCREENSHOT_QUALITY: @([FBConfiguration mjpegServerScreenshotQuality]), FB_SETTING_MJPEG_SERVER_FRAMERATE: @([FBConfiguration mjpegServerFramerate]), FB_SETTING_MJPEG_SCALING_FACTOR: @([FBConfiguration mjpegScalingFactor]), + FB_SETTING_MJPEG_FIX_ORIENTATION: @([FBConfiguration mjpegShouldFixOrientation]), FB_SETTING_SCREENSHOT_QUALITY: @([FBConfiguration screenshotQuality]), FB_SETTING_KEYBOARD_AUTOCORRECTION: @([FBConfiguration keyboardAutocorrection]), FB_SETTING_KEYBOARD_PREDICTION: @([FBConfiguration keyboardPrediction]), @@ -327,6 +328,9 @@ + (NSArray *)routes if (nil != [settings objectForKey:FB_SETTING_MJPEG_SCALING_FACTOR]) { [FBConfiguration setMjpegScalingFactor:[[settings objectForKey:FB_SETTING_MJPEG_SCALING_FACTOR] unsignedIntegerValue]]; } + if (nil != [settings objectForKey:FB_SETTING_MJPEG_FIX_ORIENTATION]) { + [FBConfiguration setMjpegShouldFixOrientation:[[settings objectForKey:FB_SETTING_MJPEG_FIX_ORIENTATION] boolValue]]; + } if (nil != [settings objectForKey:FB_SETTING_KEYBOARD_AUTOCORRECTION]) { [FBConfiguration setKeyboardAutocorrection:[[settings objectForKey:FB_SETTING_KEYBOARD_AUTOCORRECTION] boolValue]]; } diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index 8bb9d48ca..dd0015e56 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -84,6 +84,16 @@ extern NSString *const FBSnapshotMaxDepthKey; + (NSUInteger)mjpegServerScreenshotQuality; + (void)setMjpegServerScreenshotQuality:(NSUInteger)quality; +/** + Whether to apply orientation fixes to the streamed JPEG images. + This is an expensive operation and it is disabled by default, so screenshots + are returned in portrait, but their actual orientation value could still be found in the EXIF + metadata. + ! Enablement of this setting may lead to WDA process termination because of an excessive CPU usage. + */ ++ (BOOL)mjpegShouldFixOrientation; ++ (void)setMjpegShouldFixOrientation:(BOOL)enabled; + /** The framerate at which the background screenshots broadcaster should broadcast screenshots in range 1..60. The default value is 10 (Frames Per Second). @@ -93,7 +103,7 @@ extern NSString *const FBSnapshotMaxDepthKey; + (void)setMjpegServerFramerate:(NSUInteger)framerate; /** - The quality of display screenshots. The higher quality you set is the bigger screenshot size is. + The quality of display screenshots. The higher quality you set is the bigger screenshot size is. The highest quality value is 0 (lossless PNG) or 3 (lossless HEIC). The lowest quality is 2 (highly compressed JPEG). The default quality value is 3 (lossless HEIC). See https://developer.apple.com/documentation/xctest/xctimagequality?language=objc @@ -112,7 +122,10 @@ extern NSString *const FBSnapshotMaxDepthKey; + (NSInteger)mjpegServerPort; /** - The scaling factor for frames of the mjpeg stream (Default values is 100 and does not perform scaling). + The scaling factor for frames of the mjpeg stream. The default (and maximum) value is 100, + which does not perform any scaling. The minimum value must be greater than zero. + ! Setting this to a value less than 100, especially together with orientation fixing enabled + ! may lead to WDA process termination because of an excessive CPU usage. */ + (NSUInteger)mjpegScalingFactor; + (void)setMjpegScalingFactor:(NSUInteger)scalingFactor; diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index f149d2193..03b6a6b1b 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -33,6 +33,7 @@ static BOOL FBShouldUseSingletonTestManager = YES; static NSUInteger FBMjpegScalingFactor = 100; +static BOOL FBMjpegShouldFixOrientation = NO; static NSUInteger FBMjpegServerScreenshotQuality = 25; static NSUInteger FBMjpegServerFramerate = 10; @@ -143,6 +144,15 @@ + (void)setMjpegScalingFactor:(NSUInteger)scalingFactor { FBMjpegScalingFactor = scalingFactor; } ++ (BOOL)mjpegShouldFixOrientation +{ + return FBMjpegShouldFixOrientation; +} + ++ (void)setMjpegShouldFixOrientation:(BOOL)enabled { + FBMjpegShouldFixOrientation = enabled; +} + + (BOOL)verboseLoggingEnabled { return [NSProcessInfo.processInfo.environment[@"VERBOSE_LOGGING"] boolValue]; diff --git a/WebDriverAgentLib/Utilities/FBImageIOScaler.m b/WebDriverAgentLib/Utilities/FBImageIOScaler.m deleted file mode 100644 index 0ca87b747..000000000 --- a/WebDriverAgentLib/Utilities/FBImageIOScaler.m +++ /dev/null @@ -1,195 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBImageIOScaler.h" - -#import -#import -@import UniformTypeIdentifiers; - -#import "FBConfiguration.h" -#import "FBErrorBuilder.h" -#import "FBLogger.h" - -const CGFloat FBMinScalingFactor = 0.01f; -const CGFloat FBMaxScalingFactor = 1.0f; -const CGFloat FBMinCompressionQuality = 0.0f; -const CGFloat FBMaxCompressionQuality = 1.0f; - -@interface FBImageIOScaler () - -@property (nonatomic) NSData *nextImage; -@property (nonatomic, readonly) NSLock *nextImageLock; -@property (nonatomic, readonly) dispatch_queue_t scalingQueue; - -@end - -@implementation FBImageIOScaler - -- (id)init -{ - self = [super init]; - if (self) { - _nextImageLock = [[NSLock alloc] init]; - _scalingQueue = dispatch_queue_create("image.scaling.queue", NULL); - } - return self; -} - -- (void)submitImage:(NSData *)image - scalingFactor:(CGFloat)scalingFactor - compressionQuality:(CGFloat)compressionQuality - completionHandler:(void (^)(NSData *))completionHandler -{ - [self.nextImageLock lock]; - if (self.nextImage != nil) { - [FBLogger verboseLog:@"Discarding screenshot"]; - } - scalingFactor = MAX(FBMinScalingFactor, MIN(FBMaxScalingFactor, scalingFactor)); - compressionQuality = MAX(FBMinCompressionQuality, MIN(FBMaxCompressionQuality, compressionQuality)); - self.nextImage = image; - [self.nextImageLock unlock]; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wcompletion-handler" - dispatch_async(self.scalingQueue, ^{ - [self.nextImageLock lock]; - NSData *next = self.nextImage; - self.nextImage = nil; - [self.nextImageLock unlock]; - if (next == nil) { - return; - } - - NSError *error; - NSData *scaled = [self scaledJpegImageWithImage:next - scalingFactor:scalingFactor - compressionQuality:compressionQuality - error:&error]; - if (scaled == nil) { - [FBLogger logFmt:@"%@", error.description]; - return; - } - completionHandler(scaled); - }); -#pragma clang diagnostic pop -} - -// This method is more optimized for JPEG scaling -// and should be used in `submitImage` API, while the `scaledImageWithImage` -// one is more generic -- (nullable NSData *)scaledJpegImageWithImage:(NSData *)image - scalingFactor:(CGFloat)scalingFactor - compressionQuality:(CGFloat)compressionQuality - error:(NSError **)error -{ - CGImageSourceRef imageData = CGImageSourceCreateWithData((CFDataRef)image, nil); - CGSize size = [self.class imageSizeWithImage:imageData]; - CGFloat scaledMaxPixelSize = MAX(size.width, size.height) * scalingFactor; - CFDictionaryRef params = (__bridge CFDictionaryRef)@{ - (const NSString *)kCGImageSourceCreateThumbnailWithTransform: @(YES), - (const NSString *)kCGImageSourceCreateThumbnailFromImageIfAbsent: @(YES), - (const NSString *)kCGImageSourceThumbnailMaxPixelSize: @(scaledMaxPixelSize) - }; - CGImageRef scaled = CGImageSourceCreateThumbnailAtIndex(imageData, 0, params); - CFRelease(imageData); - if (nil == scaled) { - [[[FBErrorBuilder builder] - withDescriptionFormat:@"Failed to scale the image"] - buildError:error]; - return nil; - } - NSData *resData = [self jpegDataWithImage:scaled - compressionQuality:compressionQuality]; - if (nil == resData) { - [[[FBErrorBuilder builder] - withDescriptionFormat:@"Failed to compress the image to JPEG format"] - buildError:error]; - } - CGImageRelease(scaled); - return resData; -} - -- (nullable NSData *)scaledImageWithImage:(NSData *)image - uti:(UTType *)uti - rect:(CGRect)rect - scalingFactor:(CGFloat)scalingFactor - compressionQuality:(CGFloat)compressionQuality - error:(NSError **)error -{ - UIImage *uiImage = [UIImage imageWithData:image]; - CGSize size = uiImage.size; - CGSize scaledSize = CGSizeMake(size.width * scalingFactor, size.height * scalingFactor); - UIGraphicsBeginImageContext(scaledSize); - UIImageOrientation orientation = uiImage.imageOrientation; -#if !TARGET_OS_TV - if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationPortrait) { - orientation = UIImageOrientationUp; - } else if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationPortraitUpsideDown) { - orientation = UIImageOrientationDown; - } else if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationLandscapeLeft) { - orientation = UIImageOrientationRight; - } else if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationLandscapeRight) { - orientation = UIImageOrientationLeft; - } -#endif - uiImage = [UIImage imageWithCGImage:(CGImageRef)uiImage.CGImage - scale:uiImage.scale - orientation:orientation]; - [uiImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)]; - UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - if (!CGRectIsNull(rect)) { - UIGraphicsBeginImageContext(rect.size); - [resultImage drawAtPoint:CGPointMake(-rect.origin.x, -rect.origin.y)]; - resultImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - } - - return [uti conformsToType:UTTypePNG] - ? UIImagePNGRepresentation(resultImage) - : UIImageJPEGRepresentation(resultImage, compressionQuality); -} - -- (nullable NSData *)jpegDataWithImage:(CGImageRef)imageRef - compressionQuality:(CGFloat)compressionQuality -{ - NSMutableData *newImageData = [NSMutableData data]; - CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData( - (__bridge CFMutableDataRef) newImageData, - (__bridge CFStringRef) UTTypeJPEG.identifier, - 1, - NULL); - CFDictionaryRef compressionOptions = (__bridge CFDictionaryRef)@{ - (const NSString *)kCGImageDestinationLossyCompressionQuality: @(compressionQuality) - }; - CGImageDestinationAddImage(imageDestination, imageRef, compressionOptions); - if(!CGImageDestinationFinalize(imageDestination)) { - [FBLogger log:@"Failed to write the image"]; - newImageData = nil; - } - CFRelease(imageDestination); - return newImageData; -} - -+ (CGSize)imageSizeWithImage:(CGImageSourceRef)imageSource -{ - NSDictionary *options = @{ - (const NSString *)kCGImageSourceShouldCache: @(NO) - }; - CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (CFDictionaryRef)options); - NSNumber *width = [(__bridge NSDictionary *)properties objectForKey:(const NSString *)kCGImagePropertyPixelWidth]; - NSNumber *height = [(__bridge NSDictionary *)properties objectForKey:(const NSString *)kCGImagePropertyPixelHeight]; - CGSize size = CGSizeMake([width floatValue], [height floatValue]); - CFRelease(properties); - return size; -} - -@end diff --git a/WebDriverAgentLib/Utilities/FBImageIOScaler.h b/WebDriverAgentLib/Utilities/FBImageProcessor.h similarity index 64% rename from WebDriverAgentLib/Utilities/FBImageIOScaler.h rename to WebDriverAgentLib/Utilities/FBImageProcessor.h index 476daba04..a350bd9ce 100644 --- a/WebDriverAgentLib/Utilities/FBImageIOScaler.h +++ b/WebDriverAgentLib/Utilities/FBImageProcessor.h @@ -20,7 +20,7 @@ extern const CGFloat FBMaxScalingFactor; extern const CGFloat FBMinCompressionQuality; extern const CGFloat FBMaxCompressionQuality; -@interface FBImageIOScaler : NSObject +@interface FBImageProcessor : NSObject /** Puts the passed image on the queue and dispatches a scaling operation. If there is already a image on the @@ -29,34 +29,27 @@ extern const CGFloat FBMaxCompressionQuality; @param image The image to scale down @param completionHandler called after successfully scaling down an image @param scalingFactor the scaling factor in range 0.01..1.0. A value of 1.0 won't perform scaling at all - @param compressionQuality the compression quality in range 0.0..1.0 (0.0 for max. compression and 1.0 for lossless compression) - Only applicable for UTTypeJPEG */ -- (void)submitImage:(NSData *)image - scalingFactor:(CGFloat)scalingFactor - compressionQuality:(CGFloat)compressionQuality - completionHandler:(void (^)(NSData *))completionHandler; +- (void)submitImageData:(NSData *)image + scalingFactor:(CGFloat)scalingFactor + completionHandler:(void (^)(NSData *))completionHandler; /** Scales and crops the source image @param image The source image data @param uti Either UTTypePNG or UTTypeJPEG - @param rect The cropping rectange for the screenshot. The value is expected to be non-scaled one - since it happens after scaling/orientation change. - CGRectNull could be used to take a screenshot of the full screen. @param scalingFactor Scaling factor in range 0.01..1.0. A value of 1.0 won't perform scaling at all @param compressionQuality the compression quality in range 0.0..1.0 (0.0 for max. compression and 1.0 for lossless compression). Only works if UTI is set to kUTTypeJPEG @param error The actual error instance if the returned result is nil @returns Processed image data compressed according to the given UTI or nil in case of a failure */ -- (nullable NSData *)scaledImageWithImage:(NSData *)image - uti:(UTType *)uti - rect:(CGRect)rect - scalingFactor:(CGFloat)scalingFactor - compressionQuality:(CGFloat)compressionQuality - error:(NSError **)error; +- (nullable NSData *)scaledImageWithData:(NSData *)image + uti:(UTType *)uti + scalingFactor:(CGFloat)scalingFactor + compressionQuality:(CGFloat)compressionQuality + error:(NSError **)error; @end diff --git a/WebDriverAgentLib/Utilities/FBImageProcessor.m b/WebDriverAgentLib/Utilities/FBImageProcessor.m new file mode 100644 index 000000000..16601ce8e --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBImageProcessor.m @@ -0,0 +1,171 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "FBImageProcessor.h" + +#import +#import +@import UniformTypeIdentifiers; + +#import "FBConfiguration.h" +#import "FBErrorBuilder.h" +#import "FBImageUtils.h" +#import "FBLogger.h" + +const CGFloat FBMinScalingFactor = 0.01f; +const CGFloat FBMaxScalingFactor = 1.0f; +const CGFloat FBMinCompressionQuality = 0.0f; +const CGFloat FBMaxCompressionQuality = 1.0f; + +@interface FBImageProcessor () + +@property (nonatomic) NSData *nextImage; +@property (nonatomic, readonly) NSLock *nextImageLock; +@property (nonatomic, readonly) dispatch_queue_t scalingQueue; + +@end + +@implementation FBImageProcessor + +- (id)init +{ + self = [super init]; + if (self) { + _nextImageLock = [[NSLock alloc] init]; + _scalingQueue = dispatch_queue_create("image.scaling.queue", NULL); + } + return self; +} + +- (void)submitImageData:(NSData *)image + scalingFactor:(CGFloat)scalingFactor + completionHandler:(void (^)(NSData *))completionHandler +{ + [self.nextImageLock lock]; + if (self.nextImage != nil) { + [FBLogger verboseLog:@"Discarding screenshot"]; + } + self.nextImage = image; + [self.nextImageLock unlock]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcompletion-handler" + dispatch_async(self.scalingQueue, ^{ + [self.nextImageLock lock]; + NSData *nextImageData = self.nextImage; + self.nextImage = nil; + [self.nextImageLock unlock]; + if (nextImageData == nil) { + return; + } + + // We do not want this value to be too high because then we get images larger in size than original ones + // Although, we also don't want to lose too much of the quality on recompression + CGFloat recompressionQuality = MAX(0.9, + MIN(FBMaxCompressionQuality, FBConfiguration.mjpegServerScreenshotQuality / 100.0)); + NSData *thumbnailData = [self.class fixedImageDataWithImageData:nextImageData + scalingFactor:scalingFactor + uti:UTTypeJPEG + compressionQuality:recompressionQuality + // iOS always returns screnshots in portrait orientation, but puts the real value into the metadata + // Use it with care. See https://github.com/appium/WebDriverAgent/pull/812 + fixOrientation:FBConfiguration.mjpegShouldFixOrientation + desiredOrientation:nil]; + completionHandler(thumbnailData ?: nextImageData); + }); +#pragma clang diagnostic pop +} + ++ (nullable NSData *)fixedImageDataWithImageData:(NSData *)imageData + scalingFactor:(CGFloat)scalingFactor + uti:(UTType *)uti + compressionQuality:(CGFloat)compressionQuality + fixOrientation:(BOOL)fixOrientation + desiredOrientation:(nullable NSNumber *)orientation +{ + scalingFactor = MAX(FBMinScalingFactor, MIN(FBMaxScalingFactor, scalingFactor)); + BOOL usesScaling = scalingFactor > 0.0 && scalingFactor < FBMaxScalingFactor; + @autoreleasepool { + if (!usesScaling && !fixOrientation) { + return [uti conformsToType:UTTypePNG] ? FBToPngData(imageData) : FBToJpegData(imageData, compressionQuality); + } + + UIImage *image = [UIImage imageWithData:imageData]; + if (nil == image + || ((image.imageOrientation == UIImageOrientationUp || !fixOrientation) && !usesScaling)) { + return [uti conformsToType:UTTypePNG] ? FBToPngData(imageData) : FBToJpegData(imageData, compressionQuality); + } + + CGSize scaledSize = CGSizeMake(image.size.width * scalingFactor, image.size.height * scalingFactor); + if (!fixOrientation && usesScaling) { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block UIImage *result = nil; + [image prepareThumbnailOfSize:scaledSize + completionHandler:^(UIImage * _Nullable thumbnail) { + result = thumbnail; + dispatch_semaphore_signal(semaphore); + }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + if (nil == result) { + return [uti conformsToType:UTTypePNG] ? FBToPngData(imageData) : FBToJpegData(imageData, compressionQuality); + } + return [uti conformsToType:UTTypePNG] + ? UIImagePNGRepresentation(result) + : UIImageJPEGRepresentation(result, compressionQuality); + } + + UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init]; + format.scale = scalingFactor; + UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:scaledSize + format:format]; + UIImageOrientation desiredOrientation = orientation == nil + ? image.imageOrientation + : (UIImageOrientation)orientation.integerValue; + UIImage *uiImage = [UIImage imageWithCGImage:(CGImageRef)image.CGImage + scale:image.scale + orientation:desiredOrientation]; + return [uti conformsToType:UTTypePNG] + ? [renderer PNGDataWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) { + [uiImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)]; + }] + : [renderer JPEGDataWithCompressionQuality:compressionQuality + actions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) { + [uiImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)]; + }]; + } +} + +- (nullable NSData *)scaledImageWithData:(NSData *)imageData + uti:(UTType *)uti + scalingFactor:(CGFloat)scalingFactor + compressionQuality:(CGFloat)compressionQuality + error:(NSError **)error +{ + NSNumber *orientation = nil; +#if !TARGET_OS_TV + if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationPortrait) { + orientation = @(UIImageOrientationUp); + } else if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationPortraitUpsideDown) { + orientation = @(UIImageOrientationDown); + } else if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationLandscapeLeft) { + orientation = @(UIImageOrientationRight); + } else if (FBConfiguration.screenshotOrientation == UIInterfaceOrientationLandscapeRight) { + orientation = @(UIImageOrientationLeft); + } +#endif + NSData *resultData = [self.class fixedImageDataWithImageData:imageData + scalingFactor:scalingFactor + uti:uti + compressionQuality:compressionQuality + fixOrientation:YES + desiredOrientation:orientation]; + return resultData ?: imageData; +} + +@end diff --git a/WebDriverAgentLib/Utilities/FBImageUtils.h b/WebDriverAgentLib/Utilities/FBImageUtils.h index 96ea15a6b..15a04f6fe 100644 --- a/WebDriverAgentLib/Utilities/FBImageUtils.h +++ b/WebDriverAgentLib/Utilities/FBImageUtils.h @@ -17,4 +17,10 @@ BOOL FBIsPngImage(NSData *imageData); /*! Converts the given image data to a PNG representation if necessary */ NSData *_Nullable FBToPngData(NSData *imageData); +/*! Returns YES if the data contains a JPG image */ +BOOL FBIsJpegImage(NSData *imageData); + +/*! Converts the given image data to a JPG representation if necessary */ +NSData *_Nullable FBToJpegData(NSData *imageData, CGFloat compressionQuality); + NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBImageUtils.m b/WebDriverAgentLib/Utilities/FBImageUtils.m index 5983ddc30..b1d2f9b5b 100644 --- a/WebDriverAgentLib/Utilities/FBImageUtils.m +++ b/WebDriverAgentLib/Utilities/FBImageUtils.m @@ -12,8 +12,11 @@ #import "FBMacros.h" #import "FBConfiguration.h" +// https://en.wikipedia.org/wiki/List_of_file_signatures static uint8_t PNG_MAGIC[] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; static const NSUInteger PNG_MAGIC_LEN = 8; +static uint8_t JPG_MAGIC[] = { 0xff, 0xd8, 0xff }; +static const NSUInteger JPG_MAGIC_LEN = 3; BOOL FBIsPngImage(NSData *imageData) { @@ -45,3 +48,34 @@ BOOL FBIsPngImage(NSData *imageData) UIImage *image = [UIImage imageWithData:imageData]; return nil == image ? nil : (NSData *)UIImagePNGRepresentation(image); } + +BOOL FBIsJpegImage(NSData *imageData) +{ + if (nil == imageData || [imageData length] < JPG_MAGIC_LEN) { + return NO; + } + + static NSData* jpgMagicStartData = nil; + static dispatch_once_t onceJpgToken; + dispatch_once(&onceJpgToken, ^{ + jpgMagicStartData = [NSData dataWithBytesNoCopy:(void*)JPG_MAGIC length:JPG_MAGIC_LEN freeWhenDone:NO]; + }); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wassign-enum" + NSRange range = [imageData rangeOfData:jpgMagicStartData options:kNilOptions range:NSMakeRange(0, JPG_MAGIC_LEN)]; +#pragma clang diagnostic pop + return range.location != NSNotFound; +} + +NSData *FBToJpegData(NSData *imageData, CGFloat compressionQuality) { + if (nil == imageData || [imageData length] < JPG_MAGIC_LEN) { + return nil; + } + if (FBIsJpegImage(imageData)) { + return imageData; + } + + UIImage *image = [UIImage imageWithData:imageData]; + return nil == image ? nil : (NSData *)UIImageJPEGRepresentation(image, compressionQuality); +} diff --git a/WebDriverAgentLib/Utilities/FBMjpegServer.m b/WebDriverAgentLib/Utilities/FBMjpegServer.m index 51fa48687..a0970e256 100644 --- a/WebDriverAgentLib/Utilities/FBMjpegServer.m +++ b/WebDriverAgentLib/Utilities/FBMjpegServer.m @@ -17,7 +17,8 @@ #import "FBConfiguration.h" #import "FBLogger.h" #import "FBScreenshot.h" -#import "FBImageIOScaler.h" +#import "FBImageProcessor.h" +#import "FBImageUtils.h" #import "XCUIScreen.h" static const NSUInteger MAX_FPS = 60; @@ -31,7 +32,7 @@ @interface FBMjpegServer() @property (nonatomic, readonly) dispatch_queue_t backgroundQueue; @property (nonatomic, readonly) NSMutableArray *listeningClients; -@property (nonatomic, readonly) FBImageIOScaler *imageScaler; +@property (nonatomic, readonly) FBImageProcessor *imageProcessor; @property (nonatomic, readonly) long long mainScreenID; @end @@ -48,7 +49,7 @@ - (instancetype)init dispatch_async(_backgroundQueue, ^{ [self streamScreenshot]; }); - _imageScaler = [[FBImageIOScaler alloc] init]; + _imageProcessor = [[FBImageProcessor alloc] init]; _mainScreenID = [XCUIScreen.mainScreen displayID]; } return self; @@ -82,15 +83,11 @@ - (void)streamScreenshot } } - CGFloat scalingFactor = [FBConfiguration mjpegScalingFactor] / 100.0f; - BOOL usesScaling = fabs(FBMaxScalingFactor - scalingFactor) > DBL_EPSILON; - CGFloat compressionQuality = FBConfiguration.mjpegServerScreenshotQuality / 100.0f; - // If scaling is applied we perform another JPEG compression after scaling - // To get the desired compressionQuality we need to do a lossless compression here - CGFloat screenshotCompressionQuality = usesScaling ? FBMaxCompressionQuality : compressionQuality; NSError *error; + CGFloat compressionQuality = MAX(FBMinCompressionQuality, + MIN(FBMaxCompressionQuality, FBConfiguration.mjpegServerScreenshotQuality / 100.0)); NSData *screenshotData = [FBScreenshot takeInOriginalResolutionWithScreenID:self.mainScreenID - compressionQuality:screenshotCompressionQuality + compressionQuality:compressionQuality uti:UTTypeJPEG timeout:FRAME_TIMEOUT error:&error]; @@ -100,16 +97,12 @@ - (void)streamScreenshot return; } - if (usesScaling) { - [self.imageScaler submitImage:screenshotData - scalingFactor:scalingFactor - compressionQuality:compressionQuality - completionHandler:^(NSData * _Nonnull scaled) { - [self sendScreenshot:scaled]; - }]; - } else { - [self sendScreenshot:screenshotData]; - } + CGFloat scalingFactor = FBConfiguration.mjpegScalingFactor / 100.0; + [self.imageProcessor submitImageData:screenshotData + scalingFactor:scalingFactor + completionHandler:^(NSData * _Nonnull scaled) { + [self sendScreenshot:scaled]; + }]; [self scheduleNextScreenshotWithInterval:timerInterval timeStarted:timeStarted]; } diff --git a/WebDriverAgentLib/Utilities/FBScreenshot.h b/WebDriverAgentLib/Utilities/FBScreenshot.h index 036a5e1cb..74e6b5886 100644 --- a/WebDriverAgentLib/Utilities/FBScreenshot.h +++ b/WebDriverAgentLib/Utilities/FBScreenshot.h @@ -24,19 +24,6 @@ NS_ASSUME_NONNULL_BEGIN + (nullable NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality error:(NSError **)error; -/** - Retrieves non-scaled screenshot of the particular screen rectangle - - @param quality The number in range 0-3, where 0 is PNG (lossless), 3 is HEIC (lossless), 1- low quality JPEG and 2 - high quality JPEG - @param rect The bounding rectange for the screenshot. The value is expected be non-scaled one. - CGRectNull could be used to take a screenshot of the full screen. - @param error If there is an error, upon return contains an NSError object that describes the problem. - @return Device screenshot as PNG-encoded data or nil in case of failure - */ -+ (nullable NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality - rect:(CGRect)rect - error:(NSError **)error; - /** Retrieves non-scaled screenshot of the whole screen diff --git a/WebDriverAgentLib/Utilities/FBScreenshot.m b/WebDriverAgentLib/Utilities/FBScreenshot.m index 8cea6530d..3d9716dea 100644 --- a/WebDriverAgentLib/Utilities/FBScreenshot.m +++ b/WebDriverAgentLib/Utilities/FBScreenshot.m @@ -13,7 +13,7 @@ #import "FBConfiguration.h" #import "FBErrorBuilder.h" -#import "FBImageIOScaler.h" +#import "FBImageProcessor.h" #import "FBLogger.h" #import "FBMacros.h" #import "FBXCodeCompatibility.h" @@ -59,30 +59,19 @@ + (UTType *)imageUtiWithQuality:(NSUInteger)quality } + (NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality - rect:(CGRect)rect error:(NSError **)error { XCUIScreen *mainScreen = XCUIScreen.mainScreen; return [self.class takeWithScreenID:mainScreen.displayID scale:SCREENSHOT_SCALE compressionQuality:[self.class compressionQualityWithQuality:quality] - rect:rect sourceUTI:[self.class imageUtiWithQuality:quality] error:error]; } -+ (NSData *)takeInOriginalResolutionWithQuality:(NSUInteger)quality - error:(NSError **)error -{ - return [self.class takeInOriginalResolutionWithQuality:quality - rect:CGRectNull - error:error]; -} - + (NSData *)takeWithScreenID:(long long)screenID scale:(CGFloat)scale compressionQuality:(CGFloat)compressionQuality - rect:(CGRect)rect sourceUTI:(UTType *)uti error:(NSError **)error { @@ -94,9 +83,8 @@ + (NSData *)takeWithScreenID:(long long)screenID if (nil == screenshotData) { return nil; } - return [[[FBImageIOScaler alloc] init] scaledImageWithImage:screenshotData + return [[[FBImageProcessor alloc] init] scaledImageWithData:screenshotData uti:UTTypePNG - rect:rect scalingFactor:1.0 / scale compressionQuality:FBMaxCompressionQuality error:error]; diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index 8235cb337..dd82d740c 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -17,6 +17,7 @@ extern NSString* const FB_SETTING_USE_COMPACT_RESPONSES; extern NSString* const FB_SETTING_ELEMENT_RESPONSE_ATTRIBUTES; extern NSString* const FB_SETTING_MJPEG_SERVER_SCREENSHOT_QUALITY; extern NSString* const FB_SETTING_MJPEG_SERVER_FRAMERATE; +extern NSString* const FB_SETTING_MJPEG_FIX_ORIENTATION; extern NSString* const FB_SETTING_MJPEG_SCALING_FACTOR; extern NSString* const FB_SETTING_SCREENSHOT_QUALITY; extern NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION; diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index 26bae07e0..6b12a4cd4 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -14,6 +14,7 @@ NSString* const FB_SETTING_MJPEG_SERVER_SCREENSHOT_QUALITY = @"mjpegServerScreenshotQuality"; NSString* const FB_SETTING_MJPEG_SERVER_FRAMERATE = @"mjpegServerFramerate"; NSString* const FB_SETTING_MJPEG_SCALING_FACTOR = @"mjpegScalingFactor"; +NSString* const FB_SETTING_MJPEG_FIX_ORIENTATION = @"mjpegFixOrientation"; NSString* const FB_SETTING_SCREENSHOT_QUALITY = @"screenshotQuality"; NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION = @"keyboardAutocorrection"; NSString* const FB_SETTING_KEYBOARD_PREDICTION = @"keyboardPrediction"; diff --git a/WebDriverAgentTests/IntegrationTests/FBImageIOScalerTests.m b/WebDriverAgentTests/IntegrationTests/FBImageProcessorTests.m similarity index 59% rename from WebDriverAgentTests/IntegrationTests/FBImageIOScalerTests.m rename to WebDriverAgentTests/IntegrationTests/FBImageProcessorTests.m index 0c2f75b62..28fa9d7ee 100644 --- a/WebDriverAgentTests/IntegrationTests/FBImageIOScalerTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBImageProcessorTests.m @@ -9,62 +9,62 @@ #import -#import "FBImageIOScaler.h" +#import "FBImageProcessor.h" #import "FBIntegrationTestCase.h" -@interface FBImageIOScalerTests : FBIntegrationTestCase +@interface FBImageProcessorTests : FBIntegrationTestCase @property (nonatomic) NSData *originalImage; @property (nonatomic) CGSize originalSize; @end -@implementation FBImageIOScalerTests +@implementation FBImageProcessorTests - (void)setUp { XCUIApplication *app = [[XCUIApplication alloc] init]; [app launch]; XCUIScreenshot *screenshot = app.screenshot; self.originalImage = UIImageJPEGRepresentation(screenshot.image, 1.0); - self.originalSize = [FBImageIOScalerTests scaledSizeFromImage:screenshot.image]; + self.originalSize = [FBImageProcessorTests scaledSizeFromImage:screenshot.image]; } - (void)testScaling { CGFloat halfScale = 0.5; - CGSize expectedHalfScaleSize = [FBImageIOScalerTests sizeFromSize:self.originalSize scalingFactor:0.5]; + CGSize expectedHalfScaleSize = [FBImageProcessorTests sizeFromSize:self.originalSize scalingFactor:0.5]; [self scaleImageWithFactor:halfScale expectedSize:expectedHalfScaleSize]; - // 1 is the smalles scaling factor we accept + // 0 is the smalles scaling factor we accept CGFloat minScale = 0.0; - CGSize expectedMinScaleSize = [FBImageIOScalerTests sizeFromSize:self.originalSize scalingFactor:0.01]; + CGSize expectedMinScaleSize = [FBImageProcessorTests sizeFromSize:self.originalSize scalingFactor:0.01]; [self scaleImageWithFactor:minScale expectedSize:expectedMinScaleSize]; // For scaling factors above 100 we don't perform any scaling and just return the unmodified image - CGFloat unscaled = 2.0; - [self scaleImageWithFactor:unscaled + [self scaleImageWithFactor:1.0 + expectedSize:self.originalSize]; + [self scaleImageWithFactor:2.0 expectedSize:self.originalSize]; } - (void)scaleImageWithFactor:(CGFloat)scalingFactor expectedSize:(CGSize)excpectedSize { - FBImageIOScaler *scaler = [[FBImageIOScaler alloc] init]; + FBImageProcessor *scaler = [[FBImageProcessor alloc] init]; id expScaled = [self expectationWithDescription:@"Receive scaled image"]; - [scaler submitImage:self.originalImage - scalingFactor:scalingFactor - compressionQuality:1.0 - completionHandler:^(NSData *scaled) { - UIImage *scaledImage = [UIImage imageWithData:scaled]; - CGSize scaledSize = [FBImageIOScalerTests scaledSizeFromImage:scaledImage]; - - XCTAssertEqualWithAccuracy(scaledSize.width, excpectedSize.width, 1.0); - XCTAssertEqualWithAccuracy(scaledSize.height, excpectedSize.height, 1.0); - - [expScaled fulfill]; - }]; + [scaler submitImageData:self.originalImage + scalingFactor:scalingFactor + completionHandler:^(NSData *scaled) { + UIImage *scaledImage = [UIImage imageWithData:scaled]; + CGSize scaledSize = [FBImageProcessorTests scaledSizeFromImage:scaledImage]; + + XCTAssertEqualWithAccuracy(scaledSize.width, excpectedSize.width, 1.0); + XCTAssertEqualWithAccuracy(scaledSize.height, excpectedSize.height, 1.0); + + [expScaled fulfill]; + }]; [self waitForExpectations:@[expScaled] timeout:0.5]; diff --git a/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m b/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m index 52a910311..ca79b2fa4 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m @@ -78,14 +78,12 @@ - (void)testLandscapeScreenshot XCTAssertTrue(screenshot.size.width > screenshot.size.height); XCUIScreen *mainScreen = XCUIScreen.mainScreen; - // TODO: This screenshot rotation was not landscape in an iOS 16 beta simulator. UIImage *screenshotExact = ((XCUIScreenshot *)mainScreen.screenshot).image; - XCTAssertEqualWithAccuracy(screenshotExact.size.height * mainScreen.scale, - screenshot.size.height, - FLT_EPSILON); - XCTAssertEqualWithAccuracy(screenshotExact.size.width * mainScreen.scale, - screenshot.size.width, - FLT_EPSILON); + CGSize realMainScreenSize = screenshotExact.size.height > screenshot.size.width + ? CGSizeMake(screenshotExact.size.height * mainScreen.scale, screenshotExact.size.width * mainScreen.scale) + : CGSizeMake(screenshotExact.size.width * mainScreen.scale, screenshotExact.size.height * mainScreen.scale); + XCTAssertEqualWithAccuracy(realMainScreenSize.height, screenshot.size.height, FLT_EPSILON); + XCTAssertEqualWithAccuracy(realMainScreenSize.width, screenshot.size.width, FLT_EPSILON); } - (void)testWifiAddress From b4704dafc4567e1f0dc8675facfc48a195aae4bf Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 16 Nov 2023 22:15:35 +0100 Subject: [PATCH 127/133] fix: Content-Type of the MJPEG server --- WebDriverAgentLib/Utilities/FBMjpegServer.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Utilities/FBMjpegServer.m b/WebDriverAgentLib/Utilities/FBMjpegServer.m index a0970e256..14a734c94 100644 --- a/WebDriverAgentLib/Utilities/FBMjpegServer.m +++ b/WebDriverAgentLib/Utilities/FBMjpegServer.m @@ -108,7 +108,7 @@ - (void)streamScreenshot } - (void)sendScreenshot:(NSData *)screenshotData { - NSString *chunkHeader = [NSString stringWithFormat:@"--BoundaryString\r\nContent-type: image/jpg\r\nContent-Length: %@\r\n\r\n", @(screenshotData.length)]; + NSString *chunkHeader = [NSString stringWithFormat:@"--BoundaryString\r\nContent-type: image/jpeg\r\nContent-Length: %@\r\n\r\n", @(screenshotData.length)]; NSMutableData *chunk = [[chunkHeader dataUsingEncoding:NSUTF8StringEncoding] mutableCopy]; [chunk appendData:screenshotData]; [chunk appendData:(id)[@"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; From d0dbbb87de7cce3d3687bda3bd53807af14dd795 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 16 Nov 2023 21:20:34 +0000 Subject: [PATCH 128/133] chore(release): 5.15.1 [skip ci] ## [5.15.1](https://github.com/appium/WebDriverAgent/compare/v5.15.0...v5.15.1) (2023-11-16) ### Bug Fixes * Content-Type of the MJPEG server ([b4704da](https://github.com/appium/WebDriverAgent/commit/b4704dafc4567e1f0dc8675facfc48a195aae4bf)) ### Code Refactoring * Optimize screenshots preprocessing ([#812](https://github.com/appium/WebDriverAgent/issues/812)) ([0b41757](https://github.com/appium/WebDriverAgent/commit/0b41757c0d21004afab32860b4e510d4bc426018)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 539251658..cf1bd97e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [5.15.1](https://github.com/appium/WebDriverAgent/compare/v5.15.0...v5.15.1) (2023-11-16) + + +### Bug Fixes + +* Content-Type of the MJPEG server ([b4704da](https://github.com/appium/WebDriverAgent/commit/b4704dafc4567e1f0dc8675facfc48a195aae4bf)) + + +### Code Refactoring + +* Optimize screenshots preprocessing ([#812](https://github.com/appium/WebDriverAgent/issues/812)) ([0b41757](https://github.com/appium/WebDriverAgent/commit/0b41757c0d21004afab32860b4e510d4bc426018)) + ## [5.15.0](https://github.com/appium/WebDriverAgent/compare/v5.14.0...v5.15.0) (2023-11-16) diff --git a/package.json b/package.json index d5568caef..ea8a6b721 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.15.0", + "version": "5.15.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 08388fd602ee9d588a8780e8d141d748813782ed Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 23 Nov 2023 01:30:47 -0800 Subject: [PATCH 129/133] chore: a dummy commit to check a package release From 014d04df956e47fef67938b089511e80d344f007 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 23 Nov 2023 02:22:36 -0800 Subject: [PATCH 130/133] fix: fix run test ci (#814) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea8a6b721..30e48bd49 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "semantic-release": "^22.0.5", "sinon": "^17.0.0", "ts-node": "^10.9.1", - "typescript": "^5.1.6" + "typescript": "~5.2" }, "dependencies": { "@appium/base-driver": "^9.0.0", From 8c76380bc22e84c76b5429b7db2c29e9c024dba5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 23 Nov 2023 10:28:49 +0000 Subject: [PATCH 131/133] chore(release): 5.15.2 [skip ci] ## [5.15.2](https://github.com/appium/WebDriverAgent/compare/v5.15.1...v5.15.2) (2023-11-23) ### Bug Fixes * fix run test ci ([#814](https://github.com/appium/WebDriverAgent/issues/814)) ([014d04d](https://github.com/appium/WebDriverAgent/commit/014d04df956e47fef67938b089511e80d344f007)) ### Miscellaneous Chores * a dummy commit to check a package release ([08388fd](https://github.com/appium/WebDriverAgent/commit/08388fd602ee9d588a8780e8d141d748813782ed)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf1bd97e8..87c1177aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [5.15.2](https://github.com/appium/WebDriverAgent/compare/v5.15.1...v5.15.2) (2023-11-23) + + +### Bug Fixes + +* fix run test ci ([#814](https://github.com/appium/WebDriverAgent/issues/814)) ([014d04d](https://github.com/appium/WebDriverAgent/commit/014d04df956e47fef67938b089511e80d344f007)) + + +### Miscellaneous Chores + +* a dummy commit to check a package release ([08388fd](https://github.com/appium/WebDriverAgent/commit/08388fd602ee9d588a8780e8d141d748813782ed)) + ## [5.15.1](https://github.com/appium/WebDriverAgent/compare/v5.15.0...v5.15.1) (2023-11-16) diff --git a/package.json b/package.json index 30e48bd49..ac2e671fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.15.1", + "version": "5.15.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 2d7fc0370b30e5e3adc9a13002fa95f607c4c160 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 24 Nov 2023 18:55:16 +0100 Subject: [PATCH 132/133] chore: Make xcodebuild error message more helpful (#816) --- lib/utils.js | 9 +++++- lib/xcodebuild.js | 72 +++++++++++++---------------------------------- 2 files changed, 28 insertions(+), 53 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 1474d929f..f52ec6fe0 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -265,12 +265,19 @@ function getXctestrunFileName (deviceInfo, version) { : `WebDriverAgentRunner_iphone${deviceInfo.isRealDevice ? `os${version}-arm64` : `simulator${version}-x86_64`}.xctestrun`; } +/** + * Ensures the process is killed after the timeout + * + * @param {string} name + * @param {import('teen_process').SubProcess} proc + * @returns {Promise} + */ async function killProcess (name, proc) { if (!proc || !proc.isRunning) { return; } - log.info(`Shutting down '${name}' process (pid '${proc.proc.pid}')`); + log.info(`Shutting down '${name}' process (pid '${proc.proc?.pid}')`); log.info(`Sending 'SIGTERM'...`); try { diff --git a/lib/xcodebuild.js b/lib/xcodebuild.js index 8194d1984..bdd484db2 100644 --- a/lib/xcodebuild.js +++ b/lib/xcodebuild.js @@ -1,17 +1,17 @@ import { retryInterval } from 'asyncbox'; import { SubProcess, exec } from 'teen_process'; -import { fs, logger, timing } from '@appium/support'; +import { logger, timing } from '@appium/support'; import defaultLogger from './logger'; import B from 'bluebird'; import { setRealDeviceSecurity, setXctestrunFile, updateProjectFile, resetProjectFile, killProcess, - getWDAUpgradeTimestamp, isTvOS } from './utils'; + getWDAUpgradeTimestamp, isTvOS +} from './utils'; import _ from 'lodash'; import path from 'path'; import { EOL } from 'os'; import { WDA_RUNNER_BUNDLE_ID } from './constants'; -import readline from 'node:readline'; const DEFAULT_SIGNING_ID = 'iPhone Developer'; @@ -34,6 +34,9 @@ const xcodeLog = logger.getLogger('Xcode'); class XcodeBuild { + /** @type {SubProcess} */ + xcodebuild; + /** * @param {string} xcodeVersion * @param {any} device @@ -85,10 +88,6 @@ class XcodeBuild { this.resultBundlePath = args.resultBundlePath; this.resultBundleVersion = args.resultBundleVersion; - /** @type {string} */ - this._logLocation = ''; - /** @type {string[]} */ - this._wdaErrorMessage = []; this._didBuildFail = false; this._didProcessExit = false; } @@ -168,8 +167,6 @@ class XcodeBuild { this.usePrebuiltWDA = true; await this.start(true); - this.xcodebuild = null; - if (this.prebuildDelay > 0) { // pause a moment await B.delay(this.prebuildDelay); @@ -286,7 +283,6 @@ class XcodeBuild { if (upgradeTimestamp) { env.UPGRADE_TIMESTAMP = upgradeTimestamp; } - this._logLocation = ''; this._didBuildFail = false; const xcodebuild = new SubProcess(cmd, args, { cwd: this.bootstrapPath, @@ -302,14 +298,6 @@ class XcodeBuild { this.log.debug(`${logMsg}. To change this, use 'showXcodeLog' desired capability`); xcodebuild.on('output', (stdout, stderr) => { let out = stdout || stderr; - // we want to pull out the log file that is created, and highlight it - // for diagnostic purposes - if (out.includes('Writing diagnostic log for test session to')) { - // pull out the first line that begins with the path separator - // which *should* be the line indicating the log file generated - this._logLocation = _.first(_.remove(out.trim().split('\n'), (v) => v.startsWith(path.sep))) ?? ''; - xcodeLog.debug(`Log file location for xcodebuild test: ${this._logLocation || 'unknown'}`); - } // if we have an error we want to output the logs // otherwise the failure is inscrutible @@ -326,9 +314,6 @@ class XcodeBuild { if (logXcodeOutput && !ignoreError) { for (const line of out.split(EOL)) { xcodeLog.error(line); - if (line) { - this._wdaErrorMessage.push(line); - } } } }); @@ -338,43 +323,27 @@ class XcodeBuild { async start (buildOnly = false) { this.xcodebuild = await this.createSubProcess(buildOnly); - // Store xcodebuild message - this._wdaErrorMessage = []; // wrap the start procedure in a promise so that we can catch, and report, // any startup errors that are thrown as events return await new B((resolve, reject) => { - // @ts-ignore xcodebuild must be present here - this.xcodebuild.once('exit', async (code, signal) => { + this.xcodebuild.once('exit', (code, signal) => { xcodeLog.error(`xcodebuild exited with code '${code}' and signal '${signal}'`); - this.xcodebuild?.removeAllListeners(); - const xcodeErrorMessage = this._wdaErrorMessage.join('\n'); - this._wdaErrorMessage = []; - // print out the xcodebuild file if users have asked for it - if (this.showXcodeLog && this._logLocation) { - xcodeLog.error(`Contents of xcodebuild log file '${this._logLocation}':`); - try { - const logFile = readline.createInterface({ - input: fs.createReadStream(this._logLocation), - terminal: false - }); - logFile.on('line', (line) => { - xcodeLog.error(line); - }); - await new B((_resolve) => { - logFile.once('close', () => { - logFile.removeAllListeners(); - _resolve(); - }); - }); - } catch (err) { - xcodeLog.error(`Unable to access xcodebuild log file: '${err.message}'`); - } - } + this.xcodebuild.removeAllListeners(); this.didProcessExit = true; if (this._didBuildFail || (!signal && code !== 0)) { - return reject(new Error(`xcodebuild failed with code ${code}\n` + - `xcodebuild error message:\n${xcodeErrorMessage}`)); + let errorMessage = `xcodebuild failed with code ${code}.` + + ` This usually indicates an issue with the local Xcode setup or WebDriverAgent` + + ` project configuration or the driver-to-platform version mismatch.`; + if (!this.showXcodeLog) { + errorMessage += ` Consider setting 'showXcodeLog' capability to true in` + + ` order to check the Appium server log for build-related error messages.`; + } else if (this.realDevice) { + errorMessage += ` Consider checking the WebDriverAgent configuration guide` + + ` for real iOS devices at` + + ` https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md.`; + } + return reject(new Error(errorMessage)); } // in the case of just building, the process will exit and that is our finish if (buildOnly) { @@ -385,7 +354,6 @@ class XcodeBuild { return (async () => { try { const timer = new timing.Timer().start(); - // @ts-ignore this.xcodebuild must be defined await this.xcodebuild.start(true); if (!buildOnly) { let status = await this.waitForStart(timer); From 0267f49da7c8f2637c5d6e936ae3f90b6fd934a6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 24 Nov 2023 18:04:50 +0000 Subject: [PATCH 133/133] chore(release): 5.15.3 [skip ci] ## [5.15.3](https://github.com/appium/WebDriverAgent/compare/v5.15.2...v5.15.3) (2023-11-24) ### Miscellaneous Chores * Make xcodebuild error message more helpful ([#816](https://github.com/appium/WebDriverAgent/issues/816)) ([2d7fc03](https://github.com/appium/WebDriverAgent/commit/2d7fc0370b30e5e3adc9a13002fa95f607c4c160)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87c1177aa..324828e67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.15.3](https://github.com/appium/WebDriverAgent/compare/v5.15.2...v5.15.3) (2023-11-24) + + +### Miscellaneous Chores + +* Make xcodebuild error message more helpful ([#816](https://github.com/appium/WebDriverAgent/issues/816)) ([2d7fc03](https://github.com/appium/WebDriverAgent/commit/2d7fc0370b30e5e3adc9a13002fa95f607c4c160)) + ## [5.15.2](https://github.com/appium/WebDriverAgent/compare/v5.15.1...v5.15.2) (2023-11-23) diff --git a/package.json b/package.json index ac2e671fb..bb4b9740f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.15.2", + "version": "5.15.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": {