From 3480bd4667fdfffbd2771519862c37f53aef1e70 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 14 Dec 2023 19:01:21 -0800 Subject: [PATCH 001/368] ci: teak tests (#824) * ci: teak tests * ci: skip one test to reduce flakiness * ci: skip some tests for ipad * use UIDevice * ci: skip long press * use number_of_retries to add -test-iterations and -retry-tests-on-failure for xcodebuild --- Fastlane/Fastfile | 1 + Fastlane/Pluginfile | 3 --- .../IntegrationTests/FBAlertTests.m | 3 +++ .../FBAppiumTouchActionsIntegrationTests.m | 3 +++ .../IntegrationTests/FBElementSwipingTests.m | 6 ++++++ .../IntegrationTests/FBKeyboardTests.m | 3 +++ WebDriverAgentTests/IntegrationTests/FBTapTest.m | 15 ++++++++++----- .../FBW3CTouchActionsIntegrationTests.m | 3 +++ 8 files changed, 29 insertions(+), 8 deletions(-) delete mode 100644 Fastlane/Pluginfile diff --git a/Fastlane/Fastfile b/Fastlane/Fastfile index 41fd63669..6e657a74e 100644 --- a/Fastlane/Fastfile +++ b/Fastlane/Fastfile @@ -8,5 +8,6 @@ lane :test do scheme: ENV['SCHEME'], sdk: ENV['SDK'], destination: ENV['DEST'], + number_of_retries: 3 ) end diff --git a/Fastlane/Pluginfile b/Fastlane/Pluginfile deleted file mode 100644 index 273a6b6f4..000000000 --- a/Fastlane/Pluginfile +++ /dev/null @@ -1,3 +0,0 @@ -# Autogenerated by fastlane -# -# Ensure this file is checked in to source control! diff --git a/WebDriverAgentTests/IntegrationTests/FBAlertTests.m b/WebDriverAgentTests/IntegrationTests/FBAlertTests.m index 57c48e492..3729c4d54 100644 --- a/WebDriverAgentTests/IntegrationTests/FBAlertTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBAlertTests.m @@ -154,8 +154,11 @@ - (void)testNotificationAlert XCTAssertTrue([alert.text containsString:@"Notifications may include"]); } +// It worked locally but CI did not. - (void)testCameraRollAlert { + XCTSkip(@"The alert depends on the permission condition. Azure CI env might have an issue to handle permission."); + FBAlert *alert = [FBAlert alertWithApplication:self.testedApplication]; XCTAssertNil(alert.text); diff --git a/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m index d48b3da77..51525e435 100644 --- a/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m @@ -244,6 +244,9 @@ - (void)testPress - (void)testLongPress { + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); + } UIDeviceOrientation orientation = UIDeviceOrientationLandscapeLeft; [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation]; CGRect elementFrame = self.testedApplication.buttons[FBShowAlertButtonName].frame; diff --git a/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m b/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m index caf5d9020..0a9d2f5c4 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m @@ -67,6 +67,9 @@ - (void)testSwipeDown - (void)testSwipeDownWithVelocity { + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); + } [self.scrollView fb_swipeWithDirection:@"up" velocity:@2500]; FBAssertInvisibleCell(@"0"); [self.scrollView fb_swipeWithDirection:@"down" velocity:@2500]; @@ -113,6 +116,9 @@ - (void)testSwipeDown - (void)testSwipeDownWithVelocity { + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); + } [self.testedApplication fb_swipeWithDirection:@"up" velocity:@2500]; FBAssertInvisibleCell(@"0"); [self.testedApplication fb_swipeWithDirection:@"down" velocity:@2500]; diff --git a/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m b/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m index 3da52e370..beca0c791 100644 --- a/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m @@ -29,6 +29,9 @@ - (void)setUp - (void)testTextTyping { + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); + } NSString *text = @"Happy typing"; XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"]; [textField tap]; diff --git a/WebDriverAgentTests/IntegrationTests/FBTapTest.m b/WebDriverAgentTests/IntegrationTests/FBTapTest.m index 9dce4084c..5b79711fc 100644 --- a/WebDriverAgentTests/IntegrationTests/FBTapTest.m +++ b/WebDriverAgentTests/IntegrationTests/FBTapTest.m @@ -33,12 +33,10 @@ - (void)verifyTapWithOrientation:(UIDeviceOrientation)orientation - (void)setUp { + // Launch the app everytime to ensure the orientation for each test. [super setUp]; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self launchApplication]; - [self goToAlertsPage]; - }); + [self launchApplication]; + [self goToAlertsPage]; [self clearAlert]; } @@ -61,11 +59,15 @@ - (void)testTapInLandscapeLeft - (void)testTapInLandscapeRight { + [self verifyTapWithOrientation:UIDeviceOrientationLandscapeRight]; } - (void)testTapInPortraitUpsideDown { + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); + } [self verifyTapWithOrientation:UIDeviceOrientationPortraitUpsideDown]; } @@ -94,6 +96,9 @@ - (void)testTapCoordinatesInLandscapeRight - (void)testTapCoordinatesInPortraitUpsideDown { + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); + } [self verifyTapByCoordinatesWithOrientation:UIDeviceOrientationPortraitUpsideDown]; } diff --git a/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m index 8549d3016..598cc66c9 100644 --- a/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m @@ -338,6 +338,9 @@ - (void)testLongPressWithCombinedPause - (void)testLongPress { + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); + } UIDeviceOrientation orientation = UIDeviceOrientationLandscapeLeft; [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation]; CGRect elementFrame = self.testedApplication.buttons[FBShowAlertButtonName].frame; From 766be59ef31753f4029c57c7a13cc01b1312cb9e Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 17 Dec 2023 07:59:54 -0800 Subject: [PATCH 002/368] ci: tune testCameraRollAlert for CI env (#828) --- WebDriverAgentTests/IntegrationTests/FBAlertTests.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/WebDriverAgentTests/IntegrationTests/FBAlertTests.m b/WebDriverAgentTests/IntegrationTests/FBAlertTests.m index 3729c4d54..a7cf04418 100644 --- a/WebDriverAgentTests/IntegrationTests/FBAlertTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBAlertTests.m @@ -154,21 +154,22 @@ - (void)testNotificationAlert XCTAssertTrue([alert.text containsString:@"Notifications may include"]); } -// It worked locally but CI did not. +// This test case depends on the local app permission state. - (void)testCameraRollAlert { - XCTSkip(@"The alert depends on the permission condition. Azure CI env might have an issue to handle permission."); - FBAlert *alert = [FBAlert alertWithApplication:self.testedApplication]; XCTAssertNil(alert.text); [self.testedApplication.buttons[@"Create Camera Roll Alert"] tap]; FBAssertWaitTillBecomesTrue(alert.isPresent); - XCTAssertTrue([alert.text containsString:@"Would Like to Access Your Photos"]); + // "Would Like to Access Your Photos" or "Would Like to Access Your Photo Library" displayes on the alert button. + XCTAssertTrue([alert.text containsString:@"Would Like to Access Your Photo"]); // iOS 15 has different UI flow if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) { [[FBAlert alertWithApplication:self.testedApplication] dismissWithError:nil]; + // CI env could take longer time to show up the button, thus it needs to wait a bit. + XCTAssertTrue([self.testedApplication.buttons[@"Cancel"] waitForExistenceWithTimeout:30.0]); [self.testedApplication.buttons[@"Cancel"] tap]; } } From 06cfb3b2b895a0bec681218fce658bdfcb4d13e9 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 6 Jan 2024 10:14:38 +0100 Subject: [PATCH 003/368] chore: Update keyboard typing implementation (#832) --- .../XCTest/XCSynthesizedEventRecord.h | 1 + .../Categories/XCUIElement+FBTyping.h | 10 ++++ .../Categories/XCUIElement+FBTyping.m | 46 +++++++++++++------ .../Commands/FBElementCommands.m | 2 +- WebDriverAgentLib/Utilities/FBConfiguration.h | 1 + WebDriverAgentLib/Utilities/FBConfiguration.m | 20 ++++++-- WebDriverAgentLib/Utilities/FBKeyboard.h | 27 ----------- WebDriverAgentLib/Utilities/FBKeyboard.m | 25 ---------- .../IntegrationTests/FBKeyboardTests.m | 25 ---------- .../IntegrationTests/FBTypingTest.m | 4 ++ 10 files changed, 64 insertions(+), 97 deletions(-) diff --git a/PrivateHeaders/XCTest/XCSynthesizedEventRecord.h b/PrivateHeaders/XCTest/XCSynthesizedEventRecord.h index 279eee3f0..d630eeb15 100644 --- a/PrivateHeaders/XCTest/XCSynthesizedEventRecord.h +++ b/PrivateHeaders/XCTest/XCSynthesizedEventRecord.h @@ -25,6 +25,7 @@ #if !TARGET_OS_TV - (id)initWithName:(NSString *)arg1 interfaceOrientation:(UIInterfaceOrientation)arg2; #endif +- (id)initWithName:(id)arg1; - (id)init; - (BOOL)synthesizeWithError:(NSError **)arg1; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h index 49ef3c6ce..c44aa7c57 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h @@ -11,6 +11,16 @@ NS_ASSUME_NONNULL_BEGIN +/** + Types a text into the currently focused element. + + @param text text that should be typed + @param typingSpeed Frequency of typing (letters per sec) + @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 FBTypeText(NSString *text, NSUInteger typingSpeed, NSError **error); + @interface XCUIElement (FBTyping) /** diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m index c6e31f4fc..db516a220 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m @@ -11,17 +11,34 @@ #import "FBConfiguration.h" #import "FBErrorBuilder.h" -#import "FBKeyboard.h" -#import "NSString+FBVisualLength.h" #import "FBXCElementSnapshotWrapper.h" #import "FBXCElementSnapshotWrapper+Helpers.h" +#import "FBXCodeCompatibility.h" +#import "FBXCTestDaemonsProxy.h" +#import "NSString+FBVisualLength.h" #import "XCUIDevice+FBHelpers.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBUtilities.h" -#import "FBXCodeCompatibility.h" +#import "XCSynthesizedEventRecord.h" +#import "XCPointerEventPath.h" +#define MAX_TEXT_ABBR_LEN 12 #define MAX_CLEAR_RETRIES 3 +BOOL FBTypeText(NSString *text, NSUInteger typingSpeed, NSError **error) +{ + NSString *name = text.length <= MAX_TEXT_ABBR_LEN + ? [NSString stringWithFormat:@"Type '%@'", text] + : [NSString stringWithFormat:@"Type '%@…'", [text substringToIndex:MAX_TEXT_ABBR_LEN]]; + XCSynthesizedEventRecord *eventRecord = [[XCSynthesizedEventRecord alloc] initWithName:name]; + XCPointerEventPath *ep = [[XCPointerEventPath alloc] initForTextInput]; + [ep typeText:text + atOffset:0.0 + typingSpeed:typingSpeed + shouldRedact:NO]; + [eventRecord addPointerEventPath:ep]; + return [FBXCTestDaemonsProxy synthesizeEventWithRecord:eventRecord error:error]; +} @interface NSString (FBRepeat) @@ -96,13 +113,12 @@ - (BOOL)fb_typeText:(NSString *)text id snapshot = self.fb_isResolvedFromCache.boolValue ? self.lastSnapshot : self.fb_takeSnapshot; - [self fb_prepareForTextInputWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot]]; - if (shouldClear && ![self fb_clearTextWithSnapshot:self.lastSnapshot - shouldPrepareForInput:NO - error:error]) { + FBXCElementSnapshotWrapper *wrapped = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; + [self fb_prepareForTextInputWithSnapshot:wrapped]; + if (shouldClear && ![self fb_clearTextWithSnapshot:wrapped shouldPrepareForInput:NO error:error]) { return NO; } - return [FBKeyboard typeText:text frequency:frequency error:error]; + return FBTypeText(text, frequency, error); } - (BOOL)fb_clearTextWithError:(NSError **)error @@ -122,15 +138,15 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot id currentValue = snapshot.value; if (nil != currentValue && ![currentValue isKindOfClass:NSString.class]) { return [[[FBErrorBuilder builder] - withDescriptionFormat:@"The value of '%@' is not a string and thus cannot be edited", snapshot.fb_description] - buildError:error]; + withDescriptionFormat:@"The value of '%@' is not a string and thus cannot be edited", snapshot.fb_description] + buildError:error]; } - + if (nil == currentValue || 0 == [currentValue fb_visualLength]) { // Short circuit if the content is not present return YES; } - + static NSString *backspaceDeleteSequence; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -160,8 +176,8 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot } 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]) { + return FBTypeText(backspaceDeleteSequence, FBConfiguration.defaultTypingFrequency, error); + } else if (!FBTypeText(backspacesToType, FBConfiguration.defaultTypingFrequency, error)) { // 2nd operation return NO; } @@ -181,7 +197,7 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot // 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]; + return FBTypeText(backspacesToType, FBConfiguration.defaultTypingFrequency, error); #endif } diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 0f163521b..a749c00a7 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -558,7 +558,7 @@ + (NSArray *)routes NSString *textToType = [request.arguments[@"value"] componentsJoinedByString:@""]; NSUInteger frequency = [request.arguments[@"frequency"] unsignedIntegerValue] ?: [FBConfiguration maxTypingFrequency]; NSError *error; - if (![FBKeyboard typeText:textToType frequency:frequency error:&error]) { + if (!FBTypeText(textToType, frequency, &error)) { return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description traceback:nil]); } diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index dd0015e56..c07c31a1e 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -60,6 +60,7 @@ extern NSString *const FBSnapshotMaxDepthKey; /* The maximum typing frequency for all typing activities */ + (void)setMaxTypingFrequency:(NSUInteger)value; + (NSUInteger)maxTypingFrequency; ++ (NSUInteger)defaultTypingFrequency; /* Use singleton test manager proxy */ + (void)setShouldUseSingletonTestManager:(BOOL)value; diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index 03b6a6b1b..3bb740a0b 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -39,7 +39,7 @@ // Session-specific settings static BOOL FBShouldTerminateApp; -static NSUInteger FBMaxTypingFrequency; +static NSNumber* FBMaxTypingFrequency; static NSUInteger FBScreenshotQuality; static NSTimeInterval FBCustomSnapshotTimeout; static BOOL FBShouldUseFirstMatch; @@ -57,6 +57,13 @@ @implementation FBConfiguration ++ (NSUInteger)defaultTypingFrequency +{ + NSInteger defaultFreq = [[NSUserDefaults standardUserDefaults] + integerForKey:@"com.apple.xctest.iOSMaximumTypingFrequency"]; + return defaultFreq > 0 ? defaultFreq : 60; +} + + (void)initialize { [FBConfiguration resetSessionSettings]; @@ -200,12 +207,17 @@ + (NSString *)elementResponseAttributes + (void)setMaxTypingFrequency:(NSUInteger)value { - FBMaxTypingFrequency = value; + FBMaxTypingFrequency = @(value); } + (NSUInteger)maxTypingFrequency { - return FBMaxTypingFrequency; + if (nil == FBMaxTypingFrequency) { + return [self defaultTypingFrequency]; + } + return FBMaxTypingFrequency.integerValue <= 0 + ? [self defaultTypingFrequency] + : FBMaxTypingFrequency.integerValue; } + (void)setShouldUseSingletonTestManager:(BOOL)value @@ -462,7 +474,7 @@ + (void)resetSessionSettings FBShouldTerminateApp = YES; FBShouldUseCompactResponses = YES; FBElementResponseAttributes = @"type,label"; - FBMaxTypingFrequency = 60; + FBMaxTypingFrequency = @([self defaultTypingFrequency]); FBScreenshotQuality = 3; FBCustomSnapshotTimeout = 15.; FBShouldUseFirstMatch = NO; diff --git a/WebDriverAgentLib/Utilities/FBKeyboard.h b/WebDriverAgentLib/Utilities/FBKeyboard.h index 5a16e1aed..fa1515e6b 100644 --- a/WebDriverAgentLib/Utilities/FBKeyboard.h +++ b/WebDriverAgentLib/Utilities/FBKeyboard.h @@ -23,19 +23,6 @@ NS_ASSUME_NONNULL_BEGIN + (nullable NSString *)keyValueForName:(NSString *)name; #endif -/** - Types a string into active element. There must be element with keyboard focus; otherwise an - error is raised. - - This API discards any modifiers set in the current context by +performWithKeyModifiers:block: so that - it strictly interprets the provided text. To input keys with modifier flags, use -typeKey:modifierFlags:. - - @param text that should be typed - @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)typeText:(NSString *)text error:(NSError **)error; - /** Waits until the keyboard is visible on the screen or a timeout happens @@ -46,20 +33,6 @@ NS_ASSUME_NONNULL_BEGIN */ + (BOOL)waitUntilVisibleForApplication:(XCUIApplication *)app timeout:(NSTimeInterval)timeout error:(NSError **)error; -/** - Types a string into active element. There must be element with keyboard focus; otherwise an - error is raised. - - This API discards any modifiers set in the current context by +performWithKeyModifiers:block: so that - it strictly interprets the provided text. To input keys with modifier flags, use -typeKey:modifierFlags:. - - @param text that should be typed - @param frequency Frequency of typing (letters per sec) - @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)typeText:(NSString *)text frequency:(NSUInteger)frequency error:(NSError **)error; - @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBKeyboard.m b/WebDriverAgentLib/Utilities/FBKeyboard.m index 0cf9964c6..e1f5fdc5b 100644 --- a/WebDriverAgentLib/Utilities/FBKeyboard.m +++ b/WebDriverAgentLib/Utilities/FBKeyboard.m @@ -25,31 +25,6 @@ @implementation FBKeyboard -+ (BOOL)typeText:(NSString *)text error:(NSError **)error -{ - return [self typeText:text frequency:[FBConfiguration maxTypingFrequency] error:error]; -} - -+ (BOOL)typeText:(NSString *)text frequency:(NSUInteger)frequency error:(NSError **)error -{ - __block BOOL didSucceed = NO; - __block NSError *innerError; - [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ - [[FBXCTestDaemonsProxy testRunnerProxy] - _XCT_sendString:text - maximumFrequency:frequency - completion:^(NSError *typingError){ - didSucceed = (typingError == nil); - innerError = typingError; - completion(); - }]; - }]; - if (error) { - *error = innerError; - } - return didSucceed; -} - + (BOOL)waitUntilVisibleForApplication:(XCUIApplication *)app timeout:(NSTimeInterval)timeout error:(NSError **)error { BOOL (^isKeyboardVisible)(void) = ^BOOL(void) { diff --git a/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m b/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m index beca0c791..793a99667 100644 --- a/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBKeyboardTests.m @@ -27,31 +27,6 @@ - (void)setUp [self goToAttributesPage]; } -- (void)testTextTyping -{ - if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { - XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); - } - NSString *text = @"Happy typing"; - XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"]; - [textField tap]; - - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) { - // A workaround until find out to clear tutorial on iOS 15 - XCUIElement *textField = self.testedApplication.staticTexts[@"Continue"]; - if (textField.hittable) { - [textField tap]; - } - } - - NSError *error; - XCTAssertTrue([FBKeyboard waitUntilVisibleForApplication:self.testedApplication timeout:1 error:&error]); - XCTAssertNil(error); - XCTAssertTrue([FBKeyboard typeText:text error:&error]); - XCTAssertNil(error); - XCTAssertEqualObjects(textField.value, text); -} - - (void)testKeyboardDismissal { XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"]; diff --git a/WebDriverAgentTests/IntegrationTests/FBTypingTest.m b/WebDriverAgentTests/IntegrationTests/FBTypingTest.m index c0c8d1426..e11ac9402 100644 --- a/WebDriverAgentTests/IntegrationTests/FBTypingTest.m +++ b/WebDriverAgentTests/IntegrationTests/FBTypingTest.m @@ -60,6 +60,10 @@ - (void)testTextClearing XCTAssertTrue([textField fb_clearTextWithError:&error]); XCTAssertNil(error); XCTAssertEqualObjects(textField.value, @""); + XCTAssertTrue([textField fb_typeText:@"Happy typing" shouldClear:YES error:&error]); + XCTAssertTrue([textField fb_typeText:@"Happy typing 2" shouldClear:YES error:&error]); + XCTAssertEqualObjects(textField.value, @"Happy typing 2"); + XCTAssertNil(error); } @end From bb3902957f792de2667f0ecf0ee57aa7f472739b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 6 Jan 2024 09:20:39 +0000 Subject: [PATCH 004/368] chore(release): 5.15.6 [skip ci] ## [5.15.6](https://github.com/appium/WebDriverAgent/compare/v5.15.5...v5.15.6) (2024-01-06) ### Miscellaneous Chores * Update keyboard typing implementation ([#832](https://github.com/appium/WebDriverAgent/issues/832)) ([06cfb3b](https://github.com/appium/WebDriverAgent/commit/06cfb3b2b895a0bec681218fce658bdfcb4d13e9)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4eb6d86a..8d2c85a7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.15.6](https://github.com/appium/WebDriverAgent/compare/v5.15.5...v5.15.6) (2024-01-06) + + +### Miscellaneous Chores + +* Update keyboard typing implementation ([#832](https://github.com/appium/WebDriverAgent/issues/832)) ([06cfb3b](https://github.com/appium/WebDriverAgent/commit/06cfb3b2b895a0bec681218fce658bdfcb4d13e9)) + ## [5.15.5](https://github.com/appium/WebDriverAgent/compare/v5.15.4...v5.15.5) (2023-12-13) diff --git a/package.json b/package.json index e5927c1fb..3c5c458e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.15.5", + "version": "5.15.6", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 70a8d98bc15d8fc615455be07fad9c37ff8d430b Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 13 Jan 2024 20:49:42 +0100 Subject: [PATCH 005/368] refactor: Ditch FBApplication in favour of XCUIApplication extensions (#834) --- PrivateHeaders/XCTest/XCUIApplication.h | 1 - WebDriverAgent.xcodeproj/project.pbxproj | 24 +-- .../Categories/XCUIApplication+FBHelpers.h | 38 ++++ .../Categories/XCUIApplication+FBHelpers.m | 153 ++++++++++++++- .../Categories/XCUIDevice+FBHelpers.m | 2 +- .../Categories/XCUIDevice+FBRotation.h | 1 - .../Categories/XCUIDevice+FBRotation.m | 8 +- .../Categories/XCUIElement+FBTVFocuse.m | 4 +- .../Commands/FBAlertViewCommands.m | 8 +- WebDriverAgentLib/Commands/FBCustomCommands.m | 4 +- WebDriverAgentLib/Commands/FBDebugCommands.m | 5 +- .../Commands/FBElementCommands.m | 6 +- .../Commands/FBFindElementCommands.m | 1 - .../Commands/FBOrientationCommands.m | 17 +- .../Commands/FBSessionCommands.m | 16 +- .../Commands/FBTouchActionCommands.m | 1 - WebDriverAgentLib/FBAlert.m | 6 +- WebDriverAgentLib/FBApplication.h | 49 ----- WebDriverAgentLib/FBApplication.m | 185 ------------------ WebDriverAgentLib/Routing/FBSession.h | 27 ++- WebDriverAgentLib/Routing/FBSession.m | 95 ++++----- WebDriverAgentLib/Utilities/FBAlertsMonitor.m | 6 +- WebDriverAgentLib/Utilities/FBKeyboard.m | 11 +- WebDriverAgentLib/Utilities/FBMjpegServer.m | 1 - WebDriverAgentLib/Utilities/FBPasteboard.m | 4 +- WebDriverAgentLib/Utilities/FBScreen.m | 3 +- .../Utilities/FBTVNavigationTracker.m | 3 +- .../Utilities/FBXCodeCompatibility.h | 33 ---- .../Utilities/FBXCodeCompatibility.m | 42 +--- WebDriverAgentLib/WebDriverAgentLib.h | 1 - .../FBAutoAlertsHandlerTests.m | 5 +- .../FBElementVisibilityTests.m | 1 - .../IntegrationTests/FBIntegrationTestCase.h | 4 +- .../IntegrationTests/FBIntegrationTestCase.m | 10 +- .../IntegrationTests/FBSafariAlertTests.m | 3 +- .../FBSessionIntegrationTests.m | 21 +- .../IntegrationTests/FBTapTest.m | 1 - .../FBW3CMultiTouchActionsIntegrationTests.m | 1 - .../XCUIApplicationHelperTests.m | 16 +- .../IntegrationTests/XCUIDeviceHelperTests.m | 9 +- .../XCUIElementHelperIntegrationTests.m | 1 - ...cationDouble.h => XCUIApplicationDouble.h} | 2 +- ...cationDouble.m => XCUIApplicationDouble.m} | 6 +- .../UnitTests/FBSessionTests.m | 6 +- 44 files changed, 346 insertions(+), 495 deletions(-) delete mode 100644 WebDriverAgentLib/FBApplication.h delete mode 100644 WebDriverAgentLib/FBApplication.m rename WebDriverAgentTests/UnitTests/Doubles/{FBApplicationDouble.h => XCUIApplicationDouble.h} (92%) rename WebDriverAgentTests/UnitTests/Doubles/{FBApplicationDouble.m => XCUIApplicationDouble.m} (88%) diff --git a/PrivateHeaders/XCTest/XCUIApplication.h b/PrivateHeaders/XCTest/XCUIApplication.h index 34bf69032..e092f26db 100644 --- a/PrivateHeaders/XCTest/XCUIApplication.h +++ b/PrivateHeaders/XCTest/XCUIApplication.h @@ -39,7 +39,6 @@ @property(readonly) id/*XCAccessibilityElement*/ accessibilityElement; + (instancetype)applicationWithPID:(pid_t)processID; -/*! DO NOT USE DIRECTLY! Please use fb_activate instead */ - (void)activate; - (void)dismissKeyboard; diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index 836267cce..4c098bde8 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -109,7 +109,6 @@ 641EE61E2240C5CA00173FCB /* FBExceptionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC088E71CB56DA400B65968 /* FBExceptionHandler.m */; }; 641EE61F2240C5CA00173FCB /* FBXCodeCompatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5A24411F136C8D0078B1D9 /* FBXCodeCompatibility.m */; }; 641EE6212240C5CA00173FCB /* FBElementTypeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7901CAEDF0C008C271F /* FBElementTypeTransformer.m */; }; - 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 */; }; 641EE6262240C5CA00173FCB /* FBMathUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = EE1888391DA661C400307AA8 /* FBMathUtils.m */; }; @@ -142,7 +141,6 @@ 641EE64B2240C5CA00173FCB /* XCTAsyncActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACCB1E3B77D600A02D78 /* XCTAsyncActivity.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE64C2240C5CA00173FCB /* XCTestMisuseObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACDF1E3B77D600A02D78 /* XCTestMisuseObserver.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE64D2240C5CA00173FCB /* XCTRunnerDaemonSession.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACEF1E3B77D600A02D78 /* XCTRunnerDaemonSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 641EE64E2240C5CA00173FCB /* FBApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7661CAEDF0C008C271F /* FBApplication.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE64F2240C5CA00173FCB /* XCTestExpectationWaiter.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACDA1E3B77D600A02D78 /* XCTestExpectationWaiter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6502240C5CA00173FCB /* UIGestureRecognizer-RecordingAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACAD1E3B77D600A02D78 /* UIGestureRecognizer-RecordingAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6512240C5CA00173FCB /* XCKeyboardKeyMap.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACBF1E3B77D600A02D78 /* XCKeyboardKeyMap.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -619,8 +617,6 @@ EE158AE91CBD456F00A3E3F0 /* FBElementTypeTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7901CAEDF0C008C271F /* FBElementTypeTransformer.m */; }; EE158AEA1CBD456F00A3E3F0 /* FBRuntimeUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7911CAEDF0C008C271F /* FBRuntimeUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; EE158AEB1CBD456F00A3E3F0 /* FBRuntimeUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7921CAEDF0C008C271F /* FBRuntimeUtils.m */; }; - EE158AF51CBD456F00A3E3F0 /* FBApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7661CAEDF0C008C271F /* FBApplication.h */; settings = {ATTRIBUTES = (Public, ); }; }; - EE158AF61CBD456F00A3E3F0 /* FBApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7671CAEDF0C008C271F /* FBApplication.m */; }; EE158B5A1CBD462100A3E3F0 /* WebDriverAgentLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE158A991CBD452B00A3E3F0 /* WebDriverAgentLib.framework */; }; EE158B5F1CBD47A000A3E3F0 /* WebDriverAgentLib.h in Headers */ = {isa = PBXBuildFile; fileRef = EE158B5E1CBD47A000A3E3F0 /* WebDriverAgentLib.h */; settings = {ATTRIBUTES = (Public, ); }; }; EE18883A1DA661C400307AA8 /* FBMathUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = EE1888381DA661C400307AA8 /* FBMathUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -756,7 +752,7 @@ EE55B3271D1D54CF003AAAEC /* FBScrollingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE55B3261D1D54CF003AAAEC /* FBScrollingTests.m */; }; EE5A24421F136D360078B1D9 /* FBXCodeCompatibility.m in Sources */ = {isa = PBXBuildFile; fileRef = EE5A24411F136C8D0078B1D9 /* FBXCodeCompatibility.m */; }; EE6A89261D0B19E60083E92B /* FBSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE6A89251D0B19E60083E92B /* FBSessionTests.m */; }; - EE6A892B1D0B25820083E92B /* FBApplicationDouble.m in Sources */ = {isa = PBXBuildFile; fileRef = EE6A89281D0B257B0083E92B /* FBApplicationDouble.m */; }; + EE6A892B1D0B25820083E92B /* XCUIApplicationDouble.m in Sources */ = {isa = PBXBuildFile; fileRef = EE6A89281D0B257B0083E92B /* XCUIApplicationDouble.m */; }; EE6A892D1D0B2AF40083E92B /* FBErrorBuilderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE6A892C1D0B2AF40083E92B /* FBErrorBuilderTests.m */; }; EE6A89371D0B35920083E92B /* FBFailureProofTestCaseTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE6A89361D0B35920083E92B /* FBFailureProofTestCaseTests.m */; }; EE6A893A1D0B38640083E92B /* FBFailureProofTestCase.h in Headers */ = {isa = PBXBuildFile; fileRef = EE6A89381D0B38640083E92B /* FBFailureProofTestCase.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1254,8 +1250,8 @@ EE5A24401F136C8D0078B1D9 /* FBXCodeCompatibility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXCodeCompatibility.h; sourceTree = ""; }; EE5A24411F136C8D0078B1D9 /* FBXCodeCompatibility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCodeCompatibility.m; sourceTree = ""; }; EE6A89251D0B19E60083E92B /* FBSessionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSessionTests.m; sourceTree = ""; }; - EE6A89271D0B257B0083E92B /* FBApplicationDouble.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBApplicationDouble.h; sourceTree = ""; }; - EE6A89281D0B257B0083E92B /* FBApplicationDouble.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBApplicationDouble.m; sourceTree = ""; }; + EE6A89271D0B257B0083E92B /* XCUIApplicationDouble.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCUIApplicationDouble.h; sourceTree = ""; }; + EE6A89281D0B257B0083E92B /* XCUIApplicationDouble.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XCUIApplicationDouble.m; sourceTree = ""; }; EE6A892C1D0B2AF40083E92B /* FBErrorBuilderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBErrorBuilderTests.m; sourceTree = ""; }; EE6A89361D0B35920083E92B /* FBFailureProofTestCaseTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBFailureProofTestCaseTests.m; sourceTree = ""; }; EE6A89381D0B38640083E92B /* FBFailureProofTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBFailureProofTestCase.h; sourceTree = ""; }; @@ -1296,8 +1292,6 @@ EE9AB7631CAEDF0C008C271F /* FBTouchIDCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBTouchIDCommands.m; sourceTree = ""; }; EE9AB7641CAEDF0C008C271F /* FBUnknownCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBUnknownCommands.h; sourceTree = ""; }; EE9AB7651CAEDF0C008C271F /* FBUnknownCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBUnknownCommands.m; sourceTree = ""; }; - EE9AB7661CAEDF0C008C271F /* FBApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FBApplication.h; path = WebDriverAgentLib/FBApplication.h; sourceTree = SOURCE_ROOT; }; - EE9AB7671CAEDF0C008C271F /* FBApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FBApplication.m; path = WebDriverAgentLib/FBApplication.m; sourceTree = SOURCE_ROOT; }; EE9AB7731CAEDF0C008C271F /* WebDriverAgent.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = WebDriverAgent.bundle; sourceTree = ""; }; EE9AB7751CAEDF0C008C271F /* FBCommandHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBCommandHandler.h; sourceTree = ""; }; EE9AB7761CAEDF0C008C271F /* FBCommandStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBCommandStatus.h; sourceTree = ""; }; @@ -1615,8 +1609,8 @@ 13FFF2F1287DBEE600E561E4 /* XCElementSnapshotDouble.m */, ADBC39961D07842800327304 /* XCUIElementDouble.h */, ADBC39971D07842800327304 /* XCUIElementDouble.m */, - EE6A89271D0B257B0083E92B /* FBApplicationDouble.h */, - EE6A89281D0B257B0083E92B /* FBApplicationDouble.m */, + EE6A89271D0B257B0083E92B /* XCUIApplicationDouble.h */, + EE6A89281D0B257B0083E92B /* XCUIApplicationDouble.m */, ); path = Doubles; sourceTree = ""; @@ -2096,8 +2090,6 @@ EE158B5E1CBD47A000A3E3F0 /* WebDriverAgentLib.h */, AD6C26921CF2379700F8B5FF /* FBAlert.h */, AD6C26931CF2379700F8B5FF /* FBAlert.m */, - EE9AB7661CAEDF0C008C271F /* FBApplication.h */, - EE9AB7671CAEDF0C008C271F /* FBApplication.m */, EE3A18641CDE734B00DE4205 /* FBKeyboard.h */, EE3A18651CDE734B00DE4205 /* FBKeyboard.m */, EE158B5D1CBD479000A3E3F0 /* Info.plist */, @@ -2283,7 +2275,6 @@ 641EE64D2240C5CA00173FCB /* XCTRunnerDaemonSession.h in Headers */, 714E14B929805CAE00375DD7 /* XCAXClient_iOS+FBSnapshotReqParams.h in Headers */, 64B2650B228CE4FF002A5025 /* FBTVNavigationTracker-Private.h in Headers */, - 641EE64E2240C5CA00173FCB /* FBApplication.h in Headers */, 641EE64F2240C5CA00173FCB /* XCTestExpectationWaiter.h in Headers */, 13DE7A5C287CA444003243C6 /* FBXCElementSnapshotWrapper+Helpers.h in Headers */, 641EE6502240C5CA00173FCB /* UIGestureRecognizer-RecordingAdditions.h in Headers */, @@ -2515,7 +2506,6 @@ EE35AD601E3B77D600A02D78 /* XCTRunnerDaemonSession.h in Headers */, 71414ED62670A1EE003A8C5D /* LRUCacheNode.h in Headers */, 64B2650A228CE4FF002A5025 /* FBTVNavigationTracker-Private.h in Headers */, - EE158AF51CBD456F00A3E3F0 /* FBApplication.h in Headers */, 71B155DF23080CA600646AFB /* FBProtocolHelpers.h in Headers */, EE35AD4B1E3B77D600A02D78 /* XCTestExpectationWaiter.h in Headers */, EE35AD1E1E3B77D600A02D78 /* UIGestureRecognizer-RecordingAdditions.h in Headers */, @@ -3158,7 +3148,6 @@ 641EE61F2240C5CA00173FCB /* FBXCodeCompatibility.m in Sources */, 71E75E70254824230099FC87 /* XCUIElementQuery+FBHelpers.m in Sources */, 641EE6212240C5CA00173FCB /* FBElementTypeTransformer.m in Sources */, - 641EE6222240C5CA00173FCB /* FBApplication.m in Sources */, 13DE7A5E287CA444003243C6 /* FBXCElementSnapshotWrapper+Helpers.m in Sources */, 641EE6232240C5CA00173FCB /* FBScreen.m in Sources */, 71D04DCB25356C43008A052C /* XCUIElement+FBCaching.m in Sources */, @@ -3292,7 +3281,6 @@ E444DC9D249131D40060D7EB /* HTTPMessage.m in Sources */, E444DCB024913C220060D7EB /* RouteResponse.m in Sources */, 71D3B3D7267FC7260076473D /* XCUIElement+FBResolve.m in Sources */, - EE158AF61CBD456F00A3E3F0 /* FBApplication.m in Sources */, 715AFAC21FFA29180053896D /* FBScreen.m in Sources */, 71B155DC230711E900646AFB /* FBCommandStatus.m in Sources */, EE35AD7C1E3B80C000A02D78 /* FBXCTestDaemonsProxy.m in Sources */, @@ -3360,7 +3348,7 @@ EE9B76591CF7987800275851 /* FBRouteTests.m in Sources */, 7139145C1DF01A12005896C2 /* NSExpressionFBFormatTests.m in Sources */, 71A224E81DE326C500844D55 /* NSPredicateFBFormatTests.m in Sources */, - EE6A892B1D0B25820083E92B /* FBApplicationDouble.m in Sources */, + EE6A892B1D0B25820083E92B /* XCUIApplicationDouble.m in Sources */, 716F0DA62A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m in Sources */, EE6A892D1D0B2AF40083E92B /* FBErrorBuilderTests.m in Sources */, 712A0C851DA3E459007D02E5 /* FBXPathTests.m in Sources */, diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h index 13fabcf88..3ef66423b 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h @@ -122,6 +122,44 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable NSArray *> *)fb_performAccessibilityAuditWithAuditTypes:(uint64_t)auditTypes error:(NSError **)error; +/** + Constructor used to get current active application + */ ++ (instancetype)fb_activeApplication; + +/** + Constructor used to get current active application + + @param bundleId The bundle identifier of an app, which should be selected as active by default + if it is present in the list of active applications + */ ++ (instancetype)fb_activeApplicationWithDefaultBundleId:(nullable NSString *)bundleId; + +/** + Constructor used to get the system application (e.g. Springboard on iOS) + */ ++ (instancetype)fb_systemApplication; + +/** + Retrieves the list of all currently active applications + */ ++ (NSArray *)fb_activeApplications; + +/** + Switch to system app (called Springboard on iOS) + + @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_switchToSystemApplicationWithError:(NSError **)error; + +/** + Determines whether the other app is the same as the current one + + @param otherApp Other app instance + @return YES if the other app has the same identifier + */ +- (BOOL)fb_isSameAppAs:(nullable XCUIApplication *)otherApp; @end diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 2656de7d6..251fb7ad9 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -9,13 +9,14 @@ #import "XCUIApplication+FBHelpers.h" +#import "FBActiveAppDetectionPoint.h" #import "FBElementTypeTransformer.h" #import "FBKeyboard.h" #import "FBLogger.h" #import "FBExceptions.h" #import "FBMacros.h" #import "FBMathUtils.h" -#import "FBActiveAppDetectionPoint.h" +#import "FBRunLoopSpinner.h" #import "FBXCodeCompatibility.h" #import "FBXPath.h" #import "FBXCAccessibilityElement.h" @@ -23,14 +24,19 @@ #import "FBXCElementSnapshotWrapper+Helpers.h" #import "FBXCAXClientProxy.h" #import "FBXMLGenerationOptions.h" +#import "XCTestManager_ManagerInterface-Protocol.h" +#import "XCTestPrivateSymbols.h" +#import "XCTRunnerDaemonSession.h" +#import "XCUIApplication.h" +#import "XCUIApplicationImpl.h" +#import "XCUIApplicationProcess.h" #import "XCUIDevice+FBHelpers.h" +#import "XCUIElement.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBIsVisible.h" #import "XCUIElement+FBUtilities.h" #import "XCUIElement+FBWebDriverAttributes.h" -#import "XCTestManager_ManagerInterface-Protocol.h" -#import "XCTestPrivateSymbols.h" -#import "XCTRunnerDaemonSession.h" +#import "XCUIElementQuery.h" static NSString* const FBUnknownBundleId = @"unknown"; @@ -141,7 +147,7 @@ - (BOOL)fb_deactivateWithDuration:(NSTimeInterval)duration error:(NSError **)err return NO; } [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:MAX(duration, .0)]]; - [self fb_activate]; + [self activate]; return YES; } @@ -393,4 +399,141 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames return isSuccessful ? resultArray.copy : nil; } ++ (instancetype)fb_activeApplication +{ + return [self fb_activeApplicationWithDefaultBundleId:nil]; +} + ++ (NSArray *)fb_activeApplications +{ + NSArray> *activeApplicationElements = [FBXCAXClientProxy.sharedClient activeApplications]; + NSMutableArray *result = [NSMutableArray array]; + if (activeApplicationElements.count > 0) { + for (id applicationElement in activeApplicationElements) { + XCUIApplication *app = [XCUIApplication fb_applicationWithPID:applicationElement.processIdentifier]; + if (nil != app) { + [result addObject:app]; + } + } + } + return result.count > 0 ? result.copy : @[self.class.fb_systemApplication]; +} + ++ (instancetype)fb_activeApplicationWithDefaultBundleId:(nullable NSString *)bundleId +{ + NSArray> *activeApplicationElements = [FBXCAXClientProxy.sharedClient activeApplications]; + id activeApplicationElement = nil; + id currentElement = nil; + if (nil != bundleId) { + currentElement = FBActiveAppDetectionPoint.sharedInstance.axElement; + if (nil != currentElement) { + NSArray *appInfos = [self fb_appsInfoWithAxElements:@[currentElement]]; + [FBLogger logFmt:@"Detected on-screen application: %@", appInfos.firstObject[@"bundleId"]]; + if ([[appInfos.firstObject objectForKey:@"bundleId"] isEqualToString:(id)bundleId]) { + activeApplicationElement = currentElement; + } + } + } + if (nil == activeApplicationElement && activeApplicationElements.count > 1) { + if (nil != bundleId) { + NSArray *appInfos = [self fb_appsInfoWithAxElements:activeApplicationElements]; + NSMutableArray *bundleIds = [NSMutableArray array]; + for (NSDictionary *appInfo in appInfos) { + [bundleIds addObject:(NSString *)appInfo[@"bundleId"]]; + } + [FBLogger logFmt:@"Detected system active application(s): %@", bundleIds]; + // Try to select the desired application first + for (NSUInteger appIdx = 0; appIdx < appInfos.count; appIdx++) { + if ([[[appInfos objectAtIndex:appIdx] objectForKey:@"bundleId"] isEqualToString:(id)bundleId]) { + activeApplicationElement = [activeApplicationElements objectAtIndex:appIdx]; + break; + } + } + } + // Fall back to the "normal" algorithm if the desired application is either + // not set or is not active + if (nil == activeApplicationElement) { + if (nil == currentElement) { + currentElement = FBActiveAppDetectionPoint.sharedInstance.axElement; + } + if (nil == currentElement) { + [FBLogger log:@"Cannot precisely detect the current application. Will use the system's recently active one"]; + if (nil == bundleId) { + [FBLogger log:@"Consider changing the 'defaultActiveApplication' setting to the bundle identifier of the desired application under test"]; + } + } else { + for (id appElement in activeApplicationElements) { + if (appElement.processIdentifier == currentElement.processIdentifier) { + activeApplicationElement = appElement; + break; + } + } + } + } + } + + if (nil != activeApplicationElement) { + XCUIApplication *application = [XCUIApplication fb_applicationWithPID:activeApplicationElement.processIdentifier]; + if (nil != application) { + return application; + } + [FBLogger log:@"Cannot translate the active process identifier into an application object"]; + } + + if (activeApplicationElements.count > 0) { + [FBLogger logFmt:@"Getting the most recent active application (out of %@ total items)", @(activeApplicationElements.count)]; + for (id appElement in activeApplicationElements) { + XCUIApplication *application = [XCUIApplication fb_applicationWithPID:appElement.processIdentifier]; + if (nil != application) { + return application; + } + } + } + + [FBLogger log:@"Cannot retrieve any active applications. Assuming the system application is the active one"]; + return [self fb_systemApplication]; +} + ++ (instancetype)fb_systemApplication +{ + return [self fb_applicationWithPID: + [[FBXCAXClientProxy.sharedClient systemApplication] processIdentifier]]; +} + ++ (instancetype)fb_applicationWithPID:(pid_t)processID +{ + return [FBXCAXClientProxy.sharedClient monitoredApplicationWithProcessIdentifier:processID]; +} + ++ (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error +{ + XCUIApplication *systemApp = self.fb_systemApplication; + @try { + if (!systemApp.running) { + [systemApp launch]; + } else { + [systemApp activate]; + } + } @catch (NSException *e) { + return [[[FBErrorBuilder alloc] + withDescription:nil == e ? @"Cannot open the home screen" : e.reason] + buildError:error]; + } + return [[[[FBRunLoopSpinner new] + timeout:5] + timeoutErrorMessage:@"Timeout waiting until the home screen is visible"] + spinUntilTrue:^BOOL{ + return [systemApp fb_isSameAppAs:self.fb_activeApplication]; + } + error:error]; +} + +- (BOOL)fb_isSameAppAs:(nullable XCUIApplication *)otherApp +{ + if (nil == otherApp) { + return NO; + } + return [self.bundleID isEqualToString:(NSString *)otherApp.bundleID]; +} + @end diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m index 959ae2831..5b95b8c62 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m @@ -56,7 +56,7 @@ + (void)fb_registerAppforDetectLockState - (BOOL)fb_goToHomescreenWithError:(NSError **)error { - return [FBApplication fb_switchToSystemApplicationWithError:error]; + return [XCUIApplication fb_switchToSystemApplicationWithError:error]; } - (BOOL)fb_lockScreen:(NSError **)error diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h b/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h index 79271e628..993c301c7 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h @@ -8,7 +8,6 @@ */ #import -#import NS_ASSUME_NONNULL_BEGIN diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m b/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m index cff45cf6a..68b9b20a9 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m @@ -10,6 +10,8 @@ #import "XCUIDevice+FBRotation.h" #import "FBConfiguration.h" +#import "XCUIApplication.h" +#import "XCUIApplication+FBHelpers.h" #import "XCUIElement+FBUtilities.h" # if !TARGET_OS_TV @@ -18,7 +20,7 @@ @implementation XCUIDevice (FBRotation) - (BOOL)fb_setDeviceInterfaceOrientation:(UIDeviceOrientation)orientation { - FBApplication *application = FBApplication.fb_activeApplication; + XCUIApplication *application = XCUIApplication.fb_activeApplication; [XCUIDevice sharedDevice].orientation = orientation; return [self waitUntilInterfaceIsAtOrientation:orientation application:application]; } @@ -30,12 +32,12 @@ - (BOOL)fb_setDeviceRotation:(NSDictionary *)rotationObj return NO; } NSInteger orientation = keysForRotationObj.firstObject.integerValue; - FBApplication *application = FBApplication.fb_activeApplication; + XCUIApplication *application = XCUIApplication.fb_activeApplication; [XCUIDevice sharedDevice].orientation = orientation; return [self waitUntilInterfaceIsAtOrientation:orientation application:application]; } -- (BOOL)waitUntilInterfaceIsAtOrientation:(NSInteger)orientation application:(FBApplication *)application +- (BOOL)waitUntilInterfaceIsAtOrientation:(NSInteger)orientation application:(XCUIApplication *)application { // Tapping elements immediately after rotation may fail due to way UIKit is handling touches. // We should wait till UI cools off, before continuing diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m b/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m index 9c82515ad..30037646d 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m @@ -10,10 +10,10 @@ #import "XCUIElement+FBTVFocuse.h" #import -#import "FBApplication.h" #import "FBConfiguration.h" #import "FBErrorBuilder.h" #import +#import "XCUIApplication+FBHelpers.h" #import "XCUIElement+FBUtilities.h" #import "XCUIElement+FBWebDriverAttributes.h" @@ -25,7 +25,7 @@ @implementation XCUIElement (FBTVFocuse) - (BOOL)fb_setFocusWithError:(NSError**) error { - [FBApplication.fb_activeApplication fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; + [XCUIApplication.fb_activeApplication fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; if (!self.wdEnabled) { if (error) { diff --git a/WebDriverAgentLib/Commands/FBAlertViewCommands.m b/WebDriverAgentLib/Commands/FBAlertViewCommands.m index dd195fbb8..760244629 100644 --- a/WebDriverAgentLib/Commands/FBAlertViewCommands.m +++ b/WebDriverAgentLib/Commands/FBAlertViewCommands.m @@ -10,9 +10,9 @@ #import "FBAlertViewCommands.h" #import "FBAlert.h" -#import "FBApplication.h" #import "FBRouteRequest.h" #import "FBSession.h" +#import "XCUIApplication+FBHelpers.h" @implementation FBAlertViewCommands @@ -38,7 +38,7 @@ + (NSArray *)routes + (id)handleAlertGetTextCommand:(FBRouteRequest *)request { - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; NSString *alertText = [FBAlert alertWithApplication:application].text; if (!alertText) { return FBResponseWithStatus([FBCommandStatus noAlertOpenErrorWithMessage:nil @@ -73,7 +73,7 @@ + (NSArray *)routes + (id)handleAlertAcceptCommand:(FBRouteRequest *)request { - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; NSString *name = request.arguments[@"name"]; FBAlert *alert = [FBAlert alertWithApplication:application]; NSError *error; @@ -96,7 +96,7 @@ + (NSArray *)routes + (id)handleAlertDismissCommand:(FBRouteRequest *)request { - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; NSString *name = request.arguments[@"name"]; FBAlert *alert = [FBAlert alertWithApplication:application]; NSError *error; diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index 5b1ce72ae..f31c96739 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -12,7 +12,6 @@ #import #import -#import "FBApplication.h" #import "FBConfiguration.h" #import "FBKeyboard.h" #import "FBNotificationsHelper.h" @@ -24,6 +23,7 @@ #import "FBScreen.h" #import "FBSession.h" #import "FBXCodeCompatibility.h" +#import "XCUIApplication.h" #import "XCUIApplication+FBHelpers.h" #import "XCUIDevice+FBHelpers.h" #import "XCUIElement.h" @@ -171,7 +171,7 @@ + (NSArray *)routes + (id)handleActiveAppInfo:(FBRouteRequest *)request { - XCUIApplication *app = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *app = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; return FBResponseWithObject(@{ @"pid": @(app.processID), @"bundleId": app.bundleID, diff --git a/WebDriverAgentLib/Commands/FBDebugCommands.m b/WebDriverAgentLib/Commands/FBDebugCommands.m index d290ebe6c..dc96958d0 100644 --- a/WebDriverAgentLib/Commands/FBDebugCommands.m +++ b/WebDriverAgentLib/Commands/FBDebugCommands.m @@ -9,7 +9,6 @@ #import "FBDebugCommands.h" -#import "FBApplication.h" #import "FBRouteRequest.h" #import "FBSession.h" #import "FBXMLGenerationOptions.h" @@ -42,7 +41,7 @@ + (NSArray *)routes + (id)handleGetSourceCommand:(FBRouteRequest *)request { // This method might be called without session - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; NSString *sourceType = request.parameters[@"format"] ?: SOURCE_FORMAT_XML; NSString *sourceScope = request.parameters[@"scope"]; id result; @@ -71,7 +70,7 @@ + (NSArray *)routes + (id)handleGetAccessibleSourceCommand:(FBRouteRequest *)request { // This method might be called without session - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; return FBResponseWithObject(application.fb_accessibilityTree ?: @{}); } diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index a749c00a7..4d5a69ea3 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -9,7 +9,6 @@ #import "FBElementCommands.h" -#import "FBApplication.h" #import "FBConfiguration.h" #import "FBKeyboard.h" #import "FBRoute.h" @@ -18,7 +17,6 @@ #import "FBElementCache.h" #import "FBErrorBuilder.h" #import "FBSession.h" -#import "FBApplication.h" #import "FBElementUtils.h" #import "FBMacros.h" #import "FBMathUtils.h" @@ -529,7 +527,7 @@ + (NSArray *)routes { XCUIElement *element = nil; if (nil == request.parameters[@"uuid"]) { - element = [FBApplication fb_activeApplication]; + element = XCUIApplication.fb_activeApplication; } else { FBElementCache *elementCache = request.session.elementCache; element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; @@ -567,7 +565,7 @@ + (NSArray *)routes + (id)handleGetWindowSize:(FBRouteRequest *)request { - XCUIApplication *app = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *app = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; #if TARGET_OS_TV CGSize screenSize = app.frame.size; diff --git a/WebDriverAgentLib/Commands/FBFindElementCommands.m b/WebDriverAgentLib/Commands/FBFindElementCommands.m index 037dbae15..ba30a7170 100644 --- a/WebDriverAgentLib/Commands/FBFindElementCommands.m +++ b/WebDriverAgentLib/Commands/FBFindElementCommands.m @@ -10,7 +10,6 @@ #import "FBFindElementCommands.h" #import "FBAlert.h" -#import "FBApplication.h" #import "FBConfiguration.h" #import "FBElementCache.h" #import "FBExceptions.h" diff --git a/WebDriverAgentLib/Commands/FBOrientationCommands.m b/WebDriverAgentLib/Commands/FBOrientationCommands.m index 185b6f2f3..aa4de26f7 100644 --- a/WebDriverAgentLib/Commands/FBOrientationCommands.m +++ b/WebDriverAgentLib/Commands/FBOrientationCommands.m @@ -12,7 +12,8 @@ #import "FBRouteRequest.h" #import "FBMacros.h" #import "FBSession.h" -#import "FBApplication.h" +#import "XCUIApplication.h" +#import "XCUIApplication+FBHelpers.h" #import "XCUIDevice.h" extern const struct FBWDOrientationValues { @@ -55,14 +56,14 @@ + (NSArray *)routes + (id)handleGetOrientation:(FBRouteRequest *)request { - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; NSString *orientation = [self.class interfaceOrientationForApplication:application]; return FBResponseWithObject([[self _wdOrientationsMapping] objectForKey:orientation]); } + (id)handleSetOrientation:(FBRouteRequest *)request { - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; if ([self.class setDeviceOrientation:request.arguments[@"orientation"] forApplication:application]) { return FBResponseWithOK(); } @@ -73,7 +74,7 @@ + (NSArray *)routes + (id)handleGetRotation:(FBRouteRequest *)request { XCUIDevice *device = [XCUIDevice sharedDevice]; - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; UIInterfaceOrientation orientation = application.interfaceOrientation; return FBResponseWithObject(device.fb_rotationMapping[@(orientation)]); } @@ -101,7 +102,7 @@ + (NSArray *)routes traceback:nil]); } - FBApplication *application = request.session.activeApplication ?: FBApplication.fb_activeApplication; + XCUIApplication *application = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; if (![self.class setDeviceRotation:request.arguments forApplication:application]) { NSString *errMessage = [ NSString stringWithFormat:@"The current rotation cannot be set to %@. Make sure the %@ application supports it", @@ -116,7 +117,7 @@ + (NSArray *)routes #pragma mark - Helpers -+ (NSString *)interfaceOrientationForApplication:(FBApplication *)application ++ (NSString *)interfaceOrientationForApplication:(XCUIApplication *)application { NSNumber *orientation = @(application.interfaceOrientation); NSSet *keys = [[self _orientationsMapping] keysOfEntriesPassingTest:^BOOL(id key, NSNumber *obj, BOOL *stop) { @@ -128,12 +129,12 @@ + (NSString *)interfaceOrientationForApplication:(FBApplication *)application return keys.anyObject; } -+ (BOOL)setDeviceRotation:(NSDictionary *)rotationObj forApplication:(FBApplication *)application ++ (BOOL)setDeviceRotation:(NSDictionary *)rotationObj forApplication:(XCUIApplication *)application { return [[XCUIDevice sharedDevice] fb_setDeviceRotation:rotationObj]; } -+ (BOOL)setDeviceOrientation:(NSString *)orientation forApplication:(FBApplication *)application ++ (BOOL)setDeviceOrientation:(NSString *)orientation forApplication:(XCUIApplication *)application { NSNumber *orientationValue = [[self _orientationsMapping] objectForKey:[orientation uppercaseString]]; if (orientationValue == nil) { diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 4a7ae1a8d..f5abdc55a 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -9,7 +9,6 @@ #import "FBSessionCommands.h" -#import "FBApplication.h" #import "FBCapabilities.h" #import "FBConfiguration.h" #import "FBLogger.h" @@ -17,7 +16,6 @@ #import "FBRouteRequest.h" #import "FBSession.h" #import "FBSettings.h" -#import "FBApplication.h" #import "FBRuntimeUtils.h" #import "FBActiveAppDetectionPoint.h" #import "FBXCodeCompatibility.h" @@ -138,15 +136,15 @@ + (NSArray *)routes } NSString *bundleID = capabilities[FB_CAP_BUNDLE_ID]; - FBApplication *app = nil; + XCUIApplication *app = nil; if (bundleID != nil) { - app = [[FBApplication alloc] initWithBundleIdentifier:bundleID]; + app = [[XCUIApplication alloc] initWithBundleIdentifier:bundleID]; BOOL forceAppLaunch = YES; if (nil != capabilities[FB_CAP_FORCE_APP_LAUNCH]) { forceAppLaunch = [capabilities[FB_CAP_FORCE_APP_LAUNCH] boolValue]; } - NSUInteger appState = [app fb_state]; - BOOL isAppRunning = appState >= 2; + XCUIApplicationState appState = app.state; + BOOL isAppRunning = appState >= XCUIApplicationStateRunningBackground; if (!isAppRunning || (isAppRunning && forceAppLaunch)) { app.fb_shouldWaitForQuiescence = nil == capabilities[FB_CAP_SHOULD_WAIT_FOR_QUIESCENCE] || [capabilities[FB_CAP_SHOULD_WAIT_FOR_QUIESCENCE] boolValue]; @@ -158,8 +156,8 @@ + (NSArray *)routes return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); } - } else if (appState < 4 && !forceAppLaunch) { - [app fb_activate]; + } else if (appState == XCUIApplicationStateRunningBackground && !forceAppLaunch) { + [app activate]; } } @@ -265,7 +263,7 @@ + (NSArray *)routes + (id)handleGetHealthCheck:(FBRouteRequest *)request { - if (![[XCUIDevice sharedDevice] fb_healthCheckWithApplication:[FBApplication fb_activeApplication]]) { + if (![[XCUIDevice sharedDevice] fb_healthCheckWithApplication:[XCUIApplication fb_activeApplication]]) { return FBResponseWithUnknownErrorFormat(@"Health check failed"); } return FBResponseWithOK(); diff --git a/WebDriverAgentLib/Commands/FBTouchActionCommands.m b/WebDriverAgentLib/Commands/FBTouchActionCommands.m index 64ef8eabe..3e31ddf2e 100644 --- a/WebDriverAgentLib/Commands/FBTouchActionCommands.m +++ b/WebDriverAgentLib/Commands/FBTouchActionCommands.m @@ -9,7 +9,6 @@ #import "FBTouchActionCommands.h" -#import "FBApplication.h" #import "FBRoute.h" #import "FBRouteRequest.h" #import "FBSession.h" diff --git a/WebDriverAgentLib/FBAlert.m b/WebDriverAgentLib/FBAlert.m index d692b04b2..0709e5f1f 100644 --- a/WebDriverAgentLib/FBAlert.m +++ b/WebDriverAgentLib/FBAlert.m @@ -9,12 +9,12 @@ #import "FBAlert.h" -#import "FBApplication.h" #import "FBConfiguration.h" #import "FBErrorBuilder.h" #import "FBLogger.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "FBXCodeCompatibility.h" +#import "XCUIApplication.h" #import "XCUIApplication+FBAlert.h" #import "XCUIElement+FBClassChain.h" #import "XCUIElement+FBTyping.h" @@ -263,8 +263,8 @@ - (XCUIElement *)alertElement if (nil == self.element) { self.element = self.application.fb_alertElement; if (nil == self.element) { - FBApplication *systemApp = FBApplication.fb_systemApplication; - for (FBApplication *activeApp in FBApplication.fb_activeApplications) { + XCUIApplication *systemApp = XCUIApplication.fb_systemApplication; + for (XCUIApplication *activeApp in XCUIApplication.fb_activeApplications) { if (systemApp.processID == activeApp.processID) { self.element = activeApp.fb_alertElement; break; diff --git a/WebDriverAgentLib/FBApplication.h b/WebDriverAgentLib/FBApplication.h deleted file mode 100644 index 00adb527d..000000000 --- a/WebDriverAgentLib/FBApplication.h +++ /dev/null @@ -1,49 +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 FBApplication : XCUIApplication - -/** - Constructor used to get current active application - */ -+ (instancetype)fb_activeApplication; - -/** - Constructor used to get current active application - - @param bundleId The bundle identifier of an app, which should be selected as active by default - if it is present in the list of active applications - */ -+ (instancetype)fb_activeApplicationWithDefaultBundleId:(nullable NSString *)bundleId; - -/** - Constructor used to get the system application (e.g. Springboard on iOS) - */ -+ (instancetype)fb_systemApplication; - -/** - Retrieves the list of all currently active applications - */ -+ (NSArray *)fb_activeApplications; - -/** - Switch to system app (called Springboard on iOS) - - @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_switchToSystemApplicationWithError:(NSError **)error; - -@end - -NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/FBApplication.m b/WebDriverAgentLib/FBApplication.m deleted file mode 100644 index fe46393fb..000000000 --- a/WebDriverAgentLib/FBApplication.m +++ /dev/null @@ -1,185 +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 "FBApplication.h" - -#import "FBXCAccessibilityElement.h" -#import "FBLogger.h" -#import "FBExceptions.h" -#import "FBRunLoopSpinner.h" -#import "FBMacros.h" -#import "FBActiveAppDetectionPoint.h" -#import "FBXCodeCompatibility.h" -#import "FBXCTestDaemonsProxy.h" -#import "XCUIApplication.h" -#import "XCUIApplication+FBHelpers.h" -#import "XCUIApplicationImpl.h" -#import "XCUIApplicationProcess.h" -#import "XCUIElement.h" -#import "XCUIElementQuery.h" -#import "FBXCAXClientProxy.h" - - -static const NSTimeInterval APP_STATE_CHANGE_TIMEOUT = 5.0; - -@interface FBApplication () -@end - -@implementation FBApplication - -+ (instancetype)fb_activeApplication -{ - return [self fb_activeApplicationWithDefaultBundleId:nil]; -} - -+ (NSArray *)fb_activeApplications -{ - NSArray> *activeApplicationElements = [FBXCAXClientProxy.sharedClient activeApplications]; - NSMutableArray *result = [NSMutableArray array]; - if (activeApplicationElements.count > 0) { - for (id applicationElement in activeApplicationElements) { - FBApplication *app = [FBApplication fb_applicationWithPID:applicationElement.processIdentifier]; - if (nil != app) { - [result addObject:app]; - } - } - } - return result.count > 0 ? result.copy : @[self.class.fb_systemApplication]; -} - -+ (instancetype)fb_activeApplicationWithDefaultBundleId:(nullable NSString *)bundleId -{ - NSArray> *activeApplicationElements = [FBXCAXClientProxy.sharedClient activeApplications]; - id activeApplicationElement = nil; - id currentElement = nil; - if (nil != bundleId) { - currentElement = FBActiveAppDetectionPoint.sharedInstance.axElement; - if (nil != currentElement) { - NSArray *appInfos = [self fb_appsInfoWithAxElements:@[currentElement]]; - [FBLogger logFmt:@"Detected on-screen application: %@", appInfos.firstObject[@"bundleId"]]; - if ([[appInfos.firstObject objectForKey:@"bundleId"] isEqualToString:(id)bundleId]) { - activeApplicationElement = currentElement; - } - } - } - if (nil == activeApplicationElement && activeApplicationElements.count > 1) { - if (nil != bundleId) { - NSArray *appInfos = [self fb_appsInfoWithAxElements:activeApplicationElements]; - NSMutableArray *bundleIds = [NSMutableArray array]; - for (NSDictionary *appInfo in appInfos) { - [bundleIds addObject:(NSString *)appInfo[@"bundleId"]]; - } - [FBLogger logFmt:@"Detected system active application(s): %@", bundleIds]; - // Try to select the desired application first - for (NSUInteger appIdx = 0; appIdx < appInfos.count; appIdx++) { - if ([[[appInfos objectAtIndex:appIdx] objectForKey:@"bundleId"] isEqualToString:(id)bundleId]) { - activeApplicationElement = [activeApplicationElements objectAtIndex:appIdx]; - break; - } - } - } - // Fall back to the "normal" algorithm if the desired application is either - // not set or is not active - if (nil == activeApplicationElement) { - if (nil == currentElement) { - currentElement = FBActiveAppDetectionPoint.sharedInstance.axElement; - } - if (nil == currentElement) { - [FBLogger log:@"Cannot precisely detect the current application. Will use the system's recently active one"]; - if (nil == bundleId) { - [FBLogger log:@"Consider changing the 'defaultActiveApplication' setting to the bundle identifier of the desired application under test"]; - } - } else { - for (id appElement in activeApplicationElements) { - if (appElement.processIdentifier == currentElement.processIdentifier) { - activeApplicationElement = appElement; - break; - } - } - } - } - } - - if (nil != activeApplicationElement) { - FBApplication *application = [FBApplication fb_applicationWithPID:activeApplicationElement.processIdentifier]; - if (nil != application) { - return application; - } - [FBLogger log:@"Cannot translate the active process identifier into an application object"]; - } - - if (activeApplicationElements.count > 0) { - [FBLogger logFmt:@"Getting the most recent active application (out of %@ total items)", @(activeApplicationElements.count)]; - for (id appElement in activeApplicationElements) { - FBApplication *application = [FBApplication fb_applicationWithPID:appElement.processIdentifier]; - if (nil != application) { - return application; - } - } - } - - [FBLogger log:@"Cannot retrieve any active applications. Assuming the system application is the active one"]; - return [self fb_systemApplication]; -} - -+ (instancetype)fb_systemApplication -{ - return [self fb_applicationWithPID: - [[FBXCAXClientProxy.sharedClient systemApplication] processIdentifier]]; -} - -+ (instancetype)applicationWithPID:(pid_t)processID -{ - if ([NSProcessInfo processInfo].processIdentifier == processID) { - return nil; - } - return (FBApplication *)[FBXCAXClientProxy.sharedClient monitoredApplicationWithProcessIdentifier:processID]; -} - -- (void)launch -{ - [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)terminate -{ - [super terminate]; - if (![self waitForState:XCUIApplicationStateNotRunning timeout:APP_STATE_CHANGE_TIMEOUT]) { - [FBLogger logFmt:@"The active application is still '%@' after %.2f seconds timeout", self.bundleID, APP_STATE_CHANGE_TIMEOUT]; - } -} - -+ (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error -{ - FBApplication *systemApp = self.fb_systemApplication; - @try { - if ([systemApp fb_state] < 2) { - [systemApp launch]; - } else { - [systemApp fb_activate]; - } - } @catch (NSException *e) { - return [[[FBErrorBuilder alloc] - withDescription:nil == e ? @"Cannot open the home screen" : e.reason] - buildError:error]; - } - return [[[[FBRunLoopSpinner new] - timeout:5] - timeoutErrorMessage:@"Timeout waiting until the home screen is visible"] - spinUntilTrue:^BOOL{ - FBApplication *activeApp = self.fb_activeApplication; - return nil != activeApp && [activeApp.bundleID isEqualToString:systemApp.bundleID]; - } - error:error]; -} - -@end diff --git a/WebDriverAgentLib/Routing/FBSession.h b/WebDriverAgentLib/Routing/FBSession.h index be7f2bbba..9b73d4d16 100644 --- a/WebDriverAgentLib/Routing/FBSession.h +++ b/WebDriverAgentLib/Routing/FBSession.h @@ -9,8 +9,8 @@ #import -@class FBApplication; @class FBElementCache; +@class XCUIApplication; NS_ASSUME_NONNULL_BEGIN @@ -20,16 +20,16 @@ NS_ASSUME_NONNULL_BEGIN @interface FBSession : NSObject /*! Application tested during that session */ -@property (nonatomic, strong, readonly) FBApplication *activeApplication; +@property (nonatomic, readonly) XCUIApplication *activeApplication; /*! Session's identifier */ -@property (nonatomic, copy, readonly) NSString *identifier; +@property (nonatomic, readonly) NSString *identifier; /*! Element cache related to that session */ -@property (nonatomic, strong, readonly) FBElementCache *elementCache; +@property (nonatomic, readonly) FBElementCache *elementCache; /*! The identifier of the active application */ -@property (nonatomic, copy) NSString *defaultActiveApplication; +@property (nonatomic) NSString *defaultActiveApplication; /*! The action to apply to unexpected alerts. Either "accept"/"dismiss" or nil/empty string (by default) to do nothing */ @property (nonatomic, nullable) NSString *defaultAlertAction; @@ -57,7 +57,7 @@ NS_ASSUME_NONNULL_BEGIN @param application The application that we want to create session for @return new session */ -+ (instancetype)initWithApplication:(nullable FBApplication *)application; ++ (instancetype)initWithApplication:(nullable XCUIApplication *)application; /** Creates and saves new session for application with default alert handling behaviour @@ -66,7 +66,8 @@ NS_ASSUME_NONNULL_BEGIN @param defaultAlertAction The default reaction to on-screen alert. Either 'accept' or 'dismiss' @return new session */ -+ (instancetype)initWithApplication:(nullable FBApplication *)application defaultAlertAction:(NSString *)defaultAlertAction; ++ (instancetype)initWithApplication:(nullable XCUIApplication *)application + defaultAlertAction:(NSString *)defaultAlertAction; /** Kills application associated with that session and removes session @@ -82,12 +83,11 @@ NS_ASSUME_NONNULL_BEGIN @param arguments The optional array of application command line arguments. The arguments are going to be applied if the application was not running before. @param environment The optional dictionary of environment variables for the application, which is going to be executed. The environment variables are going to be applied if the application was not running before. @return The application instance - @throws FBApplicationMethodNotSupportedException if the method is not supported with the current XCTest SDK */ -- (FBApplication *)launchApplicationWithBundleId:(NSString *)bundleIdentifier - shouldWaitForQuiescence:(nullable NSNumber *)shouldWaitForQuiescence - arguments:(nullable NSArray *)arguments - environment:(nullable NSDictionary *)environment; +- (XCUIApplication *)launchApplicationWithBundleId:(NSString *)bundleIdentifier + shouldWaitForQuiescence:(nullable NSNumber *)shouldWaitForQuiescence + arguments:(nullable NSArray *)arguments + environment:(nullable NSDictionary *)environment; /** Activate an application with given bundle identifier in scope of current session. @@ -95,9 +95,8 @@ NS_ASSUME_NONNULL_BEGIN @param bundleIdentifier Valid bundle identifier of the application to be activated @return The application instance - @throws FBApplicationMethodNotSupportedException if the method is not supported with the current XCTest SDK */ -- (FBApplication *)activateApplicationWithBundleId:(NSString *)bundleIdentifier; +- (XCUIApplication *)activateApplicationWithBundleId:(NSString *)bundleIdentifier; /** Terminate an application with the given bundle id. The application should be previously diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index 69d0fff78..888cff8b2 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -14,7 +14,6 @@ #import "FBXCAccessibilityElement.h" #import "FBAlertsMonitor.h" -#import "FBApplication.h" #import "FBConfiguration.h" #import "FBElementCache.h" #import "FBExceptions.h" @@ -31,7 +30,7 @@ NSString *const FBDefaultApplicationAuto = @"auto"; @interface FBSession () -@property (nonatomic) NSString *testedApplicationBundleId; +@property (nullable, nonatomic) XCUIApplication *testedApplication; @property (nonatomic) BOOL isTestedApplicationExpectedToRun; @property (nonatomic) BOOL shouldAppsWaitForQuiescence; @property (nonatomic, nullable) FBAlertsMonitor *alertsMonitor; @@ -96,7 +95,7 @@ + (instancetype)sessionWithIdentifier:(NSString *)identifier return _activeSession; } -+ (instancetype)initWithApplication:(FBApplication *)application ++ (instancetype)initWithApplication:(XCUIApplication *)application { FBSession *session = [FBSession new]; session.useNativeCachingStrategy = YES; @@ -105,10 +104,10 @@ + (instancetype)initWithApplication:(FBApplication *)application session.elementsVisibilityCache = [NSMutableDictionary dictionary]; session.identifier = [[NSUUID UUID] UUIDString]; session.defaultActiveApplication = FBDefaultApplicationAuto; - session.testedApplicationBundleId = nil; + session.testedApplication = nil; session.isTestedApplicationExpectedToRun = nil != application && application.running; if (application) { - session.testedApplicationBundleId = application.bundleID; + session.testedApplication = application; session.shouldAppsWaitForQuiescence = application.fb_shouldWaitForQuiescence; } session.elementCache = [FBElementCache new]; @@ -116,7 +115,7 @@ + (instancetype)initWithApplication:(FBApplication *)application return session; } -+ (instancetype)initWithApplication:(nullable FBApplication *)application ++ (instancetype)initWithApplication:(nullable XCUIApplication *)application defaultAlertAction:(NSString *)defaultAlertAction { FBSession *session = [self.class initWithApplication:application]; @@ -138,81 +137,78 @@ - (void)kill self.alertsMonitor = nil; } - if (self.testedApplicationBundleId && [FBConfiguration shouldTerminateApp] - && ![self.testedApplicationBundleId isEqualToString:FBApplication.fb_systemApplication.bundleID]) { - FBApplication *app = [[FBApplication alloc] initWithBundleIdentifier:self.testedApplicationBundleId]; - if ([app running]) { - @try { - [app terminate]; - } @catch (NSException *e) { - [FBLogger logFmt:@"%@", e.description]; - } + if (nil != self.testedApplication + && FBConfiguration.shouldTerminateApp + && self.testedApplication.running + && ![self.testedApplication fb_isSameAppAs:XCUIApplication.fb_systemApplication]) { + @try { + [self.testedApplication terminate]; + } @catch (NSException *e) { + [FBLogger logFmt:@"%@", e.description]; } } _activeSession = nil; } -- (FBApplication *)activeApplication +- (XCUIApplication *)activeApplication { + if (nil != self.testedApplication) { + XCUIApplicationState testedAppState = self.testedApplication.state; + if (testedAppState >= XCUIApplicationStateRunningForeground) { + return (XCUIApplication *)self.testedApplication; + } + if (self.isTestedApplicationExpectedToRun && testedAppState <= XCUIApplicationStateNotRunning) { + NSString *description = [NSString stringWithFormat:@"The application under test with bundle id '%@' is not running, possibly crashed", self.testedApplication.bundleID]; + @throw [NSException exceptionWithName:FBApplicationCrashedException reason:description userInfo:nil]; + } + } + NSString *defaultBundleId = [self.defaultActiveApplication isEqualToString:FBDefaultApplicationAuto] ? nil : self.defaultActiveApplication; - FBApplication *application = [FBApplication fb_activeApplicationWithDefaultBundleId:defaultBundleId]; - FBApplication *testedApplication = nil; - if (self.testedApplicationBundleId && self.isTestedApplicationExpectedToRun) { - testedApplication = nil != application.bundleID && [application.bundleID isEqualToString:self.testedApplicationBundleId] - ? application - : [[FBApplication alloc] initWithBundleIdentifier:self.testedApplicationBundleId]; - } - if (testedApplication && !testedApplication.running) { - NSString *description = [NSString stringWithFormat:@"The application under test with bundle id '%@' is not running, possibly crashed", self.testedApplicationBundleId]; - [[NSException exceptionWithName:FBApplicationCrashedException reason:description userInfo:nil] raise]; - } - return application; + return [XCUIApplication fb_activeApplicationWithDefaultBundleId:defaultBundleId]; } -- (FBApplication *)launchApplicationWithBundleId:(NSString *)bundleIdentifier - shouldWaitForQuiescence:(nullable NSNumber *)shouldWaitForQuiescence - arguments:(nullable NSArray *)arguments - environment:(nullable NSDictionary *)environment +- (XCUIApplication *)launchApplicationWithBundleId:(NSString *)bundleIdentifier + shouldWaitForQuiescence:(nullable NSNumber *)shouldWaitForQuiescence + arguments:(nullable NSArray *)arguments + environment:(nullable NSDictionary *)environment { - FBApplication *app = [[FBApplication alloc] initWithBundleIdentifier:bundleIdentifier]; + XCUIApplication *app = [self makeApplicationWithBundleId: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; + app.fb_shouldWaitForQuiescence = nil != self.testedApplication && self.shouldAppsWaitForQuiescence; } else { app.fb_shouldWaitForQuiescence = [shouldWaitForQuiescence boolValue]; } - if (app.fb_state < 2) { + if (!app.running) { app.launchArguments = arguments ?: @[]; app.launchEnvironment = environment ?: @{}; [app launch]; } else { - [app fb_activate]; + [app activate]; } - if (nil != self.testedApplicationBundleId - && [bundleIdentifier isEqualToString:(NSString *)self.testedApplicationBundleId]) { + if ([app fb_isSameAppAs:self.testedApplication]) { self.isTestedApplicationExpectedToRun = YES; } return app; } -- (FBApplication *)activateApplicationWithBundleId:(NSString *)bundleIdentifier +- (XCUIApplication *)activateApplicationWithBundleId:(NSString *)bundleIdentifier { - FBApplication *app = [[FBApplication alloc] initWithBundleIdentifier:bundleIdentifier]; - [app fb_activate]; + XCUIApplication *app = [self makeApplicationWithBundleId:bundleIdentifier]; + [app activate]; return app; } - (BOOL)terminateApplicationWithBundleId:(NSString *)bundleIdentifier { - FBApplication *app = [[FBApplication alloc] initWithBundleIdentifier:bundleIdentifier]; - if (nil != self.testedApplicationBundleId - && [bundleIdentifier isEqualToString:(NSString *)self.testedApplicationBundleId]) { + XCUIApplication *app = [self makeApplicationWithBundleId:bundleIdentifier]; + if ([app fb_isSameAppAs:self.testedApplication]) { self.isTestedApplicationExpectedToRun = NO; } - if (app.fb_state >= 2) { + if (app.running) { [app terminate]; return YES; } @@ -221,7 +217,14 @@ - (BOOL)terminateApplicationWithBundleId:(NSString *)bundleIdentifier - (NSUInteger)applicationStateWithBundleId:(NSString *)bundleIdentifier { - return [[FBApplication alloc] initWithBundleIdentifier:bundleIdentifier].fb_state; + return [self makeApplicationWithBundleId:bundleIdentifier].state; +} + +- (XCUIApplication *)makeApplicationWithBundleId:(NSString *)bundleIdentifier +{ + return nil != self.testedApplication && [bundleIdentifier isEqualToString:(NSString *)self.testedApplication.bundleID] + ? self.testedApplication + : [[XCUIApplication alloc] initWithBundleIdentifier:bundleIdentifier]; } @end diff --git a/WebDriverAgentLib/Utilities/FBAlertsMonitor.m b/WebDriverAgentLib/Utilities/FBAlertsMonitor.m index c2c625084..1a1b6f34c 100644 --- a/WebDriverAgentLib/Utilities/FBAlertsMonitor.m +++ b/WebDriverAgentLib/Utilities/FBAlertsMonitor.m @@ -10,9 +10,9 @@ #import "FBAlertsMonitor.h" #import "FBAlert.h" -#import "FBApplication.h" #import "FBLogger.h" #import "XCUIApplication+FBAlert.h" +#import "XCUIApplication+FBHelpers.h" static const NSTimeInterval FB_MONTORING_INTERVAL = 2.0; @@ -49,8 +49,8 @@ - (void)scheduleNextTick } dispatch_async(dispatch_get_main_queue(), ^{ - NSArray *activeApps = FBApplication.fb_activeApplications; - for (FBApplication *activeApp in activeApps) { + NSArray *activeApps = XCUIApplication.fb_activeApplications; + for (XCUIApplication *activeApp in activeApps) { XCUIElement *alertElement = nil; @try { alertElement = activeApp.fb_alertElement; diff --git a/WebDriverAgentLib/Utilities/FBKeyboard.m b/WebDriverAgentLib/Utilities/FBKeyboard.m index e1f5fdc5b..d90a68e29 100644 --- a/WebDriverAgentLib/Utilities/FBKeyboard.m +++ b/WebDriverAgentLib/Utilities/FBKeyboard.m @@ -9,8 +9,6 @@ #import "FBKeyboard.h" - -#import "FBApplication.h" #import "FBConfiguration.h" #import "FBXCTestDaemonsProxy.h" #import "FBErrorBuilder.h" @@ -25,10 +23,13 @@ @implementation FBKeyboard -+ (BOOL)waitUntilVisibleForApplication:(XCUIApplication *)app timeout:(NSTimeInterval)timeout error:(NSError **)error ++ (BOOL)waitUntilVisibleForApplication:(XCUIApplication *)app + timeout:(NSTimeInterval)timeout + error:(NSError **)error { BOOL (^isKeyboardVisible)(void) = ^BOOL(void) { - if (!app.keyboard.exists) { + XCUIElement *keyboard = app.keyboards.fb_firstMatch; + if (nil == keyboard) { return NO; } @@ -36,7 +37,7 @@ + (BOOL)waitUntilVisibleForApplication:(XCUIApplication *)app timeout:(NSTimeInt NSDictionary *bindings) { return snapshot.label.length > 0; }]; - XCUIElement *firstKey = [[app.keyboard descendantsMatchingType:XCUIElementTypeKey] + XCUIElement *firstKey = [[keyboard descendantsMatchingType:XCUIElementTypeKey] matchingPredicate:keySearchPredicate].allElementsBoundByIndex.firstObject; return firstKey.exists && firstKey.hittable; }; diff --git a/WebDriverAgentLib/Utilities/FBMjpegServer.m b/WebDriverAgentLib/Utilities/FBMjpegServer.m index 14a734c94..691e57746 100644 --- a/WebDriverAgentLib/Utilities/FBMjpegServer.m +++ b/WebDriverAgentLib/Utilities/FBMjpegServer.m @@ -13,7 +13,6 @@ @import UniformTypeIdentifiers; #import "GCDAsyncSocket.h" -#import "FBApplication.h" #import "FBConfiguration.h" #import "FBLogger.h" #import "FBScreenshot.h" diff --git a/WebDriverAgentLib/Utilities/FBPasteboard.m b/WebDriverAgentLib/Utilities/FBPasteboard.m index 6340efff3..0171b259c 100644 --- a/WebDriverAgentLib/Utilities/FBPasteboard.m +++ b/WebDriverAgentLib/Utilities/FBPasteboard.m @@ -11,9 +11,9 @@ #import #import "FBAlert.h" -#import "FBApplication.h" #import "FBErrorBuilder.h" #import "FBMacros.h" +#import "XCUIApplication+FBHelpers.h" #import "XCUIApplication+FBAlert.h" #define ALERT_TIMEOUT_SEC 30 @@ -101,7 +101,7 @@ + (nullable id)pasteboardContentForItem:(NSString *)item break; } - XCUIElement *alertElement = FBApplication.fb_systemApplication.fb_alertElement; + XCUIElement *alertElement = XCUIApplication.fb_systemApplication.fb_alertElement; if (nil != alertElement) { FBAlert *alert = [FBAlert alertWithElement:alertElement]; [alert acceptWithError:nil]; diff --git a/WebDriverAgentLib/Utilities/FBScreen.m b/WebDriverAgentLib/Utilities/FBScreen.m index e2b25855b..8ebe080d5 100644 --- a/WebDriverAgentLib/Utilities/FBScreen.m +++ b/WebDriverAgentLib/Utilities/FBScreen.m @@ -8,7 +8,6 @@ */ #import "FBScreen.h" -#import "FBApplication.h" #import "XCUIElement+FBIsVisible.h" #import "FBXCodeCompatibility.h" #import "XCUIScreen.h" @@ -22,7 +21,7 @@ + (double)scale + (CGSize)statusBarSizeForApplication:(XCUIApplication *)application { - XCUIApplication *app = FBApplication.fb_systemApplication; + XCUIApplication *app = XCUIApplication.fb_systemApplication; // Since iOS 13 the status bar is no longer part of the application, it’s part of the SpringBoard XCUIElement *mainStatusBar = app.statusBars.allElementsBoundByIndex.firstObject; if (nil == mainStatusBar) { diff --git a/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m b/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m index 7476f09bb..11becfa72 100644 --- a/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +++ b/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m @@ -10,7 +10,6 @@ #import "FBTVNavigationTracker.h" #import "FBTVNavigationTracker-Private.h" -#import "FBApplication.h" #import "FBMathUtils.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBUtilities.h" @@ -69,7 +68,7 @@ - (instancetype)initWithTargetElement:(XCUIElement *)targetElement - (FBTVDirection)directionToFocusedElement { - XCUIElement *focused = FBApplication.fb_activeApplication.fb_focusedElement; + XCUIElement *focused = XCUIApplication.fb_activeApplication.fb_focusedElement; CGPoint focusedCenter = FBRectGetCenter(focused.wdFrame); FBTVNavigationItem *item = [self navigationItemWithElement:focused]; diff --git a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h index 3922a876d..0a7dd9a0c 100644 --- a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +++ b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h @@ -28,39 +28,6 @@ NSInteger FBTestmanagerdVersion(void); NS_ASSUME_NONNULL_BEGIN -/** - The exception happends if one tries to call application method, - which is not supported in the current iOS version - */ -extern NSString *const FBApplicationMethodNotSupportedException; - -@interface XCUIApplication (FBCompatibility) - -+ (nullable instancetype)fb_applicationWithPID:(pid_t)processID; - -/** - Get the state of the application. This method only returns reliable results on Xcode SDK 9+ - - @return State value as enum item. See https://developer.apple.com/documentation/xctest/xcuiapplicationstate?language=objc for more details. - */ -- (NSUInteger)fb_state; - -/** - Activate the application by restoring it from the background. - Nothing will happen if the application is already in foreground. - This method is only supported since Xcode9. - - @throws FBTimeoutException if the app is still not active after the timeout - */ -- (void)fb_activate; - -/** - Terminate the application and wait until it disappears from the list of active apps - */ -- (void)fb_terminate; - -@end - @interface XCUIElementQuery (FBCompatibility) /* Performs short-circuit UI tree traversion in iOS 11+ to get the first element matched by the query. Equals to nil if no matching elements are found */ diff --git a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m index 4d7bb621d..b13a79e55 100644 --- a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +++ b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m @@ -9,6 +9,7 @@ #import "FBXCodeCompatibility.h" +#import "FBXCAXClientProxy.h" #import "FBConfiguration.h" #import "FBErrorBuilder.h" #import "FBLogger.h" @@ -17,45 +18,6 @@ #import "FBXCTestDaemonsProxy.h" #import "XCTestManager_ManagerInterface-Protocol.h" -static const NSTimeInterval APP_STATE_CHANGE_TIMEOUT = 5.0; - -NSString *const FBApplicationMethodNotSupportedException = @"FBApplicationMethodNotSupportedException"; - -@implementation XCUIApplication (FBCompatibility) - -+ (instancetype)fb_applicationWithPID:(pid_t)processID -{ - if (0 == processID) { - return nil; - } - - return [self applicationWithPID:processID]; -} - -- (void)fb_activate -{ - [self activate]; - if (![self waitForState:XCUIApplicationStateRunningForeground timeout:APP_STATE_CHANGE_TIMEOUT / 2] || ![self fb_waitForAppElement:APP_STATE_CHANGE_TIMEOUT / 2]) { - [FBLogger logFmt:@"The application '%@' is not running in foreground after %.2f seconds", self.bundleID, APP_STATE_CHANGE_TIMEOUT]; - } -} - -- (void)fb_terminate -{ - [self terminate]; - if (![self waitForState:XCUIApplicationStateNotRunning timeout:APP_STATE_CHANGE_TIMEOUT]) { - [FBLogger logFmt:@"The active application is still '%@' after %.2f seconds timeout", self.bundleID, APP_STATE_CHANGE_TIMEOUT]; - } -} - -- (NSUInteger)fb_state -{ - return [[self valueForKey:@"state"] intValue]; -} - -@end - - @implementation XCUIElementQuery (FBCompatibility) - (XCElementSnapshot *)fb_uniqueSnapshotWithError:(NSError **)error @@ -89,7 +51,7 @@ + (BOOL)fb_supportsNonModalElementsInclusion static dispatch_once_t hasIncludingNonModalElements; static BOOL result; dispatch_once(&hasIncludingNonModalElements, ^{ - result = [FBApplication.fb_systemApplication.query respondsToSelector:@selector(includingNonModalElements)]; + result = [XCUIApplication.fb_systemApplication.query respondsToSelector:@selector(includingNonModalElements)]; }); return result; } diff --git a/WebDriverAgentLib/WebDriverAgentLib.h b/WebDriverAgentLib/WebDriverAgentLib.h index 6d9daa1f6..f14994b86 100644 --- a/WebDriverAgentLib/WebDriverAgentLib.h +++ b/WebDriverAgentLib/WebDriverAgentLib.h @@ -16,7 +16,6 @@ FOUNDATION_EXPORT double WebDriverAgentLib_VersionNumber; FOUNDATION_EXPORT const unsigned char WebDriverAgentLib_VersionString[]; #import -#import #import #import #import diff --git a/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m b/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m index 25dc39d21..c7f0b59af 100644 --- a/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBAutoAlertsHandlerTests.m @@ -10,7 +10,6 @@ #import #import "FBIntegrationTestCase.h" -#import "FBApplication.h" #import "FBMacros.h" #import "FBSession.h" #import "FBXCodeCompatibility.h" @@ -50,7 +49,7 @@ - (void)tearDown - (void)disabled_testAutoAcceptingOfAlerts { self.session = [FBSession - initWithApplication:FBApplication.fb_activeApplication + initWithApplication:XCUIApplication.fb_activeApplication defaultAlertAction:@"accept"]; for (int i = 0; i < 2; i++) { [self.testedApplication.buttons[FBShowAlertButtonName] tap]; @@ -63,7 +62,7 @@ - (void)disabled_testAutoAcceptingOfAlerts - (void)disabled_testAutoDismissingOfAlerts { self.session = [FBSession - initWithApplication:FBApplication.fb_activeApplication + initWithApplication:XCUIApplication.fb_activeApplication defaultAlertAction:@"dismiss"]; for (int i = 0; i < 2; i++) { [self.testedApplication.buttons[FBShowAlertButtonName] tap]; diff --git a/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m b/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m index ea4fa2cee..d791e8ab5 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m @@ -9,7 +9,6 @@ #import -#import "FBApplication.h" #import "FBIntegrationTestCase.h" #import "FBMacros.h" #import "FBTestMacros.h" diff --git a/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.h b/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.h index 1d6ee85f4..a920e167c 100644 --- a/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.h +++ b/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.h @@ -9,8 +9,6 @@ #import -#import "FBApplication.h" - extern NSString *const FBShowAlertButtonName; extern NSString *const FBShowSheetAlertButtonName; extern NSString *const FBShowAlertForceTouchButtonName; @@ -22,7 +20,7 @@ extern NSString *const FBTapsCountLabelIdentifier; */ @interface FBIntegrationTestCase : XCTestCase @property (nonatomic, strong, readonly) XCUIApplication *testedApplication; -@property (nonatomic, strong, readonly) FBApplication *springboard; +@property (nonatomic, strong, readonly) XCUIApplication *springboard; /** Launches application and resets side effects of testing like orientation etc. diff --git a/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m b/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m index bfcb36648..4750b79a4 100644 --- a/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m +++ b/WebDriverAgentTests/IntegrationTests/FBIntegrationTestCase.m @@ -10,12 +10,12 @@ #import #import "FBAlert.h" -#import "FBApplication.h" #import "FBTestMacros.h" #import "FBIntegrationTestCase.h" #import "FBConfiguration.h" #import "FBMacros.h" #import "FBRunLoopSpinner.h" +#import "XCUIApplication+FBHelpers.h" #import "XCUIDevice+FBRotation.h" #import "XCUIElement.h" #import "XCUIElement+FBIsVisible.h" @@ -30,7 +30,7 @@ @interface FBIntegrationTestCase () @property (nonatomic, strong) XCUIApplication *testedApplication; -@property (nonatomic, strong) FBApplication *springboard; +@property (nonatomic, strong) XCUIApplication *springboard; @end @implementation FBIntegrationTestCase @@ -46,7 +46,7 @@ - (void)setUp [FBConfiguration disableApplicationUIInterruptionsHandling]; [FBConfiguration disableScreenshots]; self.continueAfterFailure = NO; - self.springboard = FBApplication.fb_systemApplication; + self.springboard = XCUIApplication.fb_systemApplication; self.testedApplication = [XCUIApplication new]; } @@ -91,10 +91,10 @@ - (void)goToSpringBoardFirstPage { [[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome]; [self.testedApplication fb_waitUntilStable]; - FBAssertWaitTillBecomesTrue(FBApplication.fb_systemApplication.icons[@"Safari"].exists); + FBAssertWaitTillBecomesTrue(XCUIApplication.fb_systemApplication.icons[@"Safari"].exists); [[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome]; [self.testedApplication fb_waitUntilStable]; - FBAssertWaitTillBecomesTrue(FBApplication.fb_systemApplication.icons[@"Calendar"].firstMatch.fb_isVisible); + FBAssertWaitTillBecomesTrue(XCUIApplication.fb_systemApplication.icons[@"Calendar"].firstMatch.fb_isVisible); } - (void)goToSpringBoardExtras diff --git a/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m b/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m index 336ad1902..73e2de337 100644 --- a/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m @@ -10,7 +10,6 @@ #import #import "FBIntegrationTestCase.h" -#import "FBApplication.h" #import "FBTestMacros.h" #import "FBMacros.h" #import "FBSession.h" @@ -33,7 +32,7 @@ @implementation FBSafariAlertIntegrationTests - (void)setUp { [super setUp]; - self.session = [FBSession initWithApplication:FBApplication.fb_activeApplication]; + self.session = [FBSession initWithApplication:XCUIApplication.fb_activeApplication]; [self.session launchApplicationWithBundleId:SAFARI_BUNDLE_ID shouldWaitForQuiescence:nil arguments:nil diff --git a/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m index ea9fb4cfe..2df038fda 100644 --- a/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m @@ -10,13 +10,14 @@ #import #import "FBIntegrationTestCase.h" -#import "FBApplication.h" #import "FBExceptions.h" #import "FBMacros.h" #import "FBSession.h" #import "FBXCodeCompatibility.h" #import "FBTestMacros.h" #import "FBUnattachedAppLauncher.h" +#import "XCUIApplication+FBHelpers.h" +#import "XCUIApplication.h" @interface FBSession (Tests) @@ -35,7 +36,7 @@ - (void)setUp { [super setUp]; [self launchApplication]; - FBApplication *app = [[FBApplication alloc] initWithBundleIdentifier:self.testedApplication.bundleID]; + XCUIApplication *app = [[XCUIApplication alloc] initWithBundleIdentifier:self.testedApplication.bundleID]; self.session = [FBSession initWithApplication:app]; } @@ -47,7 +48,7 @@ - (void)tearDown - (void)testSettingsAppCanBeOpenedInScopeOfTheCurrentSession { - FBApplication *testedApp = FBApplication.fb_activeApplication; + XCUIApplication *testedApp = XCUIApplication.fb_activeApplication; [self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID shouldWaitForQuiescence:nil arguments:nil @@ -61,7 +62,7 @@ - (void)testSettingsAppCanBeOpenedInScopeOfTheCurrentSession - (void)testSettingsAppCanBeReopenedInScopeOfTheCurrentSession { - FBApplication *systemApp = self.springboard; + XCUIApplication *systemApp = self.springboard; [self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID shouldWaitForQuiescence:nil arguments:nil @@ -78,7 +79,7 @@ - (void)testSettingsAppCanBeReopenedInScopeOfTheCurrentSession - (void)testMainAppCanBeReactivatedInScopeOfTheCurrentSession { - FBApplication *testedApp = FBApplication.fb_activeApplication; + XCUIApplication *testedApp = XCUIApplication.fb_activeApplication; [self.session launchApplicationWithBundleId:SETTINGS_BUNDLE_ID shouldWaitForQuiescence:nil arguments:nil @@ -90,8 +91,8 @@ - (void)testMainAppCanBeReactivatedInScopeOfTheCurrentSession - (void)testMainAppCanBeRestartedInScopeOfTheCurrentSession { - FBApplication *systemApp = self.springboard; - FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:self.testedApplication.bundleID]; + XCUIApplication *systemApp = self.springboard; + XCUIApplication *testedApp = [[XCUIApplication alloc] initWithBundleIdentifier:self.testedApplication.bundleID]; [self.session terminateApplicationWithBundleId:testedApp.bundleID]; FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:systemApp.bundleID]); [self.session launchApplicationWithBundleId:testedApp.bundleID @@ -105,12 +106,12 @@ - (void)testLaunchUnattachedApp { [FBUnattachedAppLauncher launchAppWithBundleId:SETTINGS_BUNDLE_ID]; [self.session kill]; - XCTAssertEqualObjects(SETTINGS_BUNDLE_ID, FBApplication.fb_activeApplication.bundleID); + XCTAssertEqualObjects(SETTINGS_BUNDLE_ID, XCUIApplication.fb_activeApplication.bundleID); } - (void)testAppWithInvalidBundleIDCannotBeStarted { - FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; + XCUIApplication *testedApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"yolo"]; @try { [testedApp launch]; XCTFail(@"An exception is expected to be thrown"); @@ -121,7 +122,7 @@ - (void)testAppWithInvalidBundleIDCannotBeStarted - (void)testAppWithInvalidBundleIDCannotBeActivated { - FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"]; + XCUIApplication *testedApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"yolo"]; @try { [testedApp activate]; XCTFail(@"An exception is expected to be thrown"); diff --git a/WebDriverAgentTests/IntegrationTests/FBTapTest.m b/WebDriverAgentTests/IntegrationTests/FBTapTest.m index 5b79711fc..61014d842 100644 --- a/WebDriverAgentTests/IntegrationTests/FBTapTest.m +++ b/WebDriverAgentTests/IntegrationTests/FBTapTest.m @@ -11,7 +11,6 @@ #import "FBIntegrationTestCase.h" -#import "FBApplication.h" #import "FBElementCache.h" #import "FBTestMacros.h" #import "XCUIDevice+FBRotation.h" diff --git a/WebDriverAgentTests/IntegrationTests/FBW3CMultiTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBW3CMultiTouchActionsIntegrationTests.m index f25bee825..dfbbf2039 100644 --- a/WebDriverAgentTests/IntegrationTests/FBW3CMultiTouchActionsIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBW3CMultiTouchActionsIntegrationTests.m @@ -11,7 +11,6 @@ #import "FBIntegrationTestCase.h" -#import "FBApplication.h" #import "XCUIElement.h" #import "XCUIApplication+FBTouchAction.h" #import "FBTestMacros.h" diff --git a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m index 41ee134a1..e86f62021 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m @@ -11,11 +11,11 @@ #import -#import "FBApplication.h" #import "FBIntegrationTestCase.h" #import "FBElement.h" #import "FBMacros.h" #import "FBTestMacros.h" +#import "XCUIApplication.h" #import "XCUIApplication+FBHelpers.h" #import "XCUIElement+FBIsVisible.h" #import "FBXCodeCompatibility.h" @@ -34,8 +34,8 @@ - (void)setUp - (void)testQueringSpringboard { [self goToSpringBoardFirstPage]; - XCTAssertTrue(FBApplication.fb_systemApplication.icons[@"Safari"].exists); - XCTAssertTrue(FBApplication.fb_systemApplication.icons[@"Calendar"].firstMatch.exists); + XCTAssertTrue(XCUIApplication.fb_systemApplication.icons[@"Safari"].exists); + XCTAssertTrue(XCUIApplication.fb_systemApplication.icons[@"Calendar"].firstMatch.exists); } - (void)testApplicationTree @@ -58,10 +58,10 @@ - (void)testDeactivateApplication - (void)testActiveApplication { - FBApplication *systemApp = FBApplication.fb_systemApplication; - XCTAssertTrue([FBApplication fb_activeApplication].buttons[@"Alerts"].fb_isVisible); + XCUIApplication *systemApp = XCUIApplication.fb_systemApplication; + XCTAssertTrue([XCUIApplication fb_activeApplication].buttons[@"Alerts"].fb_isVisible); [self goToSpringBoardFirstPage]; - XCTAssertEqualObjects([FBApplication fb_activeApplication].bundleID, systemApp.bundleID); + XCTAssertEqualObjects([XCUIApplication fb_activeApplication].bundleID, systemApp.bundleID); XCTAssertTrue(systemApp.icons[@"Safari"].fb_isVisible); } @@ -102,14 +102,14 @@ - (void)testAccessbilityAudit } NSError *error; - NSArray *auditIssues1 = [FBApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypes:~0UL + NSArray *auditIssues1 = [XCUIApplication.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 + NSArray *auditIssues2 = [XCUIApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypesSet:set.copy error:&error]; XCTAssertEqualObjects(auditIssues1, auditIssues2); XCTAssertNil(error); diff --git a/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m b/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m index ca79b2fa4..548bd70a5 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m @@ -9,11 +9,12 @@ #import -#import "FBApplication.h" #import "FBIntegrationTestCase.h" #import "FBImageUtils.h" #import "FBMacros.h" #import "FBTestMacros.h" +#import "XCUIApplication.h" +#import "XCUIApplication+FBHelpers.h" #import "XCUIDevice+FBHelpers.h" #import "XCUIDevice+FBRotation.h" #import "XCUIScreen.h" @@ -101,7 +102,7 @@ - (void)testGoToHomeScreen NSError *error; XCTAssertTrue([[XCUIDevice sharedDevice] fb_goToHomescreenWithError:&error]); XCTAssertNil(error); - XCTAssertTrue([FBApplication fb_activeApplication].icons[@"Safari"].exists); + XCTAssertTrue([XCUIApplication fb_activeApplication].icons[@"Safari"].exists); } - (void)testLockUnlockScreen @@ -124,7 +125,7 @@ - (void)testUrlSchemeActivation NSError *error; XCTAssertTrue([XCUIDevice.sharedDevice fb_openUrl:@"https://apple.com" error:&error]); - FBAssertWaitTillBecomesTrue([FBApplication.fb_activeApplication.bundleID isEqualToString:@"com.apple.mobilesafari"]); + FBAssertWaitTillBecomesTrue([XCUIApplication.fb_activeApplication.bundleID isEqualToString:@"com.apple.mobilesafari"]); XCTAssertNil(error); } @@ -138,7 +139,7 @@ - (void)testUrlSchemeActivationWithApp XCTAssertTrue([XCUIDevice.sharedDevice fb_openUrl:@"https://apple.com" withApplication:@"com.apple.mobilesafari" error:&error]); - FBAssertWaitTillBecomesTrue([FBApplication.fb_activeApplication.bundleID isEqualToString:@"com.apple.mobilesafari"]); + FBAssertWaitTillBecomesTrue([XCUIApplication.fb_activeApplication.bundleID isEqualToString:@"com.apple.mobilesafari"]); XCTAssertNil(error); } diff --git a/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m index f2d6d3a60..496bd353d 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m @@ -10,7 +10,6 @@ #import #import "XCTest/XCUIElementTypes.h" -#import "FBApplication.h" #import "FBIntegrationTestCase.h" #import "FBTestMacros.h" #import "FBElement.h" diff --git a/WebDriverAgentTests/UnitTests/Doubles/FBApplicationDouble.h b/WebDriverAgentTests/UnitTests/Doubles/XCUIApplicationDouble.h similarity index 92% rename from WebDriverAgentTests/UnitTests/Doubles/FBApplicationDouble.h rename to WebDriverAgentTests/UnitTests/Doubles/XCUIApplicationDouble.h index d9906899a..ed25ced3f 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/FBApplicationDouble.h +++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIApplicationDouble.h @@ -9,7 +9,7 @@ #import -@interface FBApplicationDouble : NSObject +@interface XCUIApplicationDouble : NSObject @property (nonatomic, assign, readonly) BOOL didTerminate; @property (nonatomic, strong) NSString* bundleID; @property (nonatomic) BOOL fb_shouldWaitForQuiescence; diff --git a/WebDriverAgentTests/UnitTests/Doubles/FBApplicationDouble.m b/WebDriverAgentTests/UnitTests/Doubles/XCUIApplicationDouble.m similarity index 88% rename from WebDriverAgentTests/UnitTests/Doubles/FBApplicationDouble.m rename to WebDriverAgentTests/UnitTests/Doubles/XCUIApplicationDouble.m index d5b029a44..3f61b023c 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/FBApplicationDouble.m +++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIApplicationDouble.m @@ -7,13 +7,13 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -#import "FBApplicationDouble.h" +#import "XCUIApplicationDouble.h" -@interface FBApplicationDouble () +@interface XCUIApplicationDouble () @property (nonatomic, assign, readwrite) BOOL didTerminate; @end -@implementation FBApplicationDouble +@implementation XCUIApplicationDouble - (instancetype)init { diff --git a/WebDriverAgentTests/UnitTests/FBSessionTests.m b/WebDriverAgentTests/UnitTests/FBSessionTests.m index c7ae281cc..226e965b6 100644 --- a/WebDriverAgentTests/UnitTests/FBSessionTests.m +++ b/WebDriverAgentTests/UnitTests/FBSessionTests.m @@ -9,13 +9,13 @@ #import -#import "FBApplicationDouble.h" #import "FBSession.h" #import "FBConfiguration.h" +#import "XCUIApplicationDouble.h" @interface FBSessionTests : XCTestCase @property (nonatomic, strong) FBSession *session; -@property (nonatomic, strong) FBApplication *testedApplication; +@property (nonatomic, strong) XCUIApplication *testedApplication; @property (nonatomic) BOOL shouldTerminateAppValue; @end @@ -24,7 +24,7 @@ @implementation FBSessionTests - (void)setUp { [super setUp]; - self.testedApplication = (id)FBApplicationDouble.new; + self.testedApplication = (id)XCUIApplicationDouble.new; self.shouldTerminateAppValue = FBConfiguration.shouldTerminateApp; [FBConfiguration setShouldTerminateApp:NO]; self.session = [FBSession initWithApplication:self.testedApplication]; From a3ac2c58786955507a34d0adcc4a53cd30f55014 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jan 2024 22:51:14 +0100 Subject: [PATCH 006/368] chore(deps-dev): bump semantic-release from 22.0.12 to 23.0.0 (#836) Bumps [semantic-release](https://github.com/semantic-release/semantic-release) from 22.0.12 to 23.0.0. - [Release notes](https://github.com/semantic-release/semantic-release/releases) - [Commits](https://github.com/semantic-release/semantic-release/compare/v22.0.12...v23.0.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 3c5c458e7..99866ec0a 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": "^22.0.5", + "semantic-release": "^23.0.0", "sinon": "^17.0.0", "ts-node": "^10.9.1", "typescript": "~5.2" From e011c7e83919e6982d857d384b97416a22a46350 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 16 Jan 2024 21:56:30 +0000 Subject: [PATCH 007/368] chore(release): 5.15.7 [skip ci] ## [5.15.7](https://github.com/appium/WebDriverAgent/compare/v5.15.6...v5.15.7) (2024-01-16) ### Miscellaneous Chores * **deps-dev:** bump semantic-release from 22.0.12 to 23.0.0 ([#836](https://github.com/appium/WebDriverAgent/issues/836)) ([a3ac2c5](https://github.com/appium/WebDriverAgent/commit/a3ac2c58786955507a34d0adcc4a53cd30f55014)) ### Code Refactoring * Ditch FBApplication in favour of XCUIApplication extensions ([#834](https://github.com/appium/WebDriverAgent/issues/834)) ([70a8d98](https://github.com/appium/WebDriverAgent/commit/70a8d98bc15d8fc615455be07fad9c37ff8d430b)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d2c85a7b..56adc653d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [5.15.7](https://github.com/appium/WebDriverAgent/compare/v5.15.6...v5.15.7) (2024-01-16) + + +### Miscellaneous Chores + +* **deps-dev:** bump semantic-release from 22.0.12 to 23.0.0 ([#836](https://github.com/appium/WebDriverAgent/issues/836)) ([a3ac2c5](https://github.com/appium/WebDriverAgent/commit/a3ac2c58786955507a34d0adcc4a53cd30f55014)) + + +### Code Refactoring + +* Ditch FBApplication in favour of XCUIApplication extensions ([#834](https://github.com/appium/WebDriverAgent/issues/834)) ([70a8d98](https://github.com/appium/WebDriverAgent/commit/70a8d98bc15d8fc615455be07fad9c37ff8d430b)) + ## [5.15.6](https://github.com/appium/WebDriverAgent/compare/v5.15.5...v5.15.6) (2024-01-06) diff --git a/package.json b/package.json index 99866ec0a..ed7ea6eb5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.15.6", + "version": "5.15.7", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 429e154c28ab2f17685723b02c941efce03984d4 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 23 Jan 2024 22:47:38 -0800 Subject: [PATCH 008/368] fix: use arm64 naming for xctestrun (#840) * fix: use arm64 naming for xctestrun * tweak --- lib/utils.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index f52ec6fe0..f8e7007c1 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -7,6 +7,7 @@ import { WDA_RUNNER_BUNDLE_ID, PLATFORM_NAME_TVOS } from './constants'; import B from 'bluebird'; import _fs from 'fs'; import { waitForCondition } from 'asyncbox'; +import { arch } from 'os'; const PROJECT_FILE = 'project.pbxproj'; @@ -168,9 +169,9 @@ async function setRealDeviceSecurity (keychainPath, keychainPassword) { /** * Creates xctestrun file per device & platform version. * We expects to have WebDriverAgentRunner_iphoneos${sdkVersion|platformVersion}-arm64.xctestrun for real device - * and WebDriverAgentRunner_iphonesimulator${sdkVersion|platformVersion}-x86_64.xctestrun for simulator located @bootstrapPath + * and WebDriverAgentRunner_iphonesimulator${sdkVersion|platformVersion}-${x86_64|arm64}.xctestrun for simulator located @bootstrapPath * Newer Xcode (Xcode 10.0 at least) generate xctestrun file following sdkVersion. - * e.g. Xcode which has iOS SDK Version 12.2 generate WebDriverAgentRunner_iphonesimulator.2-x86_64.xctestrun + * e.g. Xcode which has iOS SDK Version 12.2 on an intel Mac host machine generates WebDriverAgentRunner_iphonesimulator.2-x86_64.xctestrun * even if the cap has platform version 11.4 * * @param {DeviceInfo} deviceInfo @@ -260,9 +261,10 @@ async function getXctestrunFilePath (deviceInfo, sdkVersion, bootstrapPath) { * @return {string} returns xctestrunFilePath for given device */ function getXctestrunFileName (deviceInfo, version) { - return isTvOS(deviceInfo.platformName) - ? `WebDriverAgentRunner_tvOS_appletv${deviceInfo.isRealDevice ? `os${version}-arm64` : `simulator${version}-x86_64`}.xctestrun` - : `WebDriverAgentRunner_iphone${deviceInfo.isRealDevice ? `os${version}-arm64` : `simulator${version}-x86_64`}.xctestrun`; + const archSuffix = deviceInfo.isRealDevice + ? `os${version}-arm64` + : `simulator${version}-${arch() === 'arm64' ? 'arm64' : 'x86_64'}`; + return `WebDriverAgentRunner_${isTvOS(deviceInfo.platformName) ? 'tvOS_appletv' : 'iphone'}${archSuffix}.xctestrun`; } /** From 5d345d52fb6b497297cb2b93c50446a9c22b7838 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 24 Jan 2024 06:52:59 +0000 Subject: [PATCH 009/368] chore(release): 5.15.8 [skip ci] ## [5.15.8](https://github.com/appium/WebDriverAgent/compare/v5.15.7...v5.15.8) (2024-01-24) ### Bug Fixes * use arm64 naming for xctestrun ([#840](https://github.com/appium/WebDriverAgent/issues/840)) ([429e154](https://github.com/appium/WebDriverAgent/commit/429e154c28ab2f17685723b02c941efce03984d4)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56adc653d..6eff4cdcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [5.15.8](https://github.com/appium/WebDriverAgent/compare/v5.15.7...v5.15.8) (2024-01-24) + + +### Bug Fixes + +* use arm64 naming for xctestrun ([#840](https://github.com/appium/WebDriverAgent/issues/840)) ([429e154](https://github.com/appium/WebDriverAgent/commit/429e154c28ab2f17685723b02c941efce03984d4)) + ## [5.15.7](https://github.com/appium/WebDriverAgent/compare/v5.15.6...v5.15.7) (2024-01-16) diff --git a/package.json b/package.json index ed7ea6eb5..eab1410bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.15.7", + "version": "5.15.8", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From feda373b6147d3e87b29dceb871887c77febe76b Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 31 Jan 2024 15:20:26 +0100 Subject: [PATCH 010/368] feat: Add coordinate-based APIs for gesture calls (#843) BREAKING CHANGE: The /wda/tap/:uuid endpoint has been replaced by /wda/element/:uuid/tap and /wda/tap ones --- .../Categories/XCUIElement+FBSwiping.h | 14 ++ .../Categories/XCUIElement+FBSwiping.m | 37 +++- .../Commands/FBElementCommands.m | 198 ++++++++++-------- 3 files changed, 153 insertions(+), 96 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h b/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h index b1451f484..c30707dff 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h @@ -22,4 +22,18 @@ NS_ASSUME_NONNULL_BEGIN @end +#if !TARGET_OS_TV +@interface XCUICoordinate (FBSwiping) + +/** + * Performs swipe gesture on the coordinate + * + * @param direction Swipe direction. The following values are supported: up, down, left and right + * @param velocity Swipe speed in pixels per second + */ +- (void)fb_swipeWithDirection:(NSString *)direction velocity:(nullable NSNumber*)velocity; + +@end +#endif + NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m b/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m index f7d8be124..4be4d34dc 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m @@ -12,29 +12,46 @@ #import "FBLogger.h" #import "XCUIElement.h" -@implementation XCUIElement (FBSwiping) - -- (void)fb_swipeWithDirection:(NSString *)direction velocity:(nullable NSNumber*)velocity -{ +void swipeWithDirection(NSObject *target, NSString *direction, NSNumber* _Nullable velocity) { double velocityValue = .0; if (nil != velocity) { velocityValue = [velocity doubleValue]; } if (velocityValue > 0) { - SEL selector = NSSelectorFromString([NSString stringWithFormat:@"swipe%@WithVelocity:", direction.lowercaseString.capitalizedString]); - NSMethodSignature *signature = [self methodSignatureForSelector:selector]; + SEL selector = NSSelectorFromString([NSString stringWithFormat:@"swipe%@WithVelocity:", + direction.lowercaseString.capitalizedString]); + NSMethodSignature *signature = [target methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setSelector:selector]; [invocation setArgument:&velocityValue atIndex:2]; - [invocation invokeWithTarget:self]; + [invocation invokeWithTarget:target]; } else { - SEL selector = NSSelectorFromString([NSString stringWithFormat:@"swipe%@", direction.lowercaseString.capitalizedString]); - NSMethodSignature *signature = [self methodSignatureForSelector:selector]; + SEL selector = NSSelectorFromString([NSString stringWithFormat:@"swipe%@", + direction.lowercaseString.capitalizedString]); + NSMethodSignature *signature = [target methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setSelector:selector]; - [invocation invokeWithTarget:self]; + [invocation invokeWithTarget:target]; } } +@implementation XCUIElement (FBSwiping) + +- (void)fb_swipeWithDirection:(NSString *)direction velocity:(nullable NSNumber*)velocity +{ + swipeWithDirection(self, direction, velocity); +} + +@end + +#if !TARGET_OS_TV +@implementation XCUICoordinate (FBSwiping) + +- (void)fb_swipeWithDirection:(NSString *)direction velocity:(nullable NSNumber*)velocity +{ + swipeWithDirection(self, direction, velocity); +} + @end +#endif diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 4d5a69ea3..0313302f2 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -74,24 +74,46 @@ + (NSArray *)routes [[FBRoute POST:@"/wda/element/:uuid/focuse"] respondWithTarget:self action:@selector(handleFocuse:)], #else [[FBRoute POST:@"/wda/element/:uuid/swipe"] respondWithTarget:self action:@selector(handleSwipe:)], + [[FBRoute POST:@"/wda/swipe"] respondWithTarget:self action:@selector(handleSwipe:)], + [[FBRoute POST:@"/wda/element/:uuid/pinch"] respondWithTarget:self action:@selector(handlePinch:)], + [[FBRoute POST:@"/wda/pinch"] respondWithTarget:self action:@selector(handlePinch:)], + [[FBRoute POST:@"/wda/element/:uuid/rotate"] respondWithTarget:self action:@selector(handleRotate:)], + [[FBRoute POST:@"/wda/rotate"] respondWithTarget:self action:@selector(handleRotate:)], + [[FBRoute POST:@"/wda/element/:uuid/doubleTap"] respondWithTarget:self action:@selector(handleDoubleTap:)], + [[FBRoute POST:@"/wda/doubleTap"] respondWithTarget:self action:@selector(handleDoubleTap:)], + [[FBRoute POST:@"/wda/element/:uuid/twoFingerTap"] respondWithTarget:self action:@selector(handleTwoFingerTap:)], - [[FBRoute POST:@"/wda/element/:uuid/tapWithNumberOfTaps"] respondWithTarget:self action:@selector(handleTapWithNumberOfTaps:)], + [[FBRoute POST:@"/wda/twoFingerTap"] respondWithTarget:self action:@selector(handleTwoFingerTap:)], + + [[FBRoute POST:@"/wda/element/:uuid/tapWithNumberOfTaps"] respondWithTarget:self + action:@selector(handleTapWithNumberOfTaps:)], + [[FBRoute POST:@"/wda/tapWithNumberOfTaps"] respondWithTarget:self + action:@selector(handleTapWithNumberOfTaps:)], + [[FBRoute POST:@"/wda/element/:uuid/touchAndHold"] respondWithTarget:self action:@selector(handleTouchAndHold:)], + [[FBRoute POST:@"/wda/touchAndHold"] respondWithTarget:self action:@selector(handleTouchAndHold:)], + [[FBRoute POST:@"/wda/element/:uuid/scroll"] respondWithTarget:self action:@selector(handleScroll:)], + [[FBRoute POST:@"/wda/scroll"] respondWithTarget:self action:@selector(handleScroll:)], + [[FBRoute POST:@"/wda/element/:uuid/scrollTo"] respondWithTarget:self action:@selector(handleScrollTo:)], + [[FBRoute POST:@"/wda/element/:uuid/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDrag:)], + [[FBRoute POST:@"/wda/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDrag:)], + [[FBRoute POST:@"/wda/element/:uuid/pressAndDragWithVelocity"] respondWithTarget:self action:@selector(handlePressAndDragWithVelocity:)], - [[FBRoute POST:@"/wda/element/:uuid/forceTouch"] respondWithTarget:self action:@selector(handleForceTouch:)], - [[FBRoute POST:@"/wda/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDragCoordinate:)], [[FBRoute POST:@"/wda/pressAndDragWithVelocity"] respondWithTarget:self action:@selector(handlePressAndDragCoordinateWithVelocity:)], - [[FBRoute POST:@"/wda/tap/:uuid"] respondWithTarget:self action:@selector(handleTap:)], - [[FBRoute POST:@"/wda/touchAndHold"] respondWithTarget:self action:@selector(handleTouchAndHoldCoordinate:)], - [[FBRoute POST:@"/wda/doubleTap"] respondWithTarget:self action:@selector(handleDoubleTapCoordinate:)], - [[FBRoute POST:@"/wda/pickerwheel/:uuid/select"] respondWithTarget:self action:@selector(handleWheelSelect:)], + + [[FBRoute POST:@"/wda/element/:uuid/forceTouch"] respondWithTarget:self action:@selector(handleForceTouch:)], [[FBRoute POST:@"/wda/forceTouch"] respondWithTarget:self action:@selector(handleForceTouch:)], + + [[FBRoute POST:@"/wda/element/:uuid/tap"] respondWithTarget:self action:@selector(handleTap:)], + [[FBRoute POST:@"/wda/tap"] respondWithTarget:self action:@selector(handleTap:)], + + [[FBRoute POST:@"/wda/pickerwheel/:uuid/select"] respondWithTarget:self action:@selector(handleWheelSelect:)], #endif [[FBRoute POST:@"/wda/keys"] respondWithTarget:self action:@selector(handleKeys:)], ]; @@ -285,38 +307,30 @@ + (NSArray *)routes #else + (id)handleDoubleTap:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - [element doubleTap]; - return FBResponseWithOK(); -} - -+ (id)handleDoubleTapCoordinate:(FBRouteRequest *)request -{ - CGVector offset = CGVectorMake([request.arguments[@"x"] doubleValue], - [request.arguments[@"y"] doubleValue]); - XCUICoordinate *doubleTapCoordinate = [self.class gestureCoordinateWithOffset:offset - element:request.session.activeApplication]; - [doubleTapCoordinate doubleTap]; + NSError *error; + id target = [self targetWithXyCoordinatesFromRequest:request error:&error]; + if (nil == target) { + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.localizedDescription + traceback:nil]); + } + [target doubleTap]; return FBResponseWithOK(); } + (id)handleTwoFingerTap:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [self targetFromRequest:request]; [element twoFingerTap]; return FBResponseWithOK(); } + (id)handleTapWithNumberOfTaps:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; if (nil == request.arguments[@"numberOfTaps"] || nil == request.arguments[@"numberOfTouches"]) { return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"Both 'numberOfTaps' and 'numberOfTouches' arguments must be provided" traceback:nil]); } - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [self targetFromRequest:request]; [element tapWithNumberOfTaps:[request.arguments[@"numberOfTaps"] integerValue] numberOfTouches:[request.arguments[@"numberOfTouches"] integerValue]]; return FBResponseWithOK(); @@ -324,26 +338,20 @@ + (NSArray *)routes + (id)handleTouchAndHold:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - [element pressForDuration:[request.arguments[@"duration"] doubleValue]]; - return FBResponseWithOK(); -} - -+ (id)handleTouchAndHoldCoordinate:(FBRouteRequest *)request -{ - 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]]; + NSError *error; + id target = [self targetWithXyCoordinatesFromRequest:request error:&error]; + if (nil == target) { + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.localizedDescription + traceback:nil]); + } + [target pressForDuration:[request.arguments[@"duration"] doubleValue]]; return FBResponseWithOK(); } + (id)handlePressAndDragWithVelocity:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [self targetFromRequest:request]; if (![element respondsToSelector:@selector(pressForDuration:thenDragToElement:withVelocity:thenHoldForDuration:)]) { return FBResponseWithStatus([FBCommandStatus unsupportedOperationErrorWithMessage:@"This method is only supported in Xcode 12 and above" traceback:nil]); @@ -379,8 +387,7 @@ + (NSArray *)routes + (id)handleScroll:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [self targetFromRequest:request]; // Using presence of arguments as a way to convey control flow seems like a pretty bad idea but it's // what ios-driver did and sadly, we must copy them. NSString *const name = request.arguments[@"name"]; @@ -440,33 +447,18 @@ + (NSArray *)routes traceback:nil]); } -+ (id)handleDragCoordinate:(FBRouteRequest *)request -{ - FBSession *session = request.session; - 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]; - [startCoordinate pressForDuration:duration thenDragToCoordinate:endCoordinate]; - return FBResponseWithOK(); -} - + (id)handleDrag:(FBRouteRequest *)request { - FBSession *session = request.session; - FBElementCache *elementCache = session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + NSString *elementUdid = (NSString *)request.parameters[@"uuid"]; + XCUIElement *target = nil == elementUdid + ? request.session.activeApplication + : [request.session.elementCache elementForUUID:elementUdid]; CGVector startOffset = CGVectorMake([request.arguments[@"fromX"] doubleValue], [request.arguments[@"fromY"] doubleValue]); - XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset element:element]; + XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset element:target]; CGVector endOffset = CGVectorMake([request.arguments[@"toX"] doubleValue], [request.arguments[@"toY"] doubleValue]); - XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithOffset:endOffset element:element]; + XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithOffset:endOffset element:target]; NSTimeInterval duration = [request.arguments[@"duration"] doubleValue]; [startCoordinate pressForDuration:duration thenDragToCoordinate:endCoordinate]; return FBResponseWithOK(); @@ -474,39 +466,41 @@ + (NSArray *)routes + (id)handleSwipe:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; NSString *const direction = request.arguments[@"direction"]; if (!direction) { return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"Missing 'direction' parameter" traceback:nil]); } NSArray *supportedDirections = @[@"up", @"down", @"left", @"right"]; if (![supportedDirections containsObject:direction.lowercaseString]) { - return FBResponseWithStatus([FBCommandStatus - invalidArgumentErrorWithMessage:[NSString stringWithFormat: @"Unsupported swipe direction '%@'. Only the following directions are supported: %@", direction, supportedDirections] - traceback:nil]); + NSString *message = [NSString stringWithFormat:@"Unsupported swipe direction '%@'. Only the following directions are supported: %@", direction, supportedDirections]; + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:message + traceback:nil]); } - [element fb_swipeWithDirection:direction.lowercaseString velocity:request.arguments[@"velocity"]]; + NSError *error; + id target = [self targetWithXyCoordinatesFromRequest:request error:&error]; + if (nil == target) { + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.localizedDescription + traceback:nil]); + } + [target fb_swipeWithDirection:direction velocity:request.arguments[@"velocity"]]; return FBResponseWithOK(); } + (id)handleTap:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - 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]; + NSError *error; + id target = [self targetWithXyCoordinatesFromRequest:request error:&error]; + if (nil == target) { + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.localizedDescription + traceback:nil]); + } + [target tap]; return FBResponseWithOK(); } + (id)handlePinch:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [self targetFromRequest:request]; CGFloat scale = (CGFloat)[request.arguments[@"scale"] doubleValue]; CGFloat velocity = (CGFloat)[request.arguments[@"velocity"] doubleValue]; [element pinchWithScale:scale velocity:velocity]; @@ -515,8 +509,7 @@ + (NSArray *)routes + (id)handleRotate:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [self targetFromRequest:request]; CGFloat rotation = (CGFloat)[request.arguments[@"rotation"] doubleValue]; CGFloat velocity = (CGFloat)[request.arguments[@"velocity"] doubleValue]; [element rotate:rotation withVelocity:velocity]; @@ -525,13 +518,7 @@ + (NSArray *)routes + (id)handleForceTouch:(FBRouteRequest *)request { - XCUIElement *element = nil; - if (nil == request.parameters[@"uuid"]) { - element = XCUIApplication.fb_activeApplication; - } else { - FBElementCache *elementCache = request.session.elementCache; - element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - } + XCUIElement *element = [self targetFromRequest:request]; NSNumber *pressure = request.arguments[@"pressure"]; NSNumber *duration = request.arguments[@"duration"]; NSNumber *x = request.arguments[@"x"]; @@ -673,6 +660,45 @@ + (XCUICoordinate *)gestureCoordinateWithOffset:(CGVector)offset return [[element coordinateWithNormalizedOffset:CGVectorMake(0, 0)] coordinateWithOffset:offset]; } +/** + Returns either coordinates or the target element for the given request that expects 'x' and 'y' coordannates + + @param request HTTP request object + @param error Error instance if any + @return Either XCUICoordinate or XCUIElement instance. nil if the input data is invalid + */ ++ (nullable id)targetWithXyCoordinatesFromRequest:(FBRouteRequest *)request error:(NSError **)error +{ + NSNumber *x = request.arguments[@"x"]; + NSNumber *y = request.arguments[@"y"]; + if (nil == x && nil == y) { + return [self targetFromRequest:request]; + } + if ((nil == x && nil != y) || (nil != x && nil == y)) { + [[[FBErrorBuilder alloc] + withDescription:@"Both x and y coordinates must be provided"] + buildError:error]; + return nil; + } + return [self gestureCoordinateWithOffset:CGVectorMake(x.doubleValue, y.doubleValue) + element:[self targetFromRequest:request]]; +} + +/** + Returns the target element for the given request + + @param request HTTP request object + @return Matching XCUIElement instance + */ ++ (XCUIElement *)targetFromRequest:(FBRouteRequest *)request +{ + FBElementCache *elementCache = request.session.elementCache; + NSString *elementUuid = (NSString *)request.parameters[@"uuid"]; + return nil == elementUuid + ? request.session.activeApplication + : [elementCache elementForUUID:elementUuid]; +} + #endif @end From 925f358612409b5d7e0c5c4dbd892f00721ee1ae Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 31 Jan 2024 14:25:46 +0000 Subject: [PATCH 011/368] chore(release): 6.0.0 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [6.0.0](https://github.com/appium/WebDriverAgent/compare/v5.15.8...v6.0.0) (2024-01-31) ### ⚠ BREAKING CHANGES * The /wda/tap/:uuid endpoint has been replaced by /wda/element/:uuid/tap and /wda/tap ones ### Features * Add coordinate-based APIs for gesture calls ([#843](https://github.com/appium/WebDriverAgent/issues/843)) ([feda373](https://github.com/appium/WebDriverAgent/commit/feda373b6147d3e87b29dceb871887c77febe76b)) --- CHANGELOG.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eff4cdcc..6e0aabb3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [6.0.0](https://github.com/appium/WebDriverAgent/compare/v5.15.8...v6.0.0) (2024-01-31) + + +### ⚠ BREAKING CHANGES + +* The /wda/tap/:uuid endpoint has been replaced by /wda/element/:uuid/tap and /wda/tap ones + +### Features + +* Add coordinate-based APIs for gesture calls ([#843](https://github.com/appium/WebDriverAgent/issues/843)) ([feda373](https://github.com/appium/WebDriverAgent/commit/feda373b6147d3e87b29dceb871887c77febe76b)) + ## [5.15.8](https://github.com/appium/WebDriverAgent/compare/v5.15.7...v5.15.8) (2024-01-24) diff --git a/package.json b/package.json index eab1410bc..23248bbce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "5.15.8", + "version": "6.0.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From aa25e49fa9821960b08e9f4f3ea5891ebdf7d48d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 10 Feb 2024 20:59:38 +0100 Subject: [PATCH 012/368] feat: Add a possibility of starting a test with a deep link (#845) --- .../Commands/FBSessionCommands.m | 39 ++++++++++++++++++- WebDriverAgentLib/Utilities/FBCapabilities.h | 20 ++++++++++ WebDriverAgentLib/Utilities/FBCapabilities.m | 1 + package.json | 14 +------ 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index f5abdc55a..fe82a0a35 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -136,7 +136,9 @@ + (NSArray *)routes } NSString *bundleID = capabilities[FB_CAP_BUNDLE_ID]; + NSString *initialUrl = capabilities[FB_CAP_INITIAL_URL]; XCUIApplication *app = nil; + BOOL didOpenInitialUrl = NO; if (bundleID != nil) { app = [[XCUIApplication alloc] initWithBundleIdentifier:bundleID]; BOOL forceAppLaunch = YES; @@ -150,14 +152,47 @@ + (NSArray *)routes || [capabilities[FB_CAP_SHOULD_WAIT_FOR_QUIESCENCE] boolValue]; app.launchArguments = (NSArray *)capabilities[FB_CAP_ARGUMENTS] ?: @[]; app.launchEnvironment = (NSDictionary *)capabilities[FB_CAP_ENVIRNOMENT] ?: @{}; - [app launch]; + if (nil != initialUrl) { + NSError *openError; + didOpenInitialUrl = [XCUIDevice.sharedDevice fb_openUrl:initialUrl + withApplication:bundleID + error:&openError]; + if (!didOpenInitialUrl) { + NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ in %@ application. Original error: %@", + initialUrl, bundleID, openError.description]; + return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + } + } else { + [app launch]; + } if (![app running]) { NSString *errorMsg = [NSString stringWithFormat:@"Cannot launch %@ application. Make sure the correct bundle identifier has been provided in capabilities and check the device log for possible crash report occurrences", bundleID]; return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); } } else if (appState == XCUIApplicationStateRunningBackground && !forceAppLaunch) { - [app activate]; + if (nil != initialUrl) { + NSError *openError; + didOpenInitialUrl = [XCUIDevice.sharedDevice fb_openUrl:initialUrl + withApplication:bundleID + error:&openError]; + if (!didOpenInitialUrl) { + NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ in %@ application. Original error: %@", + initialUrl, bundleID, openError.description]; + return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + } + } else { + [app activate]; + } + } + } + + if (nil != initialUrl && nil == bundleID) { + NSError *openError; + if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl error:&openError]) { + NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@. Original error: %@", + initialUrl, openError.description]; + return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); } } diff --git a/WebDriverAgentLib/Utilities/FBCapabilities.h b/WebDriverAgentLib/Utilities/FBCapabilities.h index 116c408df..1045a9855 100644 --- a/WebDriverAgentLib/Utilities/FBCapabilities.h +++ b/WebDriverAgentLib/Utilities/FBCapabilities.h @@ -9,16 +9,36 @@ #import +/** Whether to use alternative elements visivility detection method */ extern NSString* const FB_CAP_USE_TEST_MANAGER_FOR_VISIBLITY_DETECTION; +/** Set the maximum amount of charatcers that could be typed within a minute (60 by default) */ extern NSString* const FB_CAP_MAX_TYPING_FREQUENCY; +/** this setting was needed for some legacy stuff */ extern NSString* const FB_CAP_USE_SINGLETON_TEST_MANAGER; +/** Whether to disable screneshots that XCTest automaticallly creates after each step */ extern NSString* const FB_CAP_DISABLE_AUTOMATIC_SCREENSHOTS; +/** Whether to terminate the application under test after the session ends */ extern NSString* const FB_CAP_SHOULD_TERMINATE_APP; +/** The maximum amount of seconds to wait for the event loop to become idle */ extern NSString* const FB_CAP_EVENT_LOOP_IDLE_DELAY_SEC; +/** Bundle identifier of the application to run the test for */ extern NSString* const FB_CAP_BUNDLE_ID; +/** + Usually an URL used as initial link to run Mobile Safari, but could be any other deep link. + This might also work together with `FB_CAP_BUNLDE_ID`, which tells XCTest to open + the given deep link in the particular app. + Only works since iOS 16.4 + */ +extern NSString* const FB_CAP_INITIAL_URL; +/** Whether to enforrce (re)start of the application under test on session startup */ extern NSString* const FB_CAP_FORCE_APP_LAUNCH; +/** Whether to wait for quiescence before starting interaction with apps laucnhes in scope of the test session */ extern NSString* const FB_CAP_SHOULD_WAIT_FOR_QUIESCENCE; +/** Array of command line arguments to be passed to the application under test */ extern NSString* const FB_CAP_ARGUMENTS; +/** Dictionary of environment variables to be passed to the application under test */ extern NSString* const FB_CAP_ENVIRNOMENT; +/** Whether to use native XCTest caching strategy */ extern NSString* const FB_CAP_USE_NATIVE_CACHING_STRATEGY; +/** Whether to enforce software keyboard presence on simulator */ extern NSString* const FB_CAP_FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE; diff --git a/WebDriverAgentLib/Utilities/FBCapabilities.m b/WebDriverAgentLib/Utilities/FBCapabilities.m index cafd0f168..1798c2195 100644 --- a/WebDriverAgentLib/Utilities/FBCapabilities.m +++ b/WebDriverAgentLib/Utilities/FBCapabilities.m @@ -16,6 +16,7 @@ NSString* const FB_CAP_SHOULD_TERMINATE_APP = @"shouldTerminateApp"; NSString* const FB_CAP_EVENT_LOOP_IDLE_DELAY_SEC = @"eventloopIdleDelaySec"; NSString* const FB_CAP_BUNDLE_ID = @"bundleId"; +NSString* const FB_CAP_INITIAL_URL = @"initialUrl"; NSString* const FB_CAP_FORCE_APP_LAUNCH = @"forceAppLaunch"; NSString* const FB_CAP_SHOULD_WAIT_FOR_QUIESCENCE = @"shouldWaitForQuiescence"; NSString* const FB_CAP_ARGUMENTS = @"arguments"; diff --git a/package.json b/package.json index 23248bbce..0df5e1b9c 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,8 @@ "dev": "npm run build -- --watch", "clean": "npm run build -- --clean", "lint": "eslint .", + "format": "prettier -w ./lib", "lint:fix": "npm run lint -- --fix", - "precommit-msg": "echo 'Pre-commit checks...' && exit 0", - "precommit-lint": "lint-staged", "prepare": "npm run build", "test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.js\"", "e2e-test": "mocha --exit --timeout 10m \"./test/functional/**/*-specs.js\"", @@ -23,20 +22,11 @@ "node": ">=14", "npm": ">=8" }, - "lint-staged": { - "*.js": [ - "eslint --fix" - ] - }, "prettier": { "bracketSpacing": false, "printWidth": 100, "singleQuote": true }, - "pre-commit": [ - "precommit-msg", - "precommit-lint" - ], "repository": { "type": "git", "url": "git+https://github.com/appium/WebDriverAgent.git" @@ -83,9 +73,7 @@ "eslint-plugin-import": "^2.28.0", "eslint-plugin-mocha": "^10.1.0", "eslint-plugin-promise": "^6.1.1", - "lint-staged": "^15.0.2", "mocha": "^10.0.0", - "pre-commit": "^1.2.2", "prettier": "^3.0.0", "semantic-release": "^23.0.0", "sinon": "^17.0.0", From ed06d2f2b60d546a9e7d0ffaa28dd3eb84d4fe3a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 10 Feb 2024 20:05:47 +0000 Subject: [PATCH 013/368] chore(release): 6.1.0 [skip ci] ## [6.1.0](https://github.com/appium/WebDriverAgent/compare/v6.0.0...v6.1.0) (2024-02-10) ### Features * Add a possibility of starting a test with a deep link ([#845](https://github.com/appium/WebDriverAgent/issues/845)) ([aa25e49](https://github.com/appium/WebDriverAgent/commit/aa25e49fa9821960b08e9f4f3ea5891ebdf7d48d)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e0aabb3e..e41776692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [6.1.0](https://github.com/appium/WebDriverAgent/compare/v6.0.0...v6.1.0) (2024-02-10) + + +### Features + +* Add a possibility of starting a test with a deep link ([#845](https://github.com/appium/WebDriverAgent/issues/845)) ([aa25e49](https://github.com/appium/WebDriverAgent/commit/aa25e49fa9821960b08e9f4f3ea5891ebdf7d48d)) + ## [6.0.0](https://github.com/appium/WebDriverAgent/compare/v5.15.8...v6.0.0) (2024-01-31) diff --git a/package.json b/package.json index 0df5e1b9c..175c61b1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "6.0.0", + "version": "6.1.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 88b0a5b0f8aefa05a7dc28d17faf62c229e0706f Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 11 Feb 2024 12:45:53 +0100 Subject: [PATCH 014/368] chore: Make sure the app under test is restarted if opened from a deep link (#846) --- .../Commands/FBSessionCommands.m | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index fe82a0a35..9594058a9 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -138,7 +138,6 @@ + (NSArray *)routes NSString *bundleID = capabilities[FB_CAP_BUNDLE_ID]; NSString *initialUrl = capabilities[FB_CAP_INITIAL_URL]; XCUIApplication *app = nil; - BOOL didOpenInitialUrl = NO; if (bundleID != nil) { app = [[XCUIApplication alloc] initWithBundleIdentifier:bundleID]; BOOL forceAppLaunch = YES; @@ -153,19 +152,21 @@ + (NSArray *)routes app.launchArguments = (NSArray *)capabilities[FB_CAP_ARGUMENTS] ?: @[]; app.launchEnvironment = (NSDictionary *)capabilities[FB_CAP_ENVIRNOMENT] ?: @{}; if (nil != initialUrl) { + if (app.running) { + [app terminate]; + } NSError *openError; - didOpenInitialUrl = [XCUIDevice.sharedDevice fb_openUrl:initialUrl - withApplication:bundleID - error:&openError]; - if (!didOpenInitialUrl) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ in %@ application. Original error: %@", + if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl + withApplication:bundleID + error:&openError]) { + NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ wuth the %@ application. Original error: %@", initialUrl, bundleID, openError.description]; return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); } } else { [app launch]; } - if (![app running]) { + if (!app.running) { NSString *errorMsg = [NSString stringWithFormat:@"Cannot launch %@ application. Make sure the correct bundle identifier has been provided in capabilities and check the device log for possible crash report occurrences", bundleID]; return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); @@ -173,11 +174,10 @@ + (NSArray *)routes } else if (appState == XCUIApplicationStateRunningBackground && !forceAppLaunch) { if (nil != initialUrl) { NSError *openError; - didOpenInitialUrl = [XCUIDevice.sharedDevice fb_openUrl:initialUrl - withApplication:bundleID - error:&openError]; - if (!didOpenInitialUrl) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ in %@ application. Original error: %@", + if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl + withApplication:bundleID + error:&openError]) { + NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", initialUrl, bundleID, openError.description]; return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); } From 17b94de2c63c6dc055455fae7d0c9776cb4770be Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 11 Feb 2024 11:51:11 +0000 Subject: [PATCH 015/368] chore(release): 6.1.1 [skip ci] ## [6.1.1](https://github.com/appium/WebDriverAgent/compare/v6.1.0...v6.1.1) (2024-02-11) ### Miscellaneous Chores * Make sure the app under test is restarted if opened from a deep link ([#846](https://github.com/appium/WebDriverAgent/issues/846)) ([88b0a5b](https://github.com/appium/WebDriverAgent/commit/88b0a5b0f8aefa05a7dc28d17faf62c229e0706f)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e41776692..ae9968eeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [6.1.1](https://github.com/appium/WebDriverAgent/compare/v6.1.0...v6.1.1) (2024-02-11) + + +### Miscellaneous Chores + +* Make sure the app under test is restarted if opened from a deep link ([#846](https://github.com/appium/WebDriverAgent/issues/846)) ([88b0a5b](https://github.com/appium/WebDriverAgent/commit/88b0a5b0f8aefa05a7dc28d17faf62c229e0706f)) + ## [6.1.0](https://github.com/appium/WebDriverAgent/compare/v6.0.0...v6.1.0) (2024-02-10) diff --git a/package.json b/package.json index 175c61b1a..c4f3cda47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "6.1.0", + "version": "6.1.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From d77f640867155fddbbbc9575f0a77802602865e7 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 12 Feb 2024 20:54:55 +0100 Subject: [PATCH 016/368] feat: Remove obsolete MJSONWP touch actions (#847) BREAKING CHANGE: The following REST endpoints have been removed, use W3C actions instead: - /wda/touch/perform - /wda/touch/multi/perform --- WebDriverAgent.xcodeproj/project.pbxproj | 20 - .../XCUIApplication+FBTouchAction.h | 37 -- .../XCUIApplication+FBTouchAction.m | 15 - .../Commands/FBTouchActionCommands.m | 13 - .../Utilities/FBAppiumActionsSynthesizer.h | 20 - .../Utilities/FBAppiumActionsSynthesizer.m | 554 ------------------ ...BAppiumMultiTouchActionsIntegrationTests.m | 206 ------- .../FBAppiumTouchActionsIntegrationTests.m | 404 ------------- 8 files changed, 1269 deletions(-) delete mode 100644 WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.h delete mode 100644 WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m delete mode 100644 WebDriverAgentTests/IntegrationTests/FBAppiumMultiTouchActionsIntegrationTests.m delete mode 100644 WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index 4c098bde8..bc4f29813 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -49,7 +49,6 @@ 641EE5DA2240C5CA00173FCB /* XCUIApplicationProcessDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */; }; 641EE5DB2240C5CA00173FCB /* FBXPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 711084431DA3AA7500F913D6 /* FBXPath.m */; }; 641EE5DC2240C5CA00173FCB /* XCUIApplication+FBAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 719CD8FB2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m */; }; - 641EE5DD2240C5CA00173FCB /* FBAppiumActionsSynthesizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 71241D771FAE31F100B9559F /* FBAppiumActionsSynthesizer.m */; }; 641EE5DE2240C5CA00173FCB /* XCUIApplication+FBTouchAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BD20721F86116100B36EC2 /* XCUIApplication+FBTouchAction.m */; }; 641EE5DF2240C5CA00173FCB /* FBWebServer.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB78D1CAEDF0C008C271F /* FBWebServer.m */; }; 641EE5E02240C5CA00173FCB /* FBTCPSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 715557D2211DBCE700613B26 /* FBTCPSocket.m */; }; @@ -269,7 +268,6 @@ 641EE6D82240C5CA00173FCB /* XCUIElement.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACFE1E3B77D600A02D78 /* XCUIElement.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6D92240C5CA00173FCB /* XCKeyboardInputSolver.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACBE1E3B77D600A02D78 /* XCKeyboardInputSolver.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6DB2240C5CA00173FCB /* FBPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 71930C4020662E1F00D3AFEC /* FBPasteboard.h */; }; - 641EE6DC2240C5CA00173FCB /* FBAppiumActionsSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 714097451FAE1B32008FB2C5 /* FBAppiumActionsSynthesizer.h */; }; 641EE6DD2240C5CA00173FCB /* FBDebugLogDelegateDecorator.h in Headers */ = {isa = PBXBuildFile; fileRef = EE7E27181D06C69F001BEC7B /* FBDebugLogDelegateDecorator.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6DE2240C5CA00173FCB /* XCUIDevice+FBHealthCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = EEDFE11F1D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h */; settings = {ATTRIBUTES = (Public, ); }; }; 641EE6DF2240C5CA00173FCB /* FBMjpegServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7155D701211DCEF400166C20 /* FBMjpegServer.h */; }; @@ -318,7 +316,6 @@ 7119E1EC1E891F8600D0B125 /* FBPickerWheelSelectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7119E1EB1E891F8600D0B125 /* FBPickerWheelSelectTests.m */; }; 711CD03425ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 711CD03325ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h */; }; 711CD03525ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 711CD03325ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h */; }; - 71241D781FAE31F100B9559F /* FBAppiumActionsSynthesizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 71241D771FAE31F100B9559F /* FBAppiumActionsSynthesizer.m */; }; 71241D7B1FAE3D2500B9559F /* FBTouchActionCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = 71241D791FAE3D2500B9559F /* FBTouchActionCommands.h */; }; 71241D7C1FAE3D2500B9559F /* FBTouchActionCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 71241D7A1FAE3D2500B9559F /* FBTouchActionCommands.m */; }; 71241D7E1FAF084E00B9559F /* FBW3CTouchActionsIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71241D7D1FAF084E00B9559F /* FBW3CTouchActionsIntegrationTests.m */; }; @@ -336,7 +333,6 @@ 713C6DCF1DDC772A00285B92 /* FBElementUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 713C6DCD1DDC772A00285B92 /* FBElementUtils.h */; }; 713C6DD01DDC772A00285B92 /* FBElementUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 713C6DCE1DDC772A00285B92 /* FBElementUtils.m */; }; 714097431FAE1B0B008FB2C5 /* FBBaseActionsSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 714097411FAE1B0B008FB2C5 /* FBBaseActionsSynthesizer.h */; }; - 714097471FAE1B32008FB2C5 /* FBAppiumActionsSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 714097451FAE1B32008FB2C5 /* FBAppiumActionsSynthesizer.h */; }; 7140974B1FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 714097491FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.h */; }; 7140974C1FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7140974A1FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.m */; }; 7140974E1FAE20EE008FB2C5 /* FBBaseActionsSynthesizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7140974D1FAE20EE008FB2C5 /* FBBaseActionsSynthesizer.m */; }; @@ -432,7 +428,6 @@ 71930C4220662E1F00D3AFEC /* FBPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 71930C4020662E1F00D3AFEC /* FBPasteboard.h */; }; 71930C4320662E1F00D3AFEC /* FBPasteboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 71930C4120662E1F00D3AFEC /* FBPasteboard.m */; }; 71930C472066434000D3AFEC /* FBPasteboardTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71930C462066434000D3AFEC /* FBPasteboardTests.m */; }; - 719A97AC1F88E7370063B4BD /* FBAppiumMultiTouchActionsIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 719A97AB1F88E7370063B4BD /* FBAppiumMultiTouchActionsIntegrationTests.m */; }; 719CD8F82126C78F00C7D0C2 /* FBAlertsMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 719CD8F62126C78F00C7D0C2 /* FBAlertsMonitor.h */; }; 719CD8F92126C78F00C7D0C2 /* FBAlertsMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 719CD8F72126C78F00C7D0C2 /* FBAlertsMonitor.m */; }; 719CD8FC2126C88B00C7D0C2 /* XCUIApplication+FBAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = 719CD8FA2126C88B00C7D0C2 /* XCUIApplication+FBAlert.h */; }; @@ -464,7 +459,6 @@ 71B49EC81ED1A58100D51AD6 /* XCUIElement+FBUID.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B49EC61ED1A58100D51AD6 /* XCUIElement+FBUID.m */; }; 71BD20731F86116100B36EC2 /* XCUIApplication+FBTouchAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BD20711F86116100B36EC2 /* XCUIApplication+FBTouchAction.h */; }; 71BD20741F86116100B36EC2 /* XCUIApplication+FBTouchAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BD20721F86116100B36EC2 /* XCUIApplication+FBTouchAction.m */; }; - 71BD20781F869E0F00B36EC2 /* FBAppiumTouchActionsIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BD20771F869E0F00B36EC2 /* FBAppiumTouchActionsIntegrationTests.m */; }; 71C8E55125399A6B008572C1 /* XCUIApplication+FBQuiescence.h in Headers */ = {isa = PBXBuildFile; fileRef = 71C8E54F25399A6B008572C1 /* XCUIApplication+FBQuiescence.h */; }; 71C8E55225399A6B008572C1 /* XCUIApplication+FBQuiescence.h in Headers */ = {isa = PBXBuildFile; fileRef = 71C8E54F25399A6B008572C1 /* XCUIApplication+FBQuiescence.h */; }; 71C8E55325399A6B008572C1 /* XCUIApplication+FBQuiescence.m in Sources */ = {isa = PBXBuildFile; fileRef = 71C8E55025399A6B008572C1 /* XCUIApplication+FBQuiescence.m */; }; @@ -940,7 +934,6 @@ 7119097B2152580600BA3C7E /* XCUIScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCUIScreen.h; sourceTree = ""; }; 7119E1EB1E891F8600D0B125 /* FBPickerWheelSelectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBPickerWheelSelectTests.m; sourceTree = ""; }; 711CD03325ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIScreenDataSource-Protocol.h"; sourceTree = ""; }; - 71241D771FAE31F100B9559F /* FBAppiumActionsSynthesizer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAppiumActionsSynthesizer.m; sourceTree = ""; }; 71241D791FAE3D2500B9559F /* FBTouchActionCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBTouchActionCommands.h; sourceTree = ""; }; 71241D7A1FAE3D2500B9559F /* FBTouchActionCommands.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBTouchActionCommands.m; sourceTree = ""; }; 71241D7D1FAF084E00B9559F /* FBW3CTouchActionsIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBW3CTouchActionsIntegrationTests.m; sourceTree = ""; }; @@ -958,7 +951,6 @@ 713C6DCD1DDC772A00285B92 /* FBElementUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBElementUtils.h; sourceTree = ""; }; 713C6DCE1DDC772A00285B92 /* FBElementUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBElementUtils.m; sourceTree = ""; }; 714097411FAE1B0B008FB2C5 /* FBBaseActionsSynthesizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBBaseActionsSynthesizer.h; sourceTree = ""; }; - 714097451FAE1B32008FB2C5 /* FBAppiumActionsSynthesizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBAppiumActionsSynthesizer.h; sourceTree = ""; }; 714097491FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBW3CActionsSynthesizer.h; sourceTree = ""; }; 7140974A1FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBW3CActionsSynthesizer.m; sourceTree = ""; }; 7140974D1FAE20EE008FB2C5 /* FBBaseActionsSynthesizer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBBaseActionsSynthesizer.m; sourceTree = ""; }; @@ -1018,7 +1010,6 @@ 71930C4020662E1F00D3AFEC /* FBPasteboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBPasteboard.h; sourceTree = ""; }; 71930C4120662E1F00D3AFEC /* FBPasteboard.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBPasteboard.m; sourceTree = ""; }; 71930C462066434000D3AFEC /* FBPasteboardTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBPasteboardTests.m; sourceTree = ""; }; - 719A97AB1F88E7370063B4BD /* FBAppiumMultiTouchActionsIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAppiumMultiTouchActionsIntegrationTests.m; sourceTree = ""; }; 719CD8F62126C78F00C7D0C2 /* FBAlertsMonitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBAlertsMonitor.h; sourceTree = ""; }; 719CD8F72126C78F00C7D0C2 /* FBAlertsMonitor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAlertsMonitor.m; sourceTree = ""; }; 719CD8FA2126C88B00C7D0C2 /* XCUIApplication+FBAlert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIApplication+FBAlert.h"; sourceTree = ""; }; @@ -1046,7 +1037,6 @@ 71B49EC61ED1A58100D51AD6 /* XCUIElement+FBUID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBUID.m"; sourceTree = ""; }; 71BD20711F86116100B36EC2 /* XCUIApplication+FBTouchAction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIApplication+FBTouchAction.h"; sourceTree = ""; }; 71BD20721F86116100B36EC2 /* XCUIApplication+FBTouchAction.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIApplication+FBTouchAction.m"; sourceTree = ""; }; - 71BD20771F869E0F00B36EC2 /* FBAppiumTouchActionsIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAppiumTouchActionsIntegrationTests.m; sourceTree = ""; }; 71C8E54F25399A6B008572C1 /* XCUIApplication+FBQuiescence.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIApplication+FBQuiescence.h"; sourceTree = ""; }; 71C8E55025399A6B008572C1 /* XCUIApplication+FBQuiescence.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIApplication+FBQuiescence.m"; sourceTree = ""; }; 71C9EAAA25E8415A00470CD8 /* FBScreenshot.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBScreenshot.h; sourceTree = ""; }; @@ -1866,8 +1856,6 @@ 13815F6E2328D20400CDAB61 /* FBActiveAppDetectionPoint.m */, 719CD8F62126C78F00C7D0C2 /* FBAlertsMonitor.h */, 719CD8F72126C78F00C7D0C2 /* FBAlertsMonitor.m */, - 714097451FAE1B32008FB2C5 /* FBAppiumActionsSynthesizer.h */, - 71241D771FAE31F100B9559F /* FBAppiumActionsSynthesizer.m */, 714097411FAE1B0B008FB2C5 /* FBBaseActionsSynthesizer.h */, 7140974D1FAE20EE008FB2C5 /* FBBaseActionsSynthesizer.m */, 714EAA0B2673FDFE005C5B47 /* FBCapabilities.h */, @@ -1965,8 +1953,6 @@ isa = PBXGroup; children = ( EE9B76991CF799F400275851 /* FBAlertTests.m */, - 71BD20771F869E0F00B36EC2 /* FBAppiumTouchActionsIntegrationTests.m */, - 719A97AB1F88E7370063B4BD /* FBAppiumMultiTouchActionsIntegrationTests.m */, 719CD8FE2126C90200C7D0C2 /* FBAutoAlertsHandlerTests.m */, EE26409C1D0EBA25009BE6B0 /* FBElementAttributeTests.m */, 71F5BE33252E5B2200EE9EBA /* FBElementSwipingTests.m */, @@ -2439,7 +2425,6 @@ 718226CB2587443700661B83 /* GCDAsyncUdpSocket.h in Headers */, 641EE6DB2240C5CA00173FCB /* FBPasteboard.h in Headers */, 711CD03525ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h in Headers */, - 641EE6DC2240C5CA00173FCB /* FBAppiumActionsSynthesizer.h in Headers */, 641EE6DD2240C5CA00173FCB /* FBDebugLogDelegateDecorator.h in Headers */, 641EE6DE2240C5CA00173FCB /* XCUIDevice+FBHealthCheck.h in Headers */, 641EE6DF2240C5CA00173FCB /* FBMjpegServer.h in Headers */, @@ -2675,7 +2660,6 @@ EE35AD6F1E3B77D600A02D78 /* XCUIElement.h in Headers */, EE35AD2F1E3B77D600A02D78 /* XCKeyboardInputSolver.h in Headers */, 71930C4220662E1F00D3AFEC /* FBPasteboard.h in Headers */, - 714097471FAE1B32008FB2C5 /* FBAppiumActionsSynthesizer.h in Headers */, EE7E271C1D06C69F001BEC7B /* FBDebugLogDelegateDecorator.h in Headers */, EEDFE1211D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h in Headers */, 7155D703211DCEF400166C20 /* FBMjpegServer.h in Headers */, @@ -3066,7 +3050,6 @@ 641EE5DB2240C5CA00173FCB /* FBXPath.m in Sources */, 71C8E55425399A6B008572C1 /* XCUIApplication+FBQuiescence.m in Sources */, 641EE5DC2240C5CA00173FCB /* XCUIApplication+FBAlert.m in Sources */, - 641EE5DD2240C5CA00173FCB /* FBAppiumActionsSynthesizer.m in Sources */, 641EE70F2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */, 714D88CF2733FB970074A925 /* FBXMLGenerationOptions.m in Sources */, 641EE5DE2240C5CA00173FCB /* XCUIApplication+FBTouchAction.m in Sources */, @@ -3180,7 +3163,6 @@ 711084451DA3AA7500F913D6 /* FBXPath.m in Sources */, 719CD8FD2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m in Sources */, 13DE7A45287C2A8D003243C6 /* FBXCAccessibilityElement.m in Sources */, - 71241D781FAE31F100B9559F /* FBAppiumActionsSynthesizer.m in Sources */, 641EE70E2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */, 71BD20741F86116100B36EC2 /* XCUIApplication+FBTouchAction.m in Sources */, EE158AE71CBD456F00A3E3F0 /* FBWebServer.m in Sources */, @@ -3298,8 +3280,6 @@ 63FD950221F9D06100A3E356 /* FBImageProcessorTests.m in Sources */, 719CD8FF2126C90200C7D0C2 /* FBAutoAlertsHandlerTests.m in Sources */, EE2202131ECC612200A29571 /* FBIntegrationTestCase.m in Sources */, - 71BD20781F869E0F00B36EC2 /* FBAppiumTouchActionsIntegrationTests.m in Sources */, - 719A97AC1F88E7370063B4BD /* FBAppiumMultiTouchActionsIntegrationTests.m in Sources */, 715AFAC41FFA2AAF0053896D /* FBScreenTests.m in Sources */, EE22021E1ECC618900A29571 /* FBTapTest.m in Sources */, 71930C472066434000D3AFEC /* FBPasteboardTests.m in Sources */, diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h b/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h index 5ab5e357c..6be298b49 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h @@ -15,43 +15,6 @@ NS_ASSUME_NONNULL_BEGIN @interface XCUIApplication (FBTouchAction) -/** - Perform complex touch action in scope of the current application. - Touch actions are represented as lists of dictionaries with predefined sets of values and keys. - Each dictionary must contain 'action' key, which is one of the following: - - 'tap' to perform a single tap - - 'longPress' to perform long tap - - 'press' to perform press - - 'release' to release the finger - - 'moveTo' to move the virtual finger - - 'wait' to modify the duration of the preceeding action - - 'cancel' to cancel the preceeding action in the chain - Each dictionary can also contain 'options' key with additional parameters dictionary related to the appropriate action. - - The following options are mandatory for 'tap', 'longPress', 'press' and 'moveTo' actions: - - 'x' the X coordinate of the action - - 'y' the Y coordinate of the action - - 'element' the corresponding element instance, for which the action is going to be performed - If only 'element' is set then hit point coordinates of this element will be used. - If only 'x' and 'y' are set then these will be considered as absolute coordinates. - If both 'element' and 'x'/'y' are set then these will act as relative element coordinates. - - It is also mandatory, that 'release' and 'wait' actions are preceeded with at least one chain item, which contains absolute coordinates, like 'tap', 'press' or 'longPress'. Empty chains are not allowed. - - The following additional options are available for different actions: - - 'tap': 'count' (defines count of taps to be performed in a row; 1 by default) - - 'longPress': 'duration' (number of milliseconds to hold/move the virtual finger; 500.0 ms by default) - - 'wait': 'ms' (number of milliseconds to wait for the preceeding action; 0.0 ms by default) - - List of lists can be passed there is order to perform multi-finger touch action. Each single actions chain is going to be executed by a separate virtual finger in such case. - - @param actions Either array of dictionaries, whose format is described above to peform single-finger touch action or array of array to perform multi-finger touch action. - @param elementCache Cached elements mapping for the currrent application. The method assumes all elements are already represented by their actual instances if nil value is set - @param error If there is an error, upon return contains an NSError object that describes the problem - @return YES If the touch action has been successfully performed without errors - */ -- (BOOL)fb_performAppiumTouchActions:(NSArray *)actions elementCache:(nullable FBElementCache *)elementCache error:(NSError * _Nullable*)error; - /** Perform complex touch action in scope of the current application. diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m b/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m index 703a0096d..622dac479 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m @@ -10,7 +10,6 @@ #import "XCUIApplication+FBTouchAction.h" -#import "FBAppiumActionsSynthesizer.h" #import "FBBaseActionsSynthesizer.h" #import "FBConfiguration.h" #import "FBExceptions.h" @@ -54,20 +53,6 @@ - (BOOL)fb_performActionsWithSynthesizerType:(Class)synthesizerType return [self fb_synthesizeEvent:eventRecord error:error]; } -- (BOOL)fb_performAppiumTouchActions:(NSArray *)actions - elementCache:(FBElementCache *)elementCache - error:(NSError **)error -{ - if (![self fb_performActionsWithSynthesizerType:FBAppiumActionsSynthesizer.class - actions:actions - elementCache:elementCache - error:error]) { - return NO; - } - [self fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; - return YES; -} - - (BOOL)fb_performW3CActions:(NSArray *)actions elementCache:(FBElementCache *)elementCache error:(NSError **)error diff --git a/WebDriverAgentLib/Commands/FBTouchActionCommands.m b/WebDriverAgentLib/Commands/FBTouchActionCommands.m index 3e31ddf2e..c14edcb63 100644 --- a/WebDriverAgentLib/Commands/FBTouchActionCommands.m +++ b/WebDriverAgentLib/Commands/FBTouchActionCommands.m @@ -22,25 +22,12 @@ + (NSArray *)routes { return @[ - [[FBRoute POST:@"/wda/touch/perform"] respondWithTarget:self action:@selector(handlePerformAppiumTouchActions:)], - [[FBRoute POST:@"/wda/touch/multi/perform"] respondWithTarget:self action:@selector(handlePerformAppiumTouchActions:)], [[FBRoute POST:@"/actions"] respondWithTarget:self action:@selector(handlePerformW3CTouchActions:)], ]; } #pragma mark - Commands -+ (id)handlePerformAppiumTouchActions:(FBRouteRequest *)request -{ - XCUIApplication *application = request.session.activeApplication; - NSArray *actions = (NSArray *)request.arguments[@"actions"]; - NSError *error; - if (![application fb_performAppiumTouchActions:actions elementCache:request.session.elementCache error:&error]) { - return FBResponseWithUnknownError(error); - } - return FBResponseWithOK(); -} - + (id)handlePerformW3CTouchActions:(FBRouteRequest *)request { XCUIApplication *application = request.session.activeApplication; diff --git a/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.h b/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.h deleted file mode 100644 index 090bacdd7..000000000 --- a/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.h +++ /dev/null @@ -1,20 +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 "FBBaseActionsSynthesizer.h" - -NS_ASSUME_NONNULL_BEGIN - -#if !TARGET_OS_TV -@interface FBAppiumActionsSynthesizer : FBBaseActionsSynthesizer - -@end -#endif - -NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m deleted file mode 100644 index 235d97e63..000000000 --- a/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m +++ /dev/null @@ -1,554 +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 "FBAppiumActionsSynthesizer.h" - -#import "FBErrorBuilder.h" -#import "FBElementCache.h" -#import "FBLogger.h" -#import "FBMacros.h" -#import "FBMathUtils.h" -#import "FBXCTestDaemonsProxy.h" -#import "FBProtocolHelpers.h" -#import "XCUIElement+FBUtilities.h" -#import "XCUIElement.h" -#import "XCSynthesizedEventRecord.h" -#import "XCPointerEventPath.h" -#import "XCPointerEvent.h" - -static NSString *const FB_ACTION_KEY = @"action"; -static NSString *const FB_ACTION_TAP = @"tap"; -static NSString *const FB_ACTION_PRESS = @"press"; -static NSString *const FB_ACTION_LONG_PRESS = @"longPress"; -static NSString *const FB_ACTION_MOVE_TO = @"moveTo"; -static NSString *const FB_ACTION_RELEASE = @"release"; -static NSString *const FB_ACTION_CANCEL = @"cancel"; -static NSString *const FB_ACTION_WAIT = @"wait"; - -static NSString *const FB_OPTION_DURATION = @"duration"; -static NSString *const FB_OPTION_COUNT = @"count"; -static NSString *const FB_OPTION_MS = @"ms"; -static NSString *const FB_OPTION_PRESSURE = @"pressure"; - -static NSString *const FB_OPTIONS_KEY = @"options"; - -#if !TARGET_OS_TV -// Some useful constants might be found at -// https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/ViewConfiguration.java -static const double FB_TAP_DURATION_MS = 100.0; -static const double FB_INTERTAP_MIN_DURATION_MS = 40.0; -static const double FB_LONG_TAP_DURATION_MS = 600.0; - -@interface FBAppiumGestureItem : FBBaseGestureItem - -@end - -@interface FBTapItem : FBAppiumGestureItem - -@end - -@interface FBPressItem : FBAppiumGestureItem -@property (nonatomic, nullable, readonly) NSNumber *pressure; -@end - -@interface FBLongPressItem : FBAppiumGestureItem - -@end - -@interface FBWaitItem : FBAppiumGestureItem - -@end - -@interface FBMoveToItem : FBAppiumGestureItem - -@property (nonatomic, nonnull) NSValue *recentPosition; - -@end - -@interface FBReleaseItem : FBAppiumGestureItem - -@end - - -@implementation FBAppiumGestureItem - -- (nullable instancetype)initWithActionItem:(NSDictionary *)item - application:(XCUIApplication *)application - atPosition:(nullable XCUICoordinate *)atPosition - offset:(double)offset - error:(NSError **)error -{ - self = [super init]; - if (self) { - self.actionItem = item; - self.application = application; - self.offset = offset; - id options = [item objectForKey:FB_OPTIONS_KEY]; - if (nil != atPosition) { - self.atPosition = (id) atPosition; - } else { - XCUICoordinate *result = [self coordinatesWithOptions:options error:error]; - if (nil == result) { - return nil; - } - self.atPosition = result; - } - self.duration = [self durationWithOptions:options]; - if (self.duration < 0) { - NSString *description = [NSString stringWithFormat:@"%@ value cannot be negative for '%@' action", FB_OPTION_DURATION, self.class.actionName]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - } - return self; -} - -+ (BOOL)hasAbsolutePositioning -{ - @throw [[FBErrorBuilder.builder withDescription:@"Override this method in subclasses"] build]; - return NO; -} - -- (double)durationWithOptions:(nullable NSDictionary *)options -{ - return (options && [options objectForKey:FB_OPTION_DURATION]) ? - ((NSNumber *)[options objectForKey:FB_OPTION_DURATION]).doubleValue : - 0.0; -} - -- (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]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - XCUIElement *element = FBExtractElement((id) options); - NSNumber *x = [options objectForKey:@"x"]; - NSNumber *y = [options objectForKey:@"y"]; - if ((nil != x && nil == y) || (nil != y && nil == x) || (nil == x && nil == y && nil == element)) { - NSString *description = [NSString stringWithFormat:@"Either element or 'x' and 'y' options should be set for '%@' action", self.class.actionName]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - NSValue *offset = (nil != x && nil != y) ? [NSValue valueWithCGPoint:CGPointMake(x.floatValue, y.floatValue)] : nil; - return [self hitpointWithElement:element positionOffset:offset error:error]; -} - -@end - -@implementation FBTapItem - -+ (NSString *)actionName -{ - return FB_ACTION_TAP; -} - -+ (BOOL)hasAbsolutePositioning -{ - return YES; -} - -- (NSArray *)addToEventPath:(XCPointerEventPath *)eventPath - allItems:(NSArray *)allItems - currentItemIndex:(NSUInteger)currentItemIndex - error:(NSError **)error -{ - NSTimeInterval currentOffset = FBMillisToSeconds(self.offset); - NSMutableArray *result = [NSMutableArray array]; - XCPointerEventPath *currentPath = [[XCPointerEventPath alloc] - initForTouchAtPoint:self.atPosition.screenPoint - offset:currentOffset]; - [result addObject:currentPath]; - currentOffset += FBMillisToSeconds(FB_TAP_DURATION_MS); - [currentPath liftUpAtOffset:currentOffset]; - - id options = [self.actionItem objectForKey:FB_OPTIONS_KEY]; - if ([options isKindOfClass:NSDictionary.class]) { - 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.screenPoint - offset:currentOffset]; - [result addObject:nextPath]; - currentOffset += FBMillisToSeconds(FB_TAP_DURATION_MS); - [nextPath liftUpAtOffset:currentOffset]; - } - } - return result.copy; -} - -- (double)durationWithOptions:(nullable NSDictionary *)options -{ - NSNumber *tapCount = @1; - if ([options isKindOfClass:NSDictionary.class]) { - tapCount = [options objectForKey:FB_OPTION_COUNT] ?: tapCount; - } - return FB_TAP_DURATION_MS * tapCount.integerValue + FB_INTERTAP_MIN_DURATION_MS * (tapCount.integerValue - 1); -} - -@end - -@implementation FBPressItem - -- (nullable instancetype)initWithActionItem:(NSDictionary *)item - application:(XCUIApplication *)application - atPosition:(nullable XCUICoordinate *)atPosition - offset:(double)offset - error:(NSError **)error -{ - self = [super initWithActionItem:item - application:application - atPosition:atPosition - offset:offset - error:error]; - if (self) { - _pressure = nil; - id options = [item objectForKey:FB_OPTIONS_KEY]; - if ([options isKindOfClass:NSDictionary.class]) { - _pressure = [options objectForKey:FB_OPTION_PRESSURE]; - } - } - return self; -} - -+ (NSString *)actionName -{ - return FB_ACTION_PRESS; -} - -+ (BOOL)hasAbsolutePositioning -{ - return YES; -} - -- (NSArray *)addToEventPath:(XCPointerEventPath *)eventPath - allItems:(NSArray *)allItems - currentItemIndex:(NSUInteger)currentItemIndex - error:(NSError **)error -{ - XCPointerEventPath *result = [[XCPointerEventPath alloc] - initForTouchAtPoint:self.atPosition.screenPoint - offset:FBMillisToSeconds(self.offset)]; - if (nil != self.pressure && nil != result.pointerEvents.lastObject) { - XCPointerEvent *pointerEvent = (XCPointerEvent *)result.pointerEvents.lastObject; - pointerEvent.pressure = self.pressure.doubleValue; - } - return @[result]; -} - -- (double)durationWithOptions:(nullable NSDictionary *)options -{ - return 0.0; -} - -@end - -@implementation FBLongPressItem - -+ (NSString *)actionName -{ - return FB_ACTION_LONG_PRESS; -} - -+ (BOOL)hasAbsolutePositioning -{ - return YES; -} - -- (NSArray *)addToEventPath:(XCPointerEventPath *)eventPath - allItems:(NSArray *)allItems - currentItemIndex:(NSUInteger)currentItemIndex - error:(NSError **)error -{ - return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint - offset:FBMillisToSeconds(self.offset)]]; -} - -- (double)durationWithOptions:(nullable NSDictionary *)options -{ - return (options && [options objectForKey:FB_OPTION_DURATION]) ? - ((NSNumber *)[options objectForKey:FB_OPTION_DURATION]).doubleValue : - FB_LONG_TAP_DURATION_MS; -} - -@end - -@implementation FBWaitItem - -+ (NSString *)actionName -{ - return FB_ACTION_WAIT; -} - -+ (BOOL)hasAbsolutePositioning -{ - return NO; -} - -- (NSArray *)addToEventPath:(XCPointerEventPath *)eventPath - allItems:(NSArray *)allItems - currentItemIndex:(NSUInteger)currentItemIndex - error:(NSError **)error -{ - if (nil != eventPath) { - if (0 == currentItemIndex) { - return @[]; - } - FBBaseGestureItem *preceedingItem = [allItems objectAtIndex:currentItemIndex - 1]; - if (![preceedingItem isKindOfClass:FBReleaseItem.class] && currentItemIndex < allItems.count - 1) { - return @[]; - } - } - NSTimeInterval currentOffset = FBMillisToSeconds(self.offset + self.duration); - XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint - offset:currentOffset]; - if (currentItemIndex == allItems.count - 1) { - [result liftUpAtOffset:currentOffset]; - } - return @[result]; -} - -- (double)durationWithOptions:(nullable NSDictionary *)options -{ - return (options && [options objectForKey:FB_OPTION_MS]) ? - ((NSNumber *)[options objectForKey:FB_OPTION_MS]).doubleValue : - 0.0; -} - -@end - -@implementation FBMoveToItem - -+ (NSString *)actionName -{ - return FB_ACTION_MOVE_TO; -} - -+ (BOOL)hasAbsolutePositioning -{ - return YES; -} - -- (NSArray *)addToEventPath:(XCPointerEventPath *)eventPath - allItems:(NSArray *)allItems - currentItemIndex:(NSUInteger)currentItemIndex - error:(NSError **)error -{ - if (nil == eventPath) { - NSString *description = [NSString stringWithFormat:@"Move To must not be the first action in '%@'", self.actionItem]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - - [eventPath moveToPoint:self.atPosition.screenPoint - atOffset:FBMillisToSeconds(self.offset)]; - return @[]; -} - -@end - -@implementation FBReleaseItem - -+ (NSString *)actionName -{ - return FB_ACTION_RELEASE; -} - -+ (BOOL)hasAbsolutePositioning -{ - return NO; -} - -- (NSArray *)addToEventPath:(XCPointerEventPath *)eventPath - allItems:(NSArray *)allItems - currentItemIndex:(NSUInteger)currentItemIndex - error:(NSError **)error -{ - if (nil == eventPath) { - NSString *description = [NSString stringWithFormat:@"Pointer Up must not be the first action in '%@'", self.actionItem]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - - [eventPath liftUpAtOffset:FBMillisToSeconds(self.offset)]; - return @[]; -} - -- (double)durationWithOptions:(nullable NSDictionary *)options -{ - return 0.0; -} - -@end - - -@interface FBAppiumGestureItemsChain : FBBaseActionItemsChain - -@end - -@implementation FBAppiumGestureItemsChain - -- (void)addItem:(FBBaseActionItem *)item -{ - self.durationOffset += ((FBAppiumGestureItem *) item).duration; - [self.items addObject:item]; -} - -- (void)reset -{ - [self.items removeAllObjects]; - self.durationOffset = 0.0; -} - -@end - -@implementation FBAppiumActionsSynthesizer - -- (NSArray *> *)preprocessAction:(NSArray *> *)touchActionItems -{ - NSMutableArray *> *result = [NSMutableArray array]; - BOOL shouldSkipNextItem = NO; - for (NSDictionary *touchItem in [touchActionItems reverseObjectEnumerator]) { - id actionItemName = [touchItem objectForKey:FB_ACTION_KEY]; - if ([actionItemName isKindOfClass:NSString.class] && [actionItemName isEqualToString:FB_ACTION_CANCEL]) { - shouldSkipNextItem = YES; - continue; - } - if (shouldSkipNextItem) { - shouldSkipNextItem = NO; - continue; - } - - id options = [touchItem objectForKey:FB_OPTIONS_KEY]; - if (![options isKindOfClass:NSDictionary.class]) { - [result addObject:touchItem]; - continue; - } - id origin = FBExtractElement(options); - XCUIElement *element; - if ([origin isKindOfClass:XCUIElement.class]) { - element = origin; - } else if ([origin isKindOfClass:NSString.class]) { - element = [self.elementCache elementForUUID:(NSString *)origin]; - } else { - [result addObject:touchItem]; - continue; - } - NSMutableDictionary *elementDict = FBCleanupElements(options).mutableCopy; - [elementDict addEntriesFromDictionary:FBToElementDict(element)]; - NSMutableDictionary *processedItem = touchItem.mutableCopy; - processedItem[FB_OPTIONS_KEY] = elementDict.copy; - [result addObject:processedItem.copy]; - } - return [[result reverseObjectEnumerator] allObjects]; -} - -- (nullable NSArray *)eventPathsWithAction:(NSArray *> *)action - error:(NSError **)error -{ - static NSDictionary *gestureItemsMapping; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - NSMutableDictionary *itemsMapping = [NSMutableDictionary dictionary]; - for (Class cls in @[FBTapItem.class, - FBPressItem.class, - FBLongPressItem.class, - FBMoveToItem.class, - FBWaitItem.class, - FBReleaseItem.class]) { - [itemsMapping setObject:cls forKey:[cls actionName]]; - } - gestureItemsMapping = itemsMapping.copy; - }); - - FBAppiumGestureItemsChain *chain = [[FBAppiumGestureItemsChain alloc] init]; - BOOL isAbsoluteTouchPositionSet = NO; - for (NSDictionary *actionItem in action) { - id actionItemName = [actionItem objectForKey:FB_ACTION_KEY]; - if (![actionItemName isKindOfClass:NSString.class]) { - NSString *description = [NSString stringWithFormat:@"'%@' property is mandatory for gesture chain item %@", FB_ACTION_KEY, actionItem]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - - Class gestureItemClass = [gestureItemsMapping objectForKey:actionItemName]; - if (nil == gestureItemClass) { - NSString *description = [NSString stringWithFormat:@"%@ value '%@' is unknown", FB_ACTION_KEY, actionItemName]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - - FBAppiumGestureItem *gestureItem = nil; - if ([gestureItemClass hasAbsolutePositioning]) { - gestureItem = [[gestureItemClass alloc] initWithActionItem:actionItem application:self.application atPosition:nil offset:chain.durationOffset error:error]; - isAbsoluteTouchPositionSet = YES; - } else { - if (!isAbsoluteTouchPositionSet) { - if (error) { - NSString *description = [NSString stringWithFormat:@"'%@' %@ should be preceded by an item with absolute positioning", actionItemName, FB_ACTION_KEY]; - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - FBAppiumGestureItem *lastItem = [chain.items lastObject]; - gestureItem = [[gestureItemClass alloc] initWithActionItem:actionItem - application:self.application - atPosition:lastItem.atPosition - offset:chain.durationOffset - error:error]; - } - if (nil == gestureItem) { - return nil; - } - - [chain addItem:gestureItem]; - } - - return [chain asEventPathsWithError:error]; -} - -- (nullable XCSynthesizedEventRecord *)synthesizeWithError:(NSError **)error -{ - XCSynthesizedEventRecord *eventRecord; - BOOL isMultiTouch = [self.actions.firstObject isKindOfClass:NSArray.class]; - eventRecord = [[XCSynthesizedEventRecord alloc] - initWithName:(isMultiTouch ? @"Multi-Finger Touch Action" : @"Single-Finger Touch Action") - 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]; - if (nil == eventPaths) { - return nil; - } - for (XCPointerEventPath *eventPath in eventPaths) { - [eventRecord addPointerEventPath:eventPath]; - } - } - return eventRecord; -} - -@end - -#endif diff --git a/WebDriverAgentTests/IntegrationTests/FBAppiumMultiTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBAppiumMultiTouchActionsIntegrationTests.m deleted file mode 100644 index 9b767c67a..000000000 --- a/WebDriverAgentTests/IntegrationTests/FBAppiumMultiTouchActionsIntegrationTests.m +++ /dev/null @@ -1,206 +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 "FBIntegrationTestCase.h" - -#import "FBMacros.h" -#import "XCUIElement.h" -#import "XCUIApplication+FBTouchAction.h" -#import "FBTestMacros.h" -#import "XCUIDevice+FBRotation.h" -#import "FBRunLoopSpinner.h" - -@interface FBAppiumMultiTouchActionsIntegrationTestsPart1 : FBIntegrationTestCase -@end - -@interface FBAppiumMultiTouchActionsIntegrationTestsPart2 : FBIntegrationTestCase -@property (nonatomic) XCUIElement *touchesLabel; -@property (nonatomic) XCUIElement *tapsLabel; -@end - -@implementation FBAppiumMultiTouchActionsIntegrationTestsPart1 - -- (void)verifyGesture:(NSArray *> *> *)gesture orientation:(UIDeviceOrientation)orientation -{ - [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation]; - NSError *error; - XCTAssertTrue([self.testedApplication fb_performAppiumTouchActions:gesture elementCache:nil error:&error]); - FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0); -} - -- (void)setUp -{ - [super setUp]; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self launchApplication]; - [self goToAlertsPage]; - }); - [self clearAlert]; -} - -- (void)tearDown -{ - [self clearAlert]; - [self resetOrientation]; - [super tearDown]; -} - -- (void)testErroneousGestures -{ - NSArray *> *> *invalidGestures = - @[ - // One of the chains is empty - @[ - @[], - @[@{@"action": @"tap", - @"options": @{ - @"ELEMENT": self.testedApplication.buttons[FBShowAlertButtonName], - } - } - ], - ], - - ]; - - for (NSArray *> *> *invalidGesture in invalidGestures) { - NSError *error; - XCTAssertFalse([self.testedApplication fb_performAppiumTouchActions:invalidGesture elementCache:nil error:&error]); - XCTAssertNotNil(error); - } -} - -- (void)testSymmetricTwoFingersTap -{ - XCUIElement *element = self.testedApplication.buttons[FBShowAlertButtonName]; - NSArray *> *> *gesture = - @[ - @[@{ - @"action": @"tap", - @"options": @{ - @"ELEMENT": element - } - } - ], - @[@{ - @"action": @"tap", - @"options": @{ - @"ELEMENT": element - } - } - ], - ]; - - [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait]; -} - -@end - -@implementation FBAppiumMultiTouchActionsIntegrationTestsPart2 - -- (void)verifyGesture:(NSArray *>*>*)gesture orientation:(UIDeviceOrientation)orientation tapsCount:(int)tapsCount touchesCount:(int)touchesCount -{ - [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation]; - NSError *error; - XCTAssertTrue([self.testedApplication fb_performAppiumTouchActions:gesture elementCache:nil error:&error]); - NSString *taps = [[self tapsLabel] label]; - NSString *touches = [[self touchesLabel] label] ; - BOOL tapsEqual = [[NSString stringWithFormat:@"%d", tapsCount] isEqualToString:taps]; - BOOL touchesEqual = [[NSString stringWithFormat:@"%d", touchesCount] isEqualToString:touches]; - XCTAssertTrue(tapsEqual); - XCTAssertTrue(touchesEqual); -} - -- (void)setUp -{ - [super setUp]; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self launchApplication]; - [self goToTouchPage]; - }); - self.touchesLabel = self.testedApplication.staticTexts[FBTouchesCountLabelIdentifier]; - self.tapsLabel = self.testedApplication.staticTexts[FBTapsCountLabelIdentifier]; -} - -- (void)testMultiTouchWithMultiTaps -{ - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) { - // Does not work on iOS 15. - // It tapped two times, but one was touch count was one. Not two finguer taps. - return; - } - - XCUIElement *touchableView = self.testedApplication.otherElements[@"touchableView"]; - XCTAssertNotNil(touchableView); - NSArray *>*> *gesture = - @[@[@{ - @"action": @"tap", - @"options": @{ - @"ELEMENT": touchableView - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @1000 - } - }, - @{ - @"action": @"tap", - @"options": @{ - @"ELEMENT": touchableView - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @1000 - } - }, - @{ - @"action": @"release" - } - ], - @[@{ - @"action": @"tap", - @"options": @{ - @"ELEMENT": touchableView - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @1000 - } - }, - @{ - @"action": @"tap", - @"options": @{ - @"ELEMENT": touchableView - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @1000 - } - }, - @{ - @"action": @"release" - } - ] - - ]; - [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait tapsCount:2 touchesCount:2]; -} - -@end diff --git a/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m deleted file mode 100644 index 51525e435..000000000 --- a/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m +++ /dev/null @@ -1,404 +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 "FBIntegrationTestCase.h" - -#import "XCUIElement.h" -#import "XCUIApplication+FBTouchAction.h" -#import "FBTestMacros.h" -#import "XCUIDevice+FBRotation.h" -#import "FBRunLoopSpinner.h" -#import "FBXCodeCompatibility.h" - -@interface FBAppiumTouchActionsIntegrationTestsPart1 : FBIntegrationTestCase -@end - -@interface FBAppiumTouchActionsIntegrationTestsPart2 : FBIntegrationTestCase -@property (nonatomic) XCUIElement *pickerWheel; -@end - - -@implementation FBAppiumTouchActionsIntegrationTestsPart1 - -- (void)verifyGesture:(NSArray *> *)gesture orientation:(UIDeviceOrientation)orientation -{ - [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation]; - NSError *error; - XCTAssertTrue([self.testedApplication fb_performAppiumTouchActions:gesture elementCache:nil error:&error]); - FBAssertWaitTillBecomesTrue(self.testedApplication.alerts.count > 0); -} - -- (void)setUp -{ - [super setUp]; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self launchApplication]; - [self goToAlertsPage]; - }); - [self clearAlert]; -} - -- (void)tearDown -{ - [self clearAlert]; - [self resetOrientation]; - [super tearDown]; -} - -- (void)testErroneousGestures -{ - XCUIElement *dstButton = self.testedApplication.buttons[FBShowAlertButtonName]; - - NSArray *> *> *invalidGestures = - @[ - // Empty chain - @[], - - // Chain element without 'action' key - @[@{ - @"options": @{ - @"ms": @100 - } - }, - ], - - // Empty chain because of cancel - @[@{ - @"action": @"moveTo", - @"options": @{ - @"ELEMENT": dstButton, - } - }, - @{ - @"action": @"cancel" - }, - ], - - // Chain with unknown action - @[@{ - @"action": @"tapP", - @"options": @{ - @"ELEMENT": dstButton, - } - }, - ], - - // Wait without preceeding coordinate - @[@{ - @"action": @"wait" - } - ], - - // Wait with negative duration - @[@{ - @"action": @"press", - @"options": @{ - @"x": @1, - @"y": @1 - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @-1.0 - } - }, - ], - - // Release without preceeding coordinate - @[@{ - @"action": @"release" - }, - @{ - @"action": @"tap", - @"options": @{ - @"x": @1, - @"y": @1 - } - }, - ], - - // Press without coordinates - @[@{ - @"action": @"press" - } - ], - - // longPress with invalid coordinates - @[@{ - @"action": @"longPress", - @"options": @{ - @"x": @1 - } - }, - ], - - // longPress with negative duration - @[@{ - @"action": @"longPress", - @"options": @{ - @"x": @1, - @"y": @1, - @"duration": @-0.01 - } - }, - ], - - ]; - - for (NSArray *> *invalidGesture in invalidGestures) { - NSError *error; - XCTAssertFalse([self.testedApplication fb_performAppiumTouchActions:invalidGesture elementCache:nil error:&error]); - XCTAssertNotNil(error); - } -} - -- (void)testTap -{ - NSArray *> *gesture = - @[@{ - @"action": @"tap", - @"options": @{ - @"ELEMENT": self.testedApplication.buttons[FBShowAlertButtonName] - } - } - ]; - [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait]; -} - -- (void)testTapByCoordinates -{ - CGRect elementRect = self.testedApplication.buttons[FBShowAlertButtonName].frame; - CGFloat x = elementRect.origin.x + elementRect.size.width / 2; - CGFloat y = elementRect.origin.y + elementRect.size.height / 2; - NSArray *> *gesture = - @[@{ - @"action": @"tap", - @"options": @{ - @"x": @(x), - @"y": @(y) - } - } - ]; - [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait]; -} - -- (void)testDoubleTap -{ - NSArray *> *gesture = - @[@{ - @"action": @"tap", - @"options": @{ - @"ELEMENT": self.testedApplication.buttons[FBShowAlertButtonName], - @"count": @2 - } - }, - ]; - [self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft]; -} - -- (void)testPress -{ - NSArray *> *gesture = - @[@{ - @"action": @"press", - @"options": @{ - @"ELEMENT": self.testedApplication.buttons[FBShowAlertButtonName], - @"x": @1, - @"y": @1 - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @300 - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @300 - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @300 - } - }, - @{ - @"action": @"release" - } - ]; - [self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeRight]; -} - -- (void)testLongPress -{ - if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { - XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); - } - UIDeviceOrientation orientation = UIDeviceOrientationLandscapeLeft; - [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:orientation]; - CGRect elementFrame = self.testedApplication.buttons[FBShowAlertButtonName].frame; - NSArray *> *gesture = - @[@{ - @"action": @"longPress", - @"options": @{ - @"x": @(elementFrame.origin.x + 1), - @"y": @(elementFrame.origin.y + 1), - @"duration": @5 - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @500 - } - }, - @{ - @"action": @"release" - } - ]; - [self verifyGesture:gesture orientation:orientation]; -} - -@end - - -@implementation FBAppiumTouchActionsIntegrationTestsPart2 - -- (void)setUp -{ - [super setUp]; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - [self launchApplication]; - [self goToAttributesPage]; - }); - self.pickerWheel = self.testedApplication.pickerWheels.allElementsBoundByIndex.firstObject; -} - -- (void)tearDown -{ - [self resetOrientation]; - [super tearDown]; -} - -- (void)verifyPickerWheelPositionChangeWithGesture:(NSArray *> *)gesture -{ - NSString *previousValue = self.pickerWheel.value; - NSError *error; - XCTAssertTrue([self.testedApplication fb_performAppiumTouchActions:gesture elementCache:nil error:&error]); - XCTAssertNil(error); - XCTAssertTrue([[[[FBRunLoopSpinner new] - timeout:2.0] - timeoutErrorMessage:@"Picker wheel value has not been changed after 2 seconds timeout"] - spinUntilTrue:^BOOL{ - return ![self.pickerWheel.fb_takeSnapshot.value isEqualToString:previousValue]; - } - error:&error]); - XCTAssertNil(error); -} - -- (void)testSwipePickerWheelWithElementCoordinates -{ - CGRect pickerFrame = self.pickerWheel.frame; - NSArray *> *gesture = - @[@{ - @"action": @"press", - @"options": @{ - @"ELEMENT": self.pickerWheel, - @"x": @(pickerFrame.size.width / 2), - @"y": @(pickerFrame.size.height / 2), - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @500, - } - }, - @{ - @"action": @"moveTo", - @"options": @{ - @"ELEMENT": self.pickerWheel, - @"x": @(pickerFrame.size.width / 2), - @"y": @(pickerFrame.size.height), - } - }, - @{ - @"action": @"release" - } - ]; - [self verifyPickerWheelPositionChangeWithGesture:gesture]; -} - -- (void)testSwipePickerWheelWithRelativeCoordinates -{ - CGRect pickerFrame = self.pickerWheel.frame; - NSArray *> *gesture = - @[@{ - @"action": @"press", - @"options": @{ - @"ELEMENT": self.pickerWheel, - @"x": @(pickerFrame.size.width / 2), - @"y": @(pickerFrame.size.height / 2), - } - }, - @{ - @"action": @"wait", - @"options": @{ - @"ms": @500, - } - }, - @{ - @"action": @"moveTo", - @"options": @{ - @"x": @(pickerFrame.origin.x / 2), - @"y": @(pickerFrame.origin.y), - } - }, - @{ - @"action": @"release" - } - ]; - [self verifyPickerWheelPositionChangeWithGesture:gesture]; -} - -- (void)testSwipePickerWheelWithAbsoluteCoordinates -{ - CGRect pickerFrame = self.pickerWheel.frame; - NSArray *> *gesture = - @[@{ - @"action": @"longPress", - @"options": @{ - @"x": @(pickerFrame.origin.x + pickerFrame.size.width / 2), - @"y": @(pickerFrame.origin.y + pickerFrame.size.height / 2), - } - }, - @{ - @"action": @"moveTo", - @"options": @{ - @"x": @(pickerFrame.origin.x + pickerFrame.size.width / 2), - @"y": @(pickerFrame.origin.y + pickerFrame.size.height), - } - }, - @{ - @"action": @"release" - } - ]; - [self verifyPickerWheelPositionChangeWithGesture:gesture]; -} - -@end - From 77aeef7eec47a5bb4911b6a53d991d533c2b8b9e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 12 Feb 2024 20:02:55 +0000 Subject: [PATCH 017/368] chore(release): 7.0.0 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [7.0.0](https://github.com/appium/WebDriverAgent/compare/v6.1.1...v7.0.0) (2024-02-12) ### ⚠ BREAKING CHANGES * The following REST endpoints have been removed, use W3C actions instead: - /wda/touch/perform - /wda/touch/multi/perform ### Features * Remove obsolete MJSONWP touch actions ([#847](https://github.com/appium/WebDriverAgent/issues/847)) ([d77f640](https://github.com/appium/WebDriverAgent/commit/d77f640867155fddbbbc9575f0a77802602865e7)) --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae9968eeb..d5321867b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [7.0.0](https://github.com/appium/WebDriverAgent/compare/v6.1.1...v7.0.0) (2024-02-12) + + +### ⚠ BREAKING CHANGES + +* The following REST endpoints have been removed, use W3C actions instead: +- /wda/touch/perform +- /wda/touch/multi/perform + +### Features + +* Remove obsolete MJSONWP touch actions ([#847](https://github.com/appium/WebDriverAgent/issues/847)) ([d77f640](https://github.com/appium/WebDriverAgent/commit/d77f640867155fddbbbc9575f0a77802602865e7)) + ## [6.1.1](https://github.com/appium/WebDriverAgent/compare/v6.1.0...v6.1.1) (2024-02-11) diff --git a/package.json b/package.json index c4f3cda47..928745924 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "6.1.1", + "version": "7.0.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 54f91f198e45535ea9d86b7eee40b21f43f84294 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 21 Feb 2024 18:21:16 +0100 Subject: [PATCH 018/368] chore: Simplify the logic of alert element detection (#851) --- WebDriverAgentLib/FBAlert.m | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/WebDriverAgentLib/FBAlert.m b/WebDriverAgentLib/FBAlert.m index 0709e5f1f..cd71663dd 100644 --- a/WebDriverAgentLib/FBAlert.m +++ b/WebDriverAgentLib/FBAlert.m @@ -261,16 +261,7 @@ - (BOOL)clickAlertButton:(NSString *)label error:(NSError **)error - (XCUIElement *)alertElement { if (nil == self.element) { - self.element = self.application.fb_alertElement; - if (nil == self.element) { - XCUIApplication *systemApp = XCUIApplication.fb_systemApplication; - for (XCUIApplication *activeApp in XCUIApplication.fb_activeApplications) { - if (systemApp.processID == activeApp.processID) { - self.element = activeApp.fb_alertElement; - break; - } - } - } + self.element = XCUIApplication.fb_systemApplication.fb_alertElement ?: self.application.fb_alertElement; } return self.element; } From 878b62a4c7441d0dd883c5272ba83f86524a6122 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 21 Feb 2024 17:26:33 +0000 Subject: [PATCH 019/368] chore(release): 7.0.1 [skip ci] ## [7.0.1](https://github.com/appium/WebDriverAgent/compare/v7.0.0...v7.0.1) (2024-02-21) ### Miscellaneous Chores * Simplify the logic of alert element detection ([#851](https://github.com/appium/WebDriverAgent/issues/851)) ([54f91f1](https://github.com/appium/WebDriverAgent/commit/54f91f198e45535ea9d86b7eee40b21f43f84294)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5321867b..998e59430 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.0.1](https://github.com/appium/WebDriverAgent/compare/v7.0.0...v7.0.1) (2024-02-21) + + +### Miscellaneous Chores + +* Simplify the logic of alert element detection ([#851](https://github.com/appium/WebDriverAgent/issues/851)) ([54f91f1](https://github.com/appium/WebDriverAgent/commit/54f91f198e45535ea9d86b7eee40b21f43f84294)) + ## [7.0.0](https://github.com/appium/WebDriverAgent/compare/v6.1.1...v7.0.0) (2024-02-12) diff --git a/package.json b/package.json index 928745924..022389e50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.0.0", + "version": "7.0.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 857d3decf497935098ba6acb61654be1da173b11 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 28 Feb 2024 19:37:14 +0100 Subject: [PATCH 020/368] chore: Tune alert detection if system app is active (#854) --- WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m | 2 +- WebDriverAgentLib/FBAlert.m | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 251fb7ad9..c3c99e6f5 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -533,7 +533,7 @@ - (BOOL)fb_isSameAppAs:(nullable XCUIApplication *)otherApp if (nil == otherApp) { return NO; } - return [self.bundleID isEqualToString:(NSString *)otherApp.bundleID]; + return self == otherApp || [self.bundleID isEqualToString:(NSString *)otherApp.bundleID]; } @end diff --git a/WebDriverAgentLib/FBAlert.m b/WebDriverAgentLib/FBAlert.m index cd71663dd..b06e26788 100644 --- a/WebDriverAgentLib/FBAlert.m +++ b/WebDriverAgentLib/FBAlert.m @@ -261,7 +261,12 @@ - (BOOL)clickAlertButton:(NSString *)label error:(NSError **)error - (XCUIElement *)alertElement { if (nil == self.element) { - self.element = XCUIApplication.fb_systemApplication.fb_alertElement ?: self.application.fb_alertElement; + XCUIApplication *systemApp = XCUIApplication.fb_systemApplication; + if ([systemApp fb_isSameAppAs:self.application]) { + self.element = systemApp.fb_alertElement; + } else { + self.element = systemApp.fb_alertElement ?: self.application.fb_alertElement; + } } return self.element; } From 9856051dac1979852f2f555797c17c59b372e4cb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 28 Feb 2024 18:50:34 +0000 Subject: [PATCH 021/368] chore(release): 7.0.2 [skip ci] ## [7.0.2](https://github.com/appium/WebDriverAgent/compare/v7.0.1...v7.0.2) (2024-02-28) ### Miscellaneous Chores * Tune alert detection if system app is active ([#854](https://github.com/appium/WebDriverAgent/issues/854)) ([857d3de](https://github.com/appium/WebDriverAgent/commit/857d3decf497935098ba6acb61654be1da173b11)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 998e59430..6f02963cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.0.2](https://github.com/appium/WebDriverAgent/compare/v7.0.1...v7.0.2) (2024-02-28) + + +### Miscellaneous Chores + +* Tune alert detection if system app is active ([#854](https://github.com/appium/WebDriverAgent/issues/854)) ([857d3de](https://github.com/appium/WebDriverAgent/commit/857d3decf497935098ba6acb61654be1da173b11)) + ## [7.0.1](https://github.com/appium/WebDriverAgent/compare/v7.0.0...v7.0.1) (2024-02-21) diff --git a/package.json b/package.json index 022389e50..e2c1ef832 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.0.1", + "version": "7.0.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From aa0765e425faba6c035a9933320e91679b167b80 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 3 Mar 2024 01:18:03 -0800 Subject: [PATCH 022/368] chore: tune release packages (#856) * chore: tune release * tune name * adjust syntax --- .github/workflows/publish.js.yml | 19 +-------------- .github/workflows/wda-package.yml | 40 +++++++++++++++++++++---------- .releaserc | 6 +---- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/.github/workflows/publish.js.yml b/.github/workflows/publish.js.yml index 92299e7a8..323ae7278 100644 --- a/.github/workflows/publish.js.yml +++ b/.github/workflows/publish.js.yml @@ -14,9 +14,7 @@ jobs: env: 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" PKG_PATH_TVOS: "appium_wda_tvos" steps: @@ -35,7 +33,7 @@ jobs: - run: npm run test name: Run test - # building WDA packages + # building WDA packages to test package build - name: Build iOS run: | xcodebuild clean build-for-testing \ @@ -44,13 +42,6 @@ jobs: -scheme WebDriverAgentRunner \ -destination generic/platform=iOS \ CODE_SIGNING_ALLOWED=NO ARCHS=arm64 - - 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 ./ - name: Build tvOS run: | xcodebuild clean build-for-testing \ @@ -59,13 +50,6 @@ jobs: -scheme WebDriverAgentRunner_tvOS \ -destination generic/platform=tvOS \ CODE_SIGNING_ALLOWED=NO ARCHS=arm64 - - 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 ./ # release tasks - run: npx semantic-release @@ -73,4 +57,3 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} name: Release - diff --git a/.github/workflows/wda-package.yml b/.github/workflows/wda-package.yml index b4b4223f2..2827b080f 100644 --- a/.github/workflows/wda-package.yml +++ b/.github/workflows/wda-package.yml @@ -2,10 +2,8 @@ name: Building WebDriverAgent on: workflow_dispatch: - workflow_run: - workflows: ["Release"] - types: - - completed + release: + types: [published] env: HOST: macos-13 @@ -56,14 +54,25 @@ jobs: 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 + - name: upload WebDriverAgentRunner-Runner.zip + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.token }} with: - path: "${{ env.ZIP_PKG_NAME_IOS }}" - - name: Upload the built generic app package for tvOS - uses: actions/upload-artifact@v3.1.0 + upload_url: ${{ github.event.release.upload_url }} + asset_path: "${{ env.ZIP_PKG_NAME_IOS }}" + asset_name: WebDriverAgentRunner-Runner.zip + asset_content_type: application/zip + + - name: upload WebDriverAgentRunner_tvOS-Runner.zip + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.token }} with: - path: "${{ env.ZIP_PKG_NAME_TVOS }}" + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ env.ZIP_PKG_NAME_TVOS }}" + asset_name: WebDriverAgentRunner_tvOS-Runner.zip + asset_content_type: application/zip for_simulator_devices: needs: [host_machine] @@ -89,7 +98,12 @@ jobs: 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 + - name: upload windows WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.token }} with: - path: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" + upload_url: ${{ github.event.release.upload_url }} + asset_path: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" + asset_name: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" + asset_content_type: application/zip diff --git a/.releaserc b/.releaserc index 0cb17f220..631d1ee18 100644 --- a/.releaserc +++ b/.releaserc @@ -32,10 +32,6 @@ "assets": ["docs", "package.json", "CHANGELOG.md"], "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" }], - ["@semantic-release/github", { - "assets": [ - "WebDriverAgentRunner-Runner.zip", - "WebDriverAgentRunner_tvOS-Runner.zip" - ]}] + ["@semantic-release/github"] ] } From 00474451f07235a2281ef0375ed4df33a772ef9c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 3 Mar 2024 09:24:34 +0000 Subject: [PATCH 023/368] chore(release): 7.0.3 [skip ci] ## [7.0.3](https://github.com/appium/WebDriverAgent/compare/v7.0.2...v7.0.3) (2024-03-03) ### Miscellaneous Chores * tune release packages ([#856](https://github.com/appium/WebDriverAgent/issues/856)) ([aa0765e](https://github.com/appium/WebDriverAgent/commit/aa0765e425faba6c035a9933320e91679b167b80)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f02963cf..2d17752a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.0.3](https://github.com/appium/WebDriverAgent/compare/v7.0.2...v7.0.3) (2024-03-03) + + +### Miscellaneous Chores + +* tune release packages ([#856](https://github.com/appium/WebDriverAgent/issues/856)) ([aa0765e](https://github.com/appium/WebDriverAgent/commit/aa0765e425faba6c035a9933320e91679b167b80)) + ## [7.0.2](https://github.com/appium/WebDriverAgent/compare/v7.0.1...v7.0.2) (2024-02-28) diff --git a/package.json b/package.json index e2c1ef832..3827fd403 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.0.2", + "version": "7.0.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 0cb66c5edc91c191d5ec412ba0a479e07cb4214b Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 3 Mar 2024 01:34:02 -0800 Subject: [PATCH 024/368] chore: dummy commit to trigger a release From 645475817d23b3b209044cac3ad1f2bca8bd64de Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 3 Mar 2024 09:40:32 +0000 Subject: [PATCH 025/368] chore(release): 7.0.4 [skip ci] ## [7.0.4](https://github.com/appium/WebDriverAgent/compare/v7.0.3...v7.0.4) (2024-03-03) ### Miscellaneous Chores * dummy commit to trigger a release ([0cb66c5](https://github.com/appium/WebDriverAgent/commit/0cb66c5edc91c191d5ec412ba0a479e07cb4214b)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d17752a1..995cba146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.0.4](https://github.com/appium/WebDriverAgent/compare/v7.0.3...v7.0.4) (2024-03-03) + + +### Miscellaneous Chores + +* dummy commit to trigger a release ([0cb66c5](https://github.com/appium/WebDriverAgent/commit/0cb66c5edc91c191d5ec412ba0a479e07cb4214b)) + ## [7.0.3](https://github.com/appium/WebDriverAgent/compare/v7.0.2...v7.0.3) (2024-03-03) diff --git a/package.json b/package.json index 3827fd403..3deb8a4c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.0.3", + "version": "7.0.4", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From dc720157a60925451e6d5935abcd168082d44785 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 3 Mar 2024 01:54:09 -0800 Subject: [PATCH 026/368] Revert "chore: tune release packages (#856)" (#857) This reverts commit aa0765e425faba6c035a9933320e91679b167b80. --- .github/workflows/publish.js.yml | 19 ++++++++++++++- .github/workflows/wda-package.yml | 40 ++++++++++--------------------- .releaserc | 6 ++++- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/.github/workflows/publish.js.yml b/.github/workflows/publish.js.yml index 323ae7278..92299e7a8 100644 --- a/.github/workflows/publish.js.yml +++ b/.github/workflows/publish.js.yml @@ -14,7 +14,9 @@ jobs: env: 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" PKG_PATH_TVOS: "appium_wda_tvos" steps: @@ -33,7 +35,7 @@ jobs: - run: npm run test name: Run test - # building WDA packages to test package build + # building WDA packages - name: Build iOS run: | xcodebuild clean build-for-testing \ @@ -42,6 +44,13 @@ jobs: -scheme WebDriverAgentRunner \ -destination generic/platform=iOS \ CODE_SIGNING_ALLOWED=NO ARCHS=arm64 + - 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 ./ - name: Build tvOS run: | xcodebuild clean build-for-testing \ @@ -50,6 +59,13 @@ jobs: -scheme WebDriverAgentRunner_tvOS \ -destination generic/platform=tvOS \ CODE_SIGNING_ALLOWED=NO ARCHS=arm64 + - 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 ./ # release tasks - run: npx semantic-release @@ -57,3 +73,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} name: Release + diff --git a/.github/workflows/wda-package.yml b/.github/workflows/wda-package.yml index 2827b080f..b4b4223f2 100644 --- a/.github/workflows/wda-package.yml +++ b/.github/workflows/wda-package.yml @@ -2,8 +2,10 @@ name: Building WebDriverAgent on: workflow_dispatch: - release: - types: [published] + workflow_run: + workflows: ["Release"] + types: + - completed env: HOST: macos-13 @@ -54,25 +56,14 @@ jobs: WD: appium_wda_tvos/Build/Products/Debug-appletvos ZIP_PKG_NAME: "${{ env.ZIP_PKG_NAME_TVOS }}" - - name: upload WebDriverAgentRunner-Runner.zip - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.token }} + - name: Upload the built generic app package for iOS + uses: actions/upload-artifact@v3.1.0 with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: "${{ env.ZIP_PKG_NAME_IOS }}" - asset_name: WebDriverAgentRunner-Runner.zip - asset_content_type: application/zip - - - name: upload WebDriverAgentRunner_tvOS-Runner.zip - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.token }} + path: "${{ env.ZIP_PKG_NAME_IOS }}" + - name: Upload the built generic app package for tvOS + uses: actions/upload-artifact@v3.1.0 with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ${{ env.ZIP_PKG_NAME_TVOS }}" - asset_name: WebDriverAgentRunner_tvOS-Runner.zip - asset_content_type: application/zip + path: "${{ env.ZIP_PKG_NAME_TVOS }}" for_simulator_devices: needs: [host_machine] @@ -98,12 +89,7 @@ jobs: SCHEME: WebDriverAgentRunner${{ matrix.target }} ARCHS: ${{ matrix.arch }} ZIP_PKG_NAME: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" - - name: upload windows WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.token }} + - name: Upload the built generic app package for WebDriverAgentRunner${{ matrix.target }} with ${{ matrix.arch }} + uses: actions/upload-artifact@v3.1.0 with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" - asset_name: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" - asset_content_type: application/zip + path: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" diff --git a/.releaserc b/.releaserc index 631d1ee18..0cb17f220 100644 --- a/.releaserc +++ b/.releaserc @@ -32,6 +32,10 @@ "assets": ["docs", "package.json", "CHANGELOG.md"], "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" }], - ["@semantic-release/github"] + ["@semantic-release/github", { + "assets": [ + "WebDriverAgentRunner-Runner.zip", + "WebDriverAgentRunner_tvOS-Runner.zip" + ]}] ] } From 6f4b64084c75acac326bde0ca7757b50a715d63d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 3 Mar 2024 09:59:37 +0000 Subject: [PATCH 027/368] chore(release): 7.0.5 [skip ci] ## [7.0.5](https://github.com/appium/WebDriverAgent/compare/v7.0.4...v7.0.5) (2024-03-03) ### Reverts * Revert "chore: tune release packages (#856)" (#857) ([dc72015](https://github.com/appium/WebDriverAgent/commit/dc720157a60925451e6d5935abcd168082d44785)), closes [#856](https://github.com/appium/WebDriverAgent/issues/856) [#857](https://github.com/appium/WebDriverAgent/issues/857) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 995cba146..6ab09f210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.0.5](https://github.com/appium/WebDriverAgent/compare/v7.0.4...v7.0.5) (2024-03-03) + + +### Reverts + +* Revert "chore: tune release packages (#856)" (#857) ([dc72015](https://github.com/appium/WebDriverAgent/commit/dc720157a60925451e6d5935abcd168082d44785)), closes [#856](https://github.com/appium/WebDriverAgent/issues/856) [#857](https://github.com/appium/WebDriverAgent/issues/857) + ## [7.0.4](https://github.com/appium/WebDriverAgent/compare/v7.0.3...v7.0.4) (2024-03-03) diff --git a/package.json b/package.json index 3deb8a4c3..48d2da85e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.0.4", + "version": "7.0.5", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 0ec5398e9cb4b0e5ab133cc0c330b85b3d37766e Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 3 Mar 2024 18:31:05 +0100 Subject: [PATCH 028/368] chore: Handle app startup errors as session creation exceptions (#855) --- .../Commands/FBSessionCommands.m | 22 ++++++++++++------- .../Routing/FBExceptionHandler.m | 3 +++ WebDriverAgentLib/Routing/FBExceptions.h | 3 +++ WebDriverAgentLib/Routing/FBExceptions.m | 1 + 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 9594058a9..38def9553 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -11,6 +11,7 @@ #import "FBCapabilities.h" #import "FBConfiguration.h" +#import "FBExceptions.h" #import "FBLogger.h" #import "FBProtocolHelpers.h" #import "FBRouteRequest.h" @@ -91,7 +92,7 @@ + (NSArray *)routes traceback:nil]); } if (nil == (capabilities = FBParseCapabilities((NSDictionary *)request.arguments[@"capabilities"], &error))) { - return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:error.description traceback:nil]); + return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:error.localizedDescription traceback:nil]); } [FBConfiguration resetSessionSettings]; @@ -159,12 +160,16 @@ + (NSArray *)routes if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl withApplication:bundleID error:&openError]) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ wuth the %@ application. Original error: %@", - initialUrl, bundleID, openError.description]; + NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", + initialUrl, bundleID, openError.localizedDescription]; return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); } } else { - [app launch]; + @try { + [app launch]; + } @catch (NSException *e) { + return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:e.reason traceback:nil]); + } } if (!app.running) { NSString *errorMsg = [NSString stringWithFormat:@"Cannot launch %@ application. Make sure the correct bundle identifier has been provided in capabilities and check the device log for possible crash report occurrences", bundleID]; @@ -178,7 +183,7 @@ + (NSArray *)routes withApplication:bundleID error:&openError]) { NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", - initialUrl, bundleID, openError.description]; + initialUrl, bundleID, openError.localizedDescription]; return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); } } else { @@ -191,7 +196,7 @@ + (NSArray *)routes NSError *openError; if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl error:&openError]) { NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@. Original error: %@", - initialUrl, openError.description]; + initialUrl, openError.localizedDescription]; return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); } } @@ -396,7 +401,8 @@ + (NSArray *)routes NSError *error; if (![FBActiveAppDetectionPoint.sharedInstance setCoordinatesWithString:(NSString *)[settings objectForKey:FB_SETTING_ACTIVE_APP_DETECTION_POINT] error:&error]) { - return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.description traceback:nil]); + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.localizedDescription + traceback:nil]); } } if (nil != [settings objectForKey:FB_SETTING_INCLUDE_NON_MODAL_ELEMENTS]) { @@ -427,7 +433,7 @@ + (NSArray *)routes NSError *error; if (![FBConfiguration setScreenshotOrientation:(NSString *)[settings objectForKey:FB_SETTING_SCREENSHOT_ORIENTATION] error:&error]) { - return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.description + return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.localizedDescription traceback:nil]); } } diff --git a/WebDriverAgentLib/Routing/FBExceptionHandler.m b/WebDriverAgentLib/Routing/FBExceptionHandler.m index 7b7a8263f..811a0efb5 100644 --- a/WebDriverAgentLib/Routing/FBExceptionHandler.m +++ b/WebDriverAgentLib/Routing/FBExceptionHandler.m @@ -45,6 +45,9 @@ - (void)handleException:(NSException *)exception forResponse:(RouteResponse *)re } else if ([exception.name isEqualToString:FBTimeoutException]) { commandStatus = [FBCommandStatus timeoutErrorWithMessage:exception.reason traceback:traceback]; + } else if ([exception.name isEqualToString:FBSessionCreationException]) { + commandStatus = [FBCommandStatus sessionNotCreatedError:exception.reason + traceback:traceback]; } else { commandStatus = [FBCommandStatus unknownErrorWithMessage:exception.reason traceback:traceback]; diff --git a/WebDriverAgentLib/Routing/FBExceptions.h b/WebDriverAgentLib/Routing/FBExceptions.h index 1c9507a19..a7263bae4 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.h +++ b/WebDriverAgentLib/Routing/FBExceptions.h @@ -14,6 +14,9 @@ NS_ASSUME_NONNULL_BEGIN /*! Exception used to notify about missing session */ extern NSString *const FBSessionDoesNotExistException; +/*! Exception used to notify about session creation issues */ +extern NSString *const FBSessionCreationException; + /*! Exception used to notify about application deadlock */ extern NSString *const FBApplicationDeadlockDetectedException; diff --git a/WebDriverAgentLib/Routing/FBExceptions.m b/WebDriverAgentLib/Routing/FBExceptions.m index 571cea4fb..9e1f2141f 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.m +++ b/WebDriverAgentLib/Routing/FBExceptions.m @@ -10,6 +10,7 @@ #import "FBExceptions.h" NSString *const FBInvalidArgumentException = @"FBInvalidArgumentException"; +NSString *const FBSessionCreationException = @"FBSessionCreationException"; NSString *const FBSessionDoesNotExistException = @"FBSessionDoesNotExistException"; NSString *const FBApplicationDeadlockDetectedException = @"FBApplicationDeadlockDetectedException"; NSString *const FBElementAttributeUnknownException = @"FBElementAttributeUnknownException"; From 21f9af8b51dd05aa041ee26b7496445a14f5322e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 3 Mar 2024 17:36:16 +0000 Subject: [PATCH 029/368] chore(release): 7.0.6 [skip ci] ## [7.0.6](https://github.com/appium/WebDriverAgent/compare/v7.0.5...v7.0.6) (2024-03-03) ### Miscellaneous Chores * Handle app startup errors as session creation exceptions ([#855](https://github.com/appium/WebDriverAgent/issues/855)) ([0ec5398](https://github.com/appium/WebDriverAgent/commit/0ec5398e9cb4b0e5ab133cc0c330b85b3d37766e)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ab09f210..660ff5544 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.0.6](https://github.com/appium/WebDriverAgent/compare/v7.0.5...v7.0.6) (2024-03-03) + + +### Miscellaneous Chores + +* Handle app startup errors as session creation exceptions ([#855](https://github.com/appium/WebDriverAgent/issues/855)) ([0ec5398](https://github.com/appium/WebDriverAgent/commit/0ec5398e9cb4b0e5ab133cc0c330b85b3d37766e)) + ## [7.0.5](https://github.com/appium/WebDriverAgent/compare/v7.0.4...v7.0.5) (2024-03-03) diff --git a/package.json b/package.json index 48d2da85e..f37ebd135 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.0.5", + "version": "7.0.6", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 89880f509f930f16f6469bcda613569040c337b6 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 7 Mar 2024 17:08:02 +0100 Subject: [PATCH 030/368] chore: bump typescript --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f37ebd135..0028b6843 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "semantic-release": "^23.0.0", "sinon": "^17.0.0", "ts-node": "^10.9.1", - "typescript": "~5.2" + "typescript": "^5.4.2" }, "dependencies": { "@appium/base-driver": "^9.0.0", From 9728548676c8de67c30d127ee8b0374f58286e74 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 7 Mar 2024 17:11:16 +0100 Subject: [PATCH 031/368] feat: Add wrappers for native XCTest video recorder (#858) --- .../XCTest/XCTRunnerDaemonSession.h | 8 ++ WebDriverAgent.xcodeproj/project.pbxproj | 60 ++++++++++++ WebDriverAgentLib/Commands/FBVideoCommands.h | 20 ++++ WebDriverAgentLib/Commands/FBVideoCommands.m | 85 ++++++++++++++++ .../Routing/FBScreenRecordingContainer.h | 57 +++++++++++ .../Routing/FBScreenRecordingContainer.m | 73 ++++++++++++++ .../Routing/FBScreenRecordingPromise.h | 30 ++++++ .../Routing/FBScreenRecordingPromise.m | 32 ++++++ .../Routing/FBScreenRecordingRequest.h | 40 ++++++++ .../Routing/FBScreenRecordingRequest.m | 95 ++++++++++++++++++ WebDriverAgentLib/Routing/FBSession.m | 13 +++ .../Utilities/FBXCTestDaemonsProxy.h | 6 ++ .../Utilities/FBXCTestDaemonsProxy.m | 97 ++++++++++++++++--- .../IntegrationTests/FBVideoRecordingTests.m | 63 ++++++++++++ 14 files changed, 663 insertions(+), 16 deletions(-) create mode 100644 WebDriverAgentLib/Commands/FBVideoCommands.h create mode 100644 WebDriverAgentLib/Commands/FBVideoCommands.m create mode 100644 WebDriverAgentLib/Routing/FBScreenRecordingContainer.h create mode 100644 WebDriverAgentLib/Routing/FBScreenRecordingContainer.m create mode 100644 WebDriverAgentLib/Routing/FBScreenRecordingPromise.h create mode 100644 WebDriverAgentLib/Routing/FBScreenRecordingPromise.m create mode 100644 WebDriverAgentLib/Routing/FBScreenRecordingRequest.h create mode 100644 WebDriverAgentLib/Routing/FBScreenRecordingRequest.m create mode 100644 WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m diff --git a/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h b/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h index 7473b2e0a..7ca530371 100644 --- a/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h +++ b/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h @@ -80,6 +80,14 @@ @property(readonly) _Bool supportsLocationSimulation; #endif +// Since Xcode 15.0-beta1 +- (void)stopScreenRecordingWithUUID:(NSUUID *)arg1 + withReply:(void (^)(NSError *))arg2; +- (void)startScreenRecordingWithRequest:(id/* XCTScreenRecordingRequest */)arg1 + withReply:(void (^)(id/* XCTAttachmentFutureMetadata */, NSError *))arg2; +- (_Bool)supportsScreenRecording; +- (_Bool)preferScreenshotsOverScreenRecordings; + // Since Xcode 10.2 - (void)launchApplicationWithPath:(NSString *)arg1 bundleID:(NSString *)arg2 diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index bc4f29813..db4465848 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -457,6 +457,27 @@ 71B155E123080CA600646AFB /* FBProtocolHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B155DE23080CA600646AFB /* FBProtocolHelpers.m */; }; 71B49EC71ED1A58100D51AD6 /* XCUIElement+FBUID.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B49EC51ED1A58100D51AD6 /* XCUIElement+FBUID.h */; }; 71B49EC81ED1A58100D51AD6 /* XCUIElement+FBUID.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B49EC61ED1A58100D51AD6 /* XCUIElement+FBUID.m */; }; + 71BB58DE2B9631B700CB9BFE /* FBVideoRecordingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58DD2B9631B700CB9BFE /* FBVideoRecordingTests.m */; }; + 71BB58E12B9631F100CB9BFE /* FBScreenRecordingPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BB58DF2B9631F100CB9BFE /* FBScreenRecordingPromise.h */; }; + 71BB58E22B9631F100CB9BFE /* FBScreenRecordingPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BB58DF2B9631F100CB9BFE /* FBScreenRecordingPromise.h */; }; + 71BB58E32B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58E02B9631F100CB9BFE /* FBScreenRecordingPromise.m */; }; + 71BB58E42B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58E02B9631F100CB9BFE /* FBScreenRecordingPromise.m */; }; + 71BB58E52B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58E02B9631F100CB9BFE /* FBScreenRecordingPromise.m */; }; + 71BB58E82B96328700CB9BFE /* FBScreenRecordingRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BB58E62B96328700CB9BFE /* FBScreenRecordingRequest.h */; }; + 71BB58E92B96328700CB9BFE /* FBScreenRecordingRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BB58E62B96328700CB9BFE /* FBScreenRecordingRequest.h */; }; + 71BB58EA2B96328700CB9BFE /* FBScreenRecordingRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58E72B96328700CB9BFE /* FBScreenRecordingRequest.m */; }; + 71BB58EB2B96328700CB9BFE /* FBScreenRecordingRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58E72B96328700CB9BFE /* FBScreenRecordingRequest.m */; }; + 71BB58EC2B96328700CB9BFE /* FBScreenRecordingRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58E72B96328700CB9BFE /* FBScreenRecordingRequest.m */; }; + 71BB58EF2B96511800CB9BFE /* FBVideoCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BB58ED2B96511800CB9BFE /* FBVideoCommands.h */; }; + 71BB58F02B96511800CB9BFE /* FBVideoCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BB58ED2B96511800CB9BFE /* FBVideoCommands.h */; }; + 71BB58F12B96511800CB9BFE /* FBVideoCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58EE2B96511800CB9BFE /* FBVideoCommands.m */; }; + 71BB58F22B96511800CB9BFE /* FBVideoCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58EE2B96511800CB9BFE /* FBVideoCommands.m */; }; + 71BB58F32B96511800CB9BFE /* FBVideoCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58EE2B96511800CB9BFE /* FBVideoCommands.m */; }; + 71BB58F62B96531900CB9BFE /* FBScreenRecordingContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BB58F42B96531900CB9BFE /* FBScreenRecordingContainer.h */; }; + 71BB58F72B96531900CB9BFE /* FBScreenRecordingContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BB58F42B96531900CB9BFE /* FBScreenRecordingContainer.h */; }; + 71BB58F82B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58F52B96531900CB9BFE /* FBScreenRecordingContainer.m */; }; + 71BB58F92B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58F52B96531900CB9BFE /* FBScreenRecordingContainer.m */; }; + 71BB58FA2B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58F52B96531900CB9BFE /* FBScreenRecordingContainer.m */; }; 71BD20731F86116100B36EC2 /* XCUIApplication+FBTouchAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 71BD20711F86116100B36EC2 /* XCUIApplication+FBTouchAction.h */; }; 71BD20741F86116100B36EC2 /* XCUIApplication+FBTouchAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BD20721F86116100B36EC2 /* XCUIApplication+FBTouchAction.m */; }; 71C8E55125399A6B008572C1 /* XCUIApplication+FBQuiescence.h in Headers */ = {isa = PBXBuildFile; fileRef = 71C8E54F25399A6B008572C1 /* XCUIApplication+FBQuiescence.h */; }; @@ -1035,6 +1056,15 @@ 71B155DE23080CA600646AFB /* FBProtocolHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBProtocolHelpers.m; sourceTree = ""; }; 71B49EC51ED1A58100D51AD6 /* XCUIElement+FBUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBUID.h"; sourceTree = ""; }; 71B49EC61ED1A58100D51AD6 /* XCUIElement+FBUID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBUID.m"; sourceTree = ""; }; + 71BB58DD2B9631B700CB9BFE /* FBVideoRecordingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBVideoRecordingTests.m; sourceTree = ""; }; + 71BB58DF2B9631F100CB9BFE /* FBScreenRecordingPromise.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBScreenRecordingPromise.h; sourceTree = ""; }; + 71BB58E02B9631F100CB9BFE /* FBScreenRecordingPromise.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBScreenRecordingPromise.m; sourceTree = ""; }; + 71BB58E62B96328700CB9BFE /* FBScreenRecordingRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBScreenRecordingRequest.h; sourceTree = ""; }; + 71BB58E72B96328700CB9BFE /* FBScreenRecordingRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBScreenRecordingRequest.m; sourceTree = ""; }; + 71BB58ED2B96511800CB9BFE /* FBVideoCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBVideoCommands.h; sourceTree = ""; }; + 71BB58EE2B96511800CB9BFE /* FBVideoCommands.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBVideoCommands.m; sourceTree = ""; }; + 71BB58F42B96531900CB9BFE /* FBScreenRecordingContainer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBScreenRecordingContainer.h; sourceTree = ""; }; + 71BB58F52B96531900CB9BFE /* FBScreenRecordingContainer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBScreenRecordingContainer.m; sourceTree = ""; }; 71BD20711F86116100B36EC2 /* XCUIApplication+FBTouchAction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIApplication+FBTouchAction.h"; sourceTree = ""; }; 71BD20721F86116100B36EC2 /* XCUIApplication+FBTouchAction.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIApplication+FBTouchAction.m"; sourceTree = ""; }; 71C8E54F25399A6B008572C1 /* XCUIApplication+FBQuiescence.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIApplication+FBQuiescence.h"; sourceTree = ""; }; @@ -1789,6 +1819,8 @@ EE9AB7631CAEDF0C008C271F /* FBTouchIDCommands.m */, EE9AB7641CAEDF0C008C271F /* FBUnknownCommands.h */, EE9AB7651CAEDF0C008C271F /* FBUnknownCommands.m */, + 71BB58ED2B96511800CB9BFE /* FBVideoCommands.h */, + 71BB58EE2B96511800CB9BFE /* FBVideoCommands.m */, ); name = Commands; path = WebDriverAgentLib/Commands; @@ -1828,6 +1860,12 @@ EE9AB7861CAEDF0C008C271F /* FBRouteRequest-Private.h */, EE9AB7871CAEDF0C008C271F /* FBRouteRequest.h */, EE9AB7881CAEDF0C008C271F /* FBRouteRequest.m */, + 71BB58F42B96531900CB9BFE /* FBScreenRecordingContainer.h */, + 71BB58F52B96531900CB9BFE /* FBScreenRecordingContainer.m */, + 71BB58DF2B9631F100CB9BFE /* FBScreenRecordingPromise.h */, + 71BB58E02B9631F100CB9BFE /* FBScreenRecordingPromise.m */, + 71BB58E62B96328700CB9BFE /* FBScreenRecordingRequest.h */, + 71BB58E72B96328700CB9BFE /* FBScreenRecordingRequest.m */, EE9AB7891CAEDF0C008C271F /* FBSession-Private.h */, EE9AB78A1CAEDF0C008C271F /* FBSession.h */, EE9AB78B1CAEDF0C008C271F /* FBSession.m */, @@ -1972,6 +2010,7 @@ EE1E06DC1D1811C4007CF043 /* FBTestMacros.h */, AD76723F1D6B826F00610457 /* FBTypingTest.m */, 714CA3C61DC23186000F12C9 /* FBXPathIntegrationTests.m */, + 71BB58DD2B9631B700CB9BFE /* FBVideoRecordingTests.m */, 71241D7D1FAF084E00B9559F /* FBW3CTouchActionsIntegrationTests.m */, 71241D7F1FAF087500B9559F /* FBW3CMultiTouchActionsIntegrationTests.m */, 7136C0F8243A182400921C76 /* FBW3CTypeActionsTests.m */, @@ -2264,6 +2303,7 @@ 641EE64F2240C5CA00173FCB /* XCTestExpectationWaiter.h in Headers */, 13DE7A5C287CA444003243C6 /* FBXCElementSnapshotWrapper+Helpers.h in Headers */, 641EE6502240C5CA00173FCB /* UIGestureRecognizer-RecordingAdditions.h in Headers */, + 71BB58E92B96328700CB9BFE /* FBScreenRecordingRequest.h in Headers */, 641EE6512240C5CA00173FCB /* XCKeyboardKeyMap.h in Headers */, 641EE6522240C5CA00173FCB /* XCTNSPredicateExpectationObject-Protocol.h in Headers */, 641EE6532240C5CA00173FCB /* WebDriverAgentLib.h in Headers */, @@ -2280,6 +2320,7 @@ 641EE65F2240C5CA00173FCB /* XCSourceCodeTreeNodeEnumerator.h in Headers */, 641EE6602240C5CA00173FCB /* XCUIElement+FBIsVisible.h in Headers */, 641EE6622240C5CA00173FCB /* FBResponsePayload.h in Headers */, + 71BB58E22B9631F100CB9BFE /* FBScreenRecordingPromise.h in Headers */, 641EE6632240C5CA00173FCB /* FBUnknownCommands.h in Headers */, 641EE7062240CDCF00173FCB /* XCUIElement+FBTVFocuse.h in Headers */, 71822738258744B800661B83 /* HTTPConnection.h in Headers */, @@ -2382,6 +2423,7 @@ 7182276E258744C900661B83 /* HTTPErrorResponse.h in Headers */, 641EE6B82240C5CA00173FCB /* FBAlert.h in Headers */, 641EE6B92240C5CA00173FCB /* XCUIElementQuery.h in Headers */, + 71BB58F02B96511800CB9BFE /* FBVideoCommands.h in Headers */, 641EE6BA2240C5CA00173FCB /* XCPointerEvent.h in Headers */, 718F49C923087ACF0045FE8B /* FBProtocolHelpers.h in Headers */, 641EE6BB2240C5CA00173FCB /* XCSourceCodeRecording.h in Headers */, @@ -2419,6 +2461,7 @@ 641EE6D42240C5CA00173FCB /* NSValue-XCTestAdditions.h in Headers */, 641EE6D52240C5CA00173FCB /* _XCTWaiterImpl.h in Headers */, 641EE6D62240C5CA00173FCB /* FBLogger.h in Headers */, + 71BB58F72B96531900CB9BFE /* FBScreenRecordingContainer.h in Headers */, 641EE6D72240C5CA00173FCB /* XCTestObserver.h in Headers */, 641EE6D82240C5CA00173FCB /* XCUIElement.h in Headers */, 641EE6D92240C5CA00173FCB /* XCKeyboardInputSolver.h in Headers */, @@ -2479,6 +2522,7 @@ EE158ABA1CBD456F00A3E3F0 /* FBCustomCommands.h in Headers */, EE35AD0D1E3B77D600A02D78 /* _XCTestCaseInterruptionException.h in Headers */, EE158AC41CBD456F00A3E3F0 /* FBOrientationCommands.h in Headers */, + 71BB58EF2B96511800CB9BFE /* FBVideoCommands.h in Headers */, 7119097C2152580600BA3C7E /* XCUIScreen.h in Headers */, EE35AD611E3B77D600A02D78 /* XCTRunnerIDESession.h in Headers */, EE158AE01CBD456F00A3E3F0 /* FBRouteRequest-Private.h in Headers */, @@ -2559,6 +2603,7 @@ EE158AD21CBD456F00A3E3F0 /* FBElementCache.h in Headers */, EE35AD5A1E3B77D600A02D78 /* XCTMetric.h in Headers */, EE35AD461E3B77D600A02D78 /* XCTestContextScope.h in Headers */, + 71BB58F62B96531900CB9BFE /* FBScreenRecordingContainer.h in Headers */, 71A7EAF51E20516B001DA4F2 /* XCUIElement+FBClassChain.h in Headers */, EE158ADA1CBD456F00A3E3F0 /* FBResponseJSONPayload.h in Headers */, EE35AD3D1E3B77D600A02D78 /* XCTAutomationTarget-Protocol.h in Headers */, @@ -2621,6 +2666,7 @@ EE35AD331E3B77D600A02D78 /* XCPointerEvent.h in Headers */, EE35AD351E3B77D600A02D78 /* XCSourceCodeRecording.h in Headers */, 71D04DC825356C43008A052C /* XCUIElement+FBCaching.h in Headers */, + 71BB58E12B9631F100CB9BFE /* FBScreenRecordingPromise.h in Headers */, E444DC99249131D40060D7EB /* HTTPLogging.h in Headers */, E444DC9B249131D40060D7EB /* HTTPResponse.h in Headers */, EEE9B4721CD02B88009D2030 /* FBRunLoopSpinner.h in Headers */, @@ -2646,6 +2692,7 @@ EE35AD571E3B77D600A02D78 /* XCTestSuiteRun.h in Headers */, EE35AD701E3B77D600A02D78 /* XCUIElementAsynchronousHandlerWrapper.h in Headers */, EE35AD4C1E3B77D600A02D78 /* XCTestLog.h in Headers */, + 71BB58E82B96328700CB9BFE /* FBScreenRecordingRequest.h in Headers */, EE35AD231E3B77D600A02D78 /* UITapGestureRecognizer-RecordingAdditions.h in Headers */, EE35AD2A1E3B77D600A02D78 /* XCDebugLogDelegate-Protocol.h in Headers */, EE35AD1C1E3B77D600A02D78 /* NSString-XCTAdditions.h in Headers */, @@ -3051,6 +3098,7 @@ 71C8E55425399A6B008572C1 /* XCUIApplication+FBQuiescence.m in Sources */, 641EE5DC2240C5CA00173FCB /* XCUIApplication+FBAlert.m in Sources */, 641EE70F2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */, + 71BB58EB2B96328700CB9BFE /* FBScreenRecordingRequest.m in Sources */, 714D88CF2733FB970074A925 /* FBXMLGenerationOptions.m in Sources */, 641EE5DE2240C5CA00173FCB /* XCUIApplication+FBTouchAction.m in Sources */, 714E14BB29805CAE00375DD7 /* XCAXClient_iOS+FBSnapshotReqParams.m in Sources */, @@ -3106,6 +3154,7 @@ 641EE6092240C5CA00173FCB /* XCUIElement+FBUtilities.m in Sources */, 641EE60A2240C5CA00173FCB /* FBLogger.m in Sources */, 641EE60B2240C5CA00173FCB /* FBCustomCommands.m in Sources */, + 71BB58E42B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */, 641EE60C2240C5CA00173FCB /* XCUIDevice+FBHelpers.m in Sources */, 641EE60D2240C5CA00173FCB /* XCTestPrivateSymbols.m in Sources */, 641EE60E2240C5CA00173FCB /* XCUIElement+FBTyping.m in Sources */, @@ -3117,6 +3166,7 @@ 641EE6132240C5CA00173FCB /* FBDebugLogDelegateDecorator.m in Sources */, 641EE6142240C5CA00173FCB /* FBAlertViewCommands.m in Sources */, 71414EDB2670A1EE003A8C5D /* LRUCacheNode.m in Sources */, + 71BB58F92B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */, 641EE6152240C5CA00173FCB /* XCUIElement+FBScrolling.m in Sources */, 641EE6162240C5CA00173FCB /* FBSessionCommands.m in Sources */, 641EE6192240C5CA00173FCB /* FBConfiguration.m in Sources */, @@ -3128,6 +3178,7 @@ 716C9DFD27315D21005AD475 /* FBReflectionUtils.m in Sources */, 641EE61D2240C5CA00173FCB /* FBElementCommands.m in Sources */, 641EE61E2240C5CA00173FCB /* FBExceptionHandler.m in Sources */, + 71BB58F22B96511800CB9BFE /* FBVideoCommands.m in Sources */, 641EE61F2240C5CA00173FCB /* FBXCodeCompatibility.m in Sources */, 71E75E70254824230099FC87 /* XCUIElementQuery+FBHelpers.m in Sources */, 641EE6212240C5CA00173FCB /* FBElementTypeTransformer.m in Sources */, @@ -3175,6 +3226,7 @@ 719DCF172601EAFB000E765F /* FBNotificationsHelper.m in Sources */, E444DCAC24913C220060D7EB /* Route.m in Sources */, 713C6DD01DDC772A00285B92 /* FBElementUtils.m in Sources */, + 71BB58E32B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */, 7140974C1FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.m in Sources */, EE6A893B1D0B38640083E92B /* FBFailureProofTestCase.m in Sources */, 713AE576243A53BE0000D657 /* FBW3CActionsHelpers.m in Sources */, @@ -3212,6 +3264,7 @@ 71F5BE51252F14EB00EE9EBA /* FBExceptions.m in Sources */, EE158ABD1CBD456F00A3E3F0 /* FBDebugCommands.m in Sources */, 716E0BCF1E917E810087A825 /* NSString+FBXMLSafeString.m in Sources */, + 71BB58EA2B96328700CB9BFE /* FBScreenRecordingRequest.m in Sources */, EE158ACD1CBD456F00A3E3F0 /* FBUnknownCommands.m in Sources */, EE158AC51CBD456F00A3E3F0 /* FBOrientationCommands.m in Sources */, 716F0DA32A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m in Sources */, @@ -3242,8 +3295,10 @@ 71C8E55325399A6B008572C1 /* XCUIApplication+FBQuiescence.m in Sources */, 71414EDA2670A1EE003A8C5D /* LRUCacheNode.m in Sources */, EE158AB91CBD456F00A3E3F0 /* FBAlertViewCommands.m in Sources */, + 71BB58F12B96511800CB9BFE /* FBVideoCommands.m in Sources */, 71F3E7D625417FF400E0C22B /* FBSettings.m in Sources */, 13DE7A57287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m in Sources */, + 71BB58F82B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */, EE158AB31CBD456F00A3E3F0 /* XCUIElement+FBScrolling.m in Sources */, 718226CE2587443700661B83 /* GCDAsyncSocket.m in Sources */, EE158AC91CBD456F00A3E3F0 /* FBSessionCommands.m in Sources */, @@ -3276,14 +3331,19 @@ buildActionMask = 2147483647; files = ( 71241D801FAF087500B9559F /* FBW3CMultiTouchActionsIntegrationTests.m in Sources */, + 71BB58DE2B9631B700CB9BFE /* FBVideoRecordingTests.m in Sources */, 71241D7E1FAF084E00B9559F /* FBW3CTouchActionsIntegrationTests.m in Sources */, 63FD950221F9D06100A3E356 /* FBImageProcessorTests.m in Sources */, 719CD8FF2126C90200C7D0C2 /* FBAutoAlertsHandlerTests.m in Sources */, EE2202131ECC612200A29571 /* FBIntegrationTestCase.m in Sources */, 715AFAC41FFA2AAF0053896D /* FBScreenTests.m in Sources */, + 71BB58EC2B96328700CB9BFE /* FBScreenRecordingRequest.m in Sources */, EE22021E1ECC618900A29571 /* FBTapTest.m in Sources */, 71930C472066434000D3AFEC /* FBPasteboardTests.m in Sources */, + 71BB58E52B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */, + 71BB58FA2B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */, 7150FFF722476B3A00B2EE28 /* FBForceTouchTests.m in Sources */, + 71BB58F32B96511800CB9BFE /* FBVideoCommands.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WebDriverAgentLib/Commands/FBVideoCommands.h b/WebDriverAgentLib/Commands/FBVideoCommands.h new file mode 100644 index 000000000..b2e3eb795 --- /dev/null +++ b/WebDriverAgentLib/Commands/FBVideoCommands.h @@ -0,0 +1,20 @@ +/** + * 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 + +NS_ASSUME_NONNULL_BEGIN + +@interface FBVideoCommands : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Commands/FBVideoCommands.m b/WebDriverAgentLib/Commands/FBVideoCommands.m new file mode 100644 index 000000000..8366c3a79 --- /dev/null +++ b/WebDriverAgentLib/Commands/FBVideoCommands.m @@ -0,0 +1,85 @@ +/** + * 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 "FBVideoCommands.h" + +#import "FBRouteRequest.h" +#import "FBScreenRecordingContainer.h" +#import "FBScreenRecordingPromise.h" +#import "FBScreenRecordingRequest.h" +#import "FBSession.h" +#import "FBXCTestDaemonsProxy.h" + +const NSUInteger DEFAULT_FPS = 24; +const NSUInteger DEFAULT_CODEC = 0; + +@implementation FBVideoCommands + ++ (NSArray *)routes +{ + return + @[ + [[FBRoute POST:@"/wda/video/start"] respondWithTarget:self action:@selector(handleStartVideoRecording:)], + [[FBRoute POST:@"/wda/video/stop"] respondWithTarget:self action:@selector(handleStopVideoRecording:)], + [[FBRoute GET:@"/wda/video"] respondWithTarget:self action:@selector(handleGetVideoRecording:)], + + [[FBRoute POST:@"/wda/video/start"].withoutSession respondWithTarget:self action:@selector(handleStartVideoRecording:)], + [[FBRoute POST:@"/wda/video/stop"].withoutSession respondWithTarget:self action:@selector(handleStopVideoRecording:)], + [[FBRoute GET:@"/wda/video"].withoutSession respondWithTarget:self action:@selector(handleGetVideoRecording:)], + ]; +} + ++ (id)handleStartVideoRecording:(FBRouteRequest *)request +{ + FBScreenRecordingPromise *activeScreenRecording = FBScreenRecordingContainer.sharedInstance.screenRecordingPromise; + if (nil != activeScreenRecording) { + return FBResponseWithObject([FBScreenRecordingContainer.sharedInstance toDictionary] ?: [NSNull null]); + } + + NSNumber *fps = (NSNumber *)request.arguments[@"fps"] ?: @(DEFAULT_FPS); + NSNumber *codec = (NSNumber *)request.arguments[@"codec"] ?: @(DEFAULT_CODEC); + FBScreenRecordingRequest *recordingRequest = [[FBScreenRecordingRequest alloc] initWithFps:fps.integerValue + codec:codec.longLongValue]; + NSError *error; + FBScreenRecordingPromise* promise = [FBXCTestDaemonsProxy startScreenRecordingWithRequest:recordingRequest + error:&error]; + if (nil == promise) { + [FBScreenRecordingContainer.sharedInstance reset]; + return FBResponseWithUnknownError(error); + } + [FBScreenRecordingContainer.sharedInstance storeScreenRecordingPromise:promise + fps:fps.integerValue + codec:codec.longLongValue]; + return FBResponseWithObject([FBScreenRecordingContainer.sharedInstance toDictionary]); +} + ++ (id)handleStopVideoRecording:(FBRouteRequest *)request +{ + FBScreenRecordingPromise *activeScreenRecording = FBScreenRecordingContainer.sharedInstance.screenRecordingPromise; + if (nil == activeScreenRecording) { + return FBResponseWithOK(); + } + + NSUUID *recordingId = activeScreenRecording.identifier; + NSDictionary *response = [FBScreenRecordingContainer.sharedInstance toDictionary]; + NSError *error; + if (![FBXCTestDaemonsProxy stopScreenRecordingWithUUID:recordingId error:&error]) { + [FBScreenRecordingContainer.sharedInstance reset]; + return FBResponseWithUnknownError(error); + } + [FBScreenRecordingContainer.sharedInstance reset]; + return FBResponseWithObject(response); +} + ++ (id)handleGetVideoRecording:(FBRouteRequest *)request +{ + return FBResponseWithObject([FBScreenRecordingContainer.sharedInstance toDictionary] ?: [NSNull null]); +} + +@end diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingContainer.h b/WebDriverAgentLib/Routing/FBScreenRecordingContainer.h new file mode 100644 index 000000000..48e5c7481 --- /dev/null +++ b/WebDriverAgentLib/Routing/FBScreenRecordingContainer.h @@ -0,0 +1,57 @@ +/** + * + * 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 + +@class FBScreenRecordingPromise; + +@interface FBScreenRecordingContainer : NSObject + +/** The amount of video FPS */ +@property (readonly, nonatomic) NSUInteger fps; +/** Codec to use, where 0 is h264, 1 - HEVC */ +@property (readonly, nonatomic) long long codec; +/** Keep the currently active screen resording promise. Equals to nil if no active screen recordings are running */ +@property (readonly, nonatomic, nullable) FBScreenRecordingPromise* screenRecordingPromise; +/** The timestamp of the video startup as Unix float seconds */ +@property (readonly, nonatomic, nullable) NSNumber *startedAt; + +/** +@return singleton instance + */ ++ (instancetype)sharedInstance; + +/** + Keeps current screen recording promise + + @param screenRecordingPromise a promise to set + @param fps FPS value + @param codec Codec value + */ +- (void)storeScreenRecordingPromise:(FBScreenRecordingPromise *)screenRecordingPromise + fps:(NSUInteger)fps + codec:(long long)codec; +/** + Resets the current screen recording promise + */ +- (void)reset; + +/** + Transforms the container content to a dictionary. + + @return May return nil if no screen recording is currently running + */ +- (nullable NSDictionary *)toDictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingContainer.m b/WebDriverAgentLib/Routing/FBScreenRecordingContainer.m new file mode 100644 index 000000000..b0a744dc0 --- /dev/null +++ b/WebDriverAgentLib/Routing/FBScreenRecordingContainer.m @@ -0,0 +1,73 @@ +/** + * + * 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 "FBScreenRecordingContainer.h" + +#import "FBScreenRecordingPromise.h" + +@interface FBScreenRecordingContainer () + +@property (readwrite) NSUInteger fps; +@property (readwrite) long long codec; +@property (readwrite) FBScreenRecordingPromise* screenRecordingPromise; +@property (readwrite) NSNumber *startedAt; + +@end + +@implementation FBScreenRecordingContainer + ++ (instancetype)sharedInstance +{ + static FBScreenRecordingContainer *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +- (void)storeScreenRecordingPromise:(FBScreenRecordingPromise *)screenRecordingPromise + fps:(NSUInteger)fps + codec:(long long)codec; +{ + self.fps = fps; + self.codec = codec; + self.screenRecordingPromise = screenRecordingPromise; + self.startedAt = @([NSDate.date timeIntervalSince1970]); +} + +- (void)reset; +{ + self.fps = 0; + self.codec = 0; + if (nil != self.screenRecordingPromise) { + [XCTContext runActivityNamed:@"Video Cleanup" block:^(id activity){ + [activity addAttachment:(XCTAttachment *)self.screenRecordingPromise.nativePromise]; + }]; + self.screenRecordingPromise = nil; + } + self.startedAt = nil; +} + +- (nullable NSDictionary *)toDictionary +{ + if (nil == self.screenRecordingPromise) { + return nil; + } + + return @{ + @"fps": @(self.fps), + @"codec": @(self.codec), + @"uuid": [self.screenRecordingPromise identifier].UUIDString ?: [NSNull null], + @"startedAt": self.startedAt ?: [NSNull null], + }; +} + +@end diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingPromise.h b/WebDriverAgentLib/Routing/FBScreenRecordingPromise.h new file mode 100644 index 000000000..a86918761 --- /dev/null +++ b/WebDriverAgentLib/Routing/FBScreenRecordingPromise.h @@ -0,0 +1,30 @@ +/** + * 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 FBScreenRecordingPromise : NSObject + +/** Unique identiifier of the video recording, also used as the default file name */ +@property (nonatomic, readonly) NSUUID *identifier; +/** Native screen recording promise */ +@property (nonatomic, readonly) id nativePromise; + +/** + Creates a wrapper object for a native screen recording promise + + @param promise Native promise object to be wrapped + */ +- (instancetype)initWithNativePromise:(id)promise; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingPromise.m b/WebDriverAgentLib/Routing/FBScreenRecordingPromise.m new file mode 100644 index 000000000..9de9dbaf1 --- /dev/null +++ b/WebDriverAgentLib/Routing/FBScreenRecordingPromise.m @@ -0,0 +1,32 @@ +/** + * + * 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 "FBScreenRecordingPromise.h" + +@interface FBScreenRecordingPromise () +@property (readwrite) id nativePromise; +@end + +@implementation FBScreenRecordingPromise + +- (instancetype)initWithNativePromise:(id)promise +{ + if ((self = [super init])) { + self.nativePromise = promise; + } + return self; +} + +- (NSUUID *)identifier +{ + return (NSUUID *)[self.nativePromise valueForKey:@"_UUID"]; +} + +@end diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingRequest.h b/WebDriverAgentLib/Routing/FBScreenRecordingRequest.h new file mode 100644 index 000000000..5e24e5588 --- /dev/null +++ b/WebDriverAgentLib/Routing/FBScreenRecordingRequest.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 FBScreenRecordingRequest : NSObject + +/** The amount of video FPS */ +@property (readonly, nonatomic) NSUInteger fps; +/** Codec to use, where 0 is h264, 1 - HEVC */ +@property (readonly, nonatomic) long long codec; + +/** + Creates a custom wrapper for a screen recording reqeust + + @param fps FPS value, see baove + @param codec Codex value, see above + */ +- (instancetype)initWithFps:(NSUInteger)fps codec:(long long)codec; + +/** + Transforms the current wrapper instance to a native object, + which is ready to be passed to XCTest APIs + + @param error If there was a failure converting the instance to a native object + @returns Native object instance + */ +- (nullable id)toNativeRequestWithError:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m b/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m new file mode 100644 index 000000000..5249b76b0 --- /dev/null +++ b/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m @@ -0,0 +1,95 @@ +/** + * 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 "FBScreenRecordingRequest.h" + +#import "FBErrorBuilder.h" +#import "XCUIScreen.h" + +@implementation FBScreenRecordingRequest + +- (instancetype)initWithFps:(NSUInteger)fps codec:(long long)codec +{ + if ((self = [super init])) { + _fps = fps; + _codec = codec; + } + return self; +} + +- (nullable id)createVideoEncodingWithError:(NSError **)error +{ + Class videoEncodingClass = NSClassFromString(@"XCTVideoEncoding"); + if (nil == videoEncodingClass) { + [[[FBErrorBuilder builder] + withDescription:@"Cannot find XCTVideoEncoding class"] + buildError:error]; + return nil; + } + + id videoEncodingAllocated = [videoEncodingClass alloc]; + SEL videoEncodingConstructorSelector = NSSelectorFromString(@"initWithCodec:frameRate:"); + if (![videoEncodingAllocated respondsToSelector:videoEncodingConstructorSelector]) { + [[[FBErrorBuilder builder] + withDescription:@"'initWithCodec:frameRate:' contructor is not found on XCTVideoEncoding class"] + buildError:error]; + return nil; + } + + NSMethodSignature *videoEncodingContructorSignature = [videoEncodingAllocated methodSignatureForSelector:videoEncodingConstructorSelector]; + NSInvocation *videoEncodingInitInvocation = [NSInvocation invocationWithMethodSignature:videoEncodingContructorSignature]; + [videoEncodingInitInvocation setSelector:videoEncodingConstructorSelector]; + long long codec = self.codec; + [videoEncodingInitInvocation setArgument:&codec atIndex:2]; + double frameRate = self.fps; + [videoEncodingInitInvocation setArgument:&frameRate atIndex:3]; + [videoEncodingInitInvocation invokeWithTarget:videoEncodingAllocated]; + id __unsafe_unretained result; + [videoEncodingInitInvocation getReturnValue:&result]; + return result; +} + +- (id)toNativeRequestWithError:(NSError **)error +{ + Class screenRecordingRequestClass = NSClassFromString(@"XCTScreenRecordingRequest"); + if (nil == screenRecordingRequestClass) { + [[[FBErrorBuilder builder] + withDescription:@"Cannot find XCTScreenRecordingRequest class"] + buildError:error]; + return nil; + } + + id screenRecordingRequestAllocated = [screenRecordingRequestClass alloc]; + SEL screenRecordingRequestConstructorSelector = NSSelectorFromString(@"initWithScreenID:rect:preferredEncoding:"); + if (![screenRecordingRequestAllocated respondsToSelector:screenRecordingRequestConstructorSelector]) { + [[[FBErrorBuilder builder] + withDescription:@"'initWithScreenID:rect:preferredEncoding:' contructor is not found on XCTScreenRecordingRequest class"] + buildError:error]; + return nil; + } + id videoEncoding = [self createVideoEncodingWithError:error]; + if (nil == videoEncoding) { + return nil; + } + + NSMethodSignature *screenRecordingRequestContructorSignature = [screenRecordingRequestAllocated methodSignatureForSelector:screenRecordingRequestConstructorSelector]; + NSInvocation *screenRecordingRequestInitInvocation = [NSInvocation invocationWithMethodSignature:screenRecordingRequestContructorSignature]; + [screenRecordingRequestInitInvocation setSelector:screenRecordingRequestConstructorSelector]; + long long mainScreenId = XCUIScreen.mainScreen.displayID; + [screenRecordingRequestInitInvocation setArgument:&mainScreenId atIndex:2]; + CGRect fullScreenRect = CGRectNull; + [screenRecordingRequestInitInvocation setArgument:&fullScreenRect atIndex:3]; + [screenRecordingRequestInitInvocation setArgument:&videoEncoding atIndex:4]; + [screenRecordingRequestInitInvocation invokeWithTarget:screenRecordingRequestAllocated]; + id __unsafe_unretained result; + [screenRecordingRequestInitInvocation getReturnValue:&result]; + return result; +} + +@end diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index 888cff8b2..d70c53432 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -18,7 +18,11 @@ #import "FBElementCache.h" #import "FBExceptions.h" #import "FBMacros.h" +#import "FBScreenRecordingContainer.h" +#import "FBScreenRecordingPromise.h" +#import "FBScreenRecordingRequest.h" #import "FBXCodeCompatibility.h" +#import "FBXCTestDaemonsProxy.h" #import "XCUIApplication+FBQuiescence.h" #import "XCUIElement.h" @@ -137,6 +141,15 @@ - (void)kill self.alertsMonitor = nil; } + FBScreenRecordingPromise *activeScreenRecording = FBScreenRecordingContainer.sharedInstance.screenRecordingPromise; + if (nil != activeScreenRecording) { + NSError *error; + if (![FBXCTestDaemonsProxy stopScreenRecordingWithUUID:activeScreenRecording.identifier error:&error]) { + [FBLogger logFmt:@"%@", error]; + } + [FBScreenRecordingContainer.sharedInstance reset]; + } + if (nil != self.testedApplication && FBConfiguration.shouldTerminateApp && self.testedApplication.running diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h index 307edb40d..18761248b 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h @@ -18,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol XCTestManager_ManagerInterface; +@class FBScreenRecordingRequest, FBScreenRecordingPromise; @interface FBXCTestDaemonsProxy : NSObject @@ -29,6 +30,11 @@ NS_ASSUME_NONNULL_BEGIN + (BOOL)openURL:(NSURL *)url usingApplication:(NSString *)bundleId error:(NSError **)error; + (BOOL)openDefaultApplicationForURL:(NSURL *)url error:(NSError **)error; ++ (nullable FBScreenRecordingPromise *)startScreenRecordingWithRequest:(FBScreenRecordingRequest *)request + error:(NSError **)error; ++ (BOOL)stopScreenRecordingWithUUID:(NSUUID *)uuid + error:(NSError **)error; + #if !TARGET_OS_TV + (BOOL)setSimulatedLocation:(CLLocation *)location error:(NSError **)error; + (nullable CLLocation *)getSimulatedLocation:(NSError **)error; diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m index 180689800..f71e1bd3d 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m @@ -16,6 +16,8 @@ #import "FBExceptions.h" #import "FBLogger.h" #import "FBRunLoopSpinner.h" +#import "FBScreenRecordingPromise.h" +#import "FBScreenRecordingRequest.h" #import "XCTestDriver.h" #import "XCTRunnerDaemonSession.h" #import "XCUIApplication.h" @@ -129,10 +131,9 @@ + (BOOL)openURL:(NSURL *)url usingApplication:(NSString *)bundleId error:(NSErro { XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(openURL:usingApplication:completion:)]) { - [[[FBErrorBuilder builder] + return [[[FBErrorBuilder builder] withDescriptionFormat:@"The current Xcode SDK does not support opening of URLs with given application"] buildError:error]; - return NO; } __block NSError *innerError = nil; @@ -157,10 +158,9 @@ + (BOOL)openDefaultApplicationForURL:(NSURL *)url error:(NSError *__autoreleasin { XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(openDefaultApplicationForURL:completion:)]) { - [[[FBErrorBuilder builder] + return [[[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; @@ -186,16 +186,14 @@ + (BOOL)setSimulatedLocation:(CLLocation *)location error:(NSError *__autoreleas { XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(setSimulatedLocation:completion:)]) { - [[[FBErrorBuilder builder] + return [[[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]) { - [[[FBErrorBuilder builder] + return [[[FBErrorBuilder builder] withDescriptionFormat:@"Your device does not support location simulation"] buildError:error]; - return NO; } __block NSError *innerError = nil; @@ -254,20 +252,14 @@ + (BOOL)clearSimulatedLocation:(NSError *__autoreleasing*)error { XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; if (![session respondsToSelector:@selector(clearSimulatedLocationWithReply:)]) { - if (error) { - [[[FBErrorBuilder builder] + return [[[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] + return [[[FBErrorBuilder builder] withDescriptionFormat:@"Your device does not support location simulation"] buildError:error]; - } - return NO; } __block NSError *innerError = nil; @@ -289,4 +281,77 @@ + (BOOL)clearSimulatedLocation:(NSError *__autoreleasing*)error } #endif ++ (FBScreenRecordingPromise *)startScreenRecordingWithRequest:(FBScreenRecordingRequest *)request + error:(NSError *__autoreleasing*)error +{ + XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; + if (![session respondsToSelector:@selector(startScreenRecordingWithRequest:withReply:)]) { + [[[FBErrorBuilder builder] + withDescriptionFormat:@"The current Xcode SDK does not support screen recording. Consider upgrading to Xcode 15+/iOS 17+"] + buildError:error]; + return nil; + } + if (![session supportsScreenRecording]) { + [[[FBErrorBuilder builder] + withDescriptionFormat:@"Your device does not support screen recording"] + buildError:error]; + return nil; + } + + id nativeRequest = [request toNativeRequestWithError:error]; + if (nil == nativeRequest) { + return nil; + } + + __block id futureMetadata = nil; + __block NSError *innerError = nil; + [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ + [session startScreenRecordingWithRequest:nativeRequest withReply:^(id reply, NSError *invokeError) { + if (nil == invokeError) { + futureMetadata = reply; + } else { + innerError = invokeError; + } + completion(); + }]; + }]; + if (nil != innerError) { + if (error) { + *error = innerError; + } + return nil; + } + return [[FBScreenRecordingPromise alloc] initWithNativePromise:futureMetadata]; +} + ++ (BOOL)stopScreenRecordingWithUUID:(NSUUID *)uuid error:(NSError *__autoreleasing*)error +{ + XCTRunnerDaemonSession *session = [XCTRunnerDaemonSession sharedSession]; + if (![session respondsToSelector:@selector(stopScreenRecordingWithUUID:withReply:)]) { + return [[[FBErrorBuilder builder] + withDescriptionFormat:@"The current Xcode SDK does not support screen recording. Consider upgrading to Xcode 15+/iOS 17+"] + buildError:error]; + + } + if (![session supportsScreenRecording]) { + return [[[FBErrorBuilder builder] + withDescriptionFormat:@"Your device does not support screen recording"] + buildError:error]; + } + + __block NSError *innerError = nil; + [FBRunLoopSpinner spinUntilCompletion:^(void(^completion)(void)){ + [session stopScreenRecordingWithUUID:uuid withReply:^(NSError *invokeError) { + if (nil != invokeError) { + innerError = invokeError; + } + completion(); + }]; + }]; + if (nil != innerError && error) { + *error = innerError; + } + return nil == innerError; +} + @end diff --git a/WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m b/WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m new file mode 100644 index 000000000..617480c0c --- /dev/null +++ b/WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m @@ -0,0 +1,63 @@ +/** + * 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 "FBIntegrationTestCase.h" + +#import "FBConfiguration.h" +#import "FBMacros.h" +#import "FBScreenRecordingPromise.h" +#import "FBScreenRecordingRequest.h" +#import "FBScreenRecordingContainer.h" +#import "FBXCTestDaemonsProxy.h" + +@interface FBVideoRecordingTests : FBIntegrationTestCase +@end + +@implementation FBVideoRecordingTests + +- (void)setUp +{ + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"DisableDiagnosticScreenRecordings"]; + [super setUp]; +} + +- (void)testStartingAndStoppingVideoRecording +{ + // Video recording is only available since iOS 17 + if (SYSTEM_VERSION_LESS_THAN(@"17.0")) { + return; + } + + FBScreenRecordingRequest *recordingRequest = [[FBScreenRecordingRequest alloc] initWithFps:24 + codec:0]; + NSError *error; + FBScreenRecordingPromise *promise = [FBXCTestDaemonsProxy startScreenRecordingWithRequest:recordingRequest + error:&error]; + XCTAssertNotNil(promise); + XCTAssertNotNil(promise.identifier); + XCTAssertNil(error); + + [FBScreenRecordingContainer.sharedInstance storeScreenRecordingPromise:promise + fps:24 + codec:0]; + XCTAssertEqual(FBScreenRecordingContainer.sharedInstance.screenRecordingPromise, promise); + + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.]]; + + BOOL isSuccessfull = [FBXCTestDaemonsProxy stopScreenRecordingWithUUID:promise.identifier error:&error]; + XCTAssertTrue(isSuccessfull); + XCTAssertNil(error); + + [FBScreenRecordingContainer.sharedInstance reset]; + XCTAssertNil(FBScreenRecordingContainer.sharedInstance.screenRecordingPromise); +} + +@end From 0a28987a7a1adb265e4b1251087b46f40ef968fd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 7 Mar 2024 16:15:12 +0000 Subject: [PATCH 032/368] chore(release): 7.1.0 [skip ci] ## [7.1.0](https://github.com/appium/WebDriverAgent/compare/v7.0.6...v7.1.0) (2024-03-07) ### Features * Add wrappers for native XCTest video recorder ([#858](https://github.com/appium/WebDriverAgent/issues/858)) ([9728548](https://github.com/appium/WebDriverAgent/commit/9728548676c8de67c30d127ee8b0374f58286e74)) ### Miscellaneous Chores * bump typescript ([89880f5](https://github.com/appium/WebDriverAgent/commit/89880f509f930f16f6469bcda613569040c337b6)) --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 660ff5544..faa1eb8d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [7.1.0](https://github.com/appium/WebDriverAgent/compare/v7.0.6...v7.1.0) (2024-03-07) + + +### Features + +* Add wrappers for native XCTest video recorder ([#858](https://github.com/appium/WebDriverAgent/issues/858)) ([9728548](https://github.com/appium/WebDriverAgent/commit/9728548676c8de67c30d127ee8b0374f58286e74)) + + +### Miscellaneous Chores + +* bump typescript ([89880f5](https://github.com/appium/WebDriverAgent/commit/89880f509f930f16f6469bcda613569040c337b6)) + ## [7.0.6](https://github.com/appium/WebDriverAgent/compare/v7.0.5...v7.0.6) (2024-03-03) diff --git a/package.json b/package.json index 0028b6843..f2dee046c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.0.6", + "version": "7.1.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From b1ddae2be3fd3f7c87de79e804d82cf7c13dc56e Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 13 Mar 2024 11:47:18 -0700 Subject: [PATCH 033/368] fix: respect defaultActiveApplication in activeApplication selection (#862) * chore: respect defaultActiveApplication * return immediately if the given defaultActiveApplication was already foreground * move the foreground check prior than the self.testedApplication * move is auto detection --- WebDriverAgentLib/Routing/FBSession.m | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index d70c53432..82134e0cc 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -166,6 +166,13 @@ - (void)kill - (XCUIApplication *)activeApplication { + BOOL isAuto = [self.defaultActiveApplication isEqualToString:FBDefaultApplicationAuto]; + NSString *defaultBundleId = isAuto ? nil : self.defaultActiveApplication; + + if (nil != defaultBundleId && [self applicationStateWithBundleId:defaultBundleId] >= XCUIApplicationStateRunningForeground) { + return [self makeApplicationWithBundleId:defaultBundleId]; + } + if (nil != self.testedApplication) { XCUIApplicationState testedAppState = self.testedApplication.state; if (testedAppState >= XCUIApplicationStateRunningForeground) { @@ -177,9 +184,6 @@ - (XCUIApplication *)activeApplication } } - NSString *defaultBundleId = [self.defaultActiveApplication isEqualToString:FBDefaultApplicationAuto] - ? nil - : self.defaultActiveApplication; return [XCUIApplication fb_activeApplicationWithDefaultBundleId:defaultBundleId]; } From c623975e9114bcead00bd0dc26c0ec5e55e356e4 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 13 Mar 2024 18:51:22 +0000 Subject: [PATCH 034/368] chore(release): 7.1.1 [skip ci] ## [7.1.1](https://github.com/appium/WebDriverAgent/compare/v7.1.0...v7.1.1) (2024-03-13) ### Bug Fixes * respect defaultActiveApplication in activeApplication selection ([#862](https://github.com/appium/WebDriverAgent/issues/862)) ([b1ddae2](https://github.com/appium/WebDriverAgent/commit/b1ddae2be3fd3f7c87de79e804d82cf7c13dc56e)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index faa1eb8d5..e4dcc6cc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.1.1](https://github.com/appium/WebDriverAgent/compare/v7.1.0...v7.1.1) (2024-03-13) + + +### Bug Fixes + +* respect defaultActiveApplication in activeApplication selection ([#862](https://github.com/appium/WebDriverAgent/issues/862)) ([b1ddae2](https://github.com/appium/WebDriverAgent/commit/b1ddae2be3fd3f7c87de79e804d82cf7c13dc56e)) + ## [7.1.0](https://github.com/appium/WebDriverAgent/compare/v7.0.6...v7.1.0) (2024-03-07) diff --git a/package.json b/package.json index f2dee046c..81fd20534 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.1.0", + "version": "7.1.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 6dbfb3f2ec8e0bfa5a42c6f8ab882893bfe3f534 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 14 Mar 2024 07:31:23 +0100 Subject: [PATCH 035/368] fix: Always assume en0 is the WiFi interface (#864) --- WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h | 2 +- WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h index e60efaa48..ca7fc53d8 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h @@ -70,7 +70,7 @@ typedef NS_ENUM(NSUInteger, FBUIInterfaceAppearance) { - (nullable NSData *)fb_screenshotWithError:(NSError*__autoreleasing*)error; /** - Returns device current wifi ip4 address + Returns device's current wifi ip4 address */ - (nullable NSString *)fb_wifiIPAddress; diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m index 5b95b8c62..ef8664fb6 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m @@ -134,7 +134,7 @@ - (NSString *)fb_wifiIPAddress continue; } NSString *interfaceName = [NSString stringWithUTF8String:temp_addr->ifa_name]; - if(![interfaceName containsString:@"en"]) { + if(![interfaceName isEqualToString:@"en0"]) { temp_addr = temp_addr->ifa_next; continue; } From 8c868dca02269cd40ef50c0746f265bcf603baa0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 14 Mar 2024 06:35:55 +0000 Subject: [PATCH 036/368] chore(release): 7.1.2 [skip ci] ## [7.1.2](https://github.com/appium/WebDriverAgent/compare/v7.1.1...v7.1.2) (2024-03-14) ### Bug Fixes * Always assume en0 is the WiFi interface ([#864](https://github.com/appium/WebDriverAgent/issues/864)) ([6dbfb3f](https://github.com/appium/WebDriverAgent/commit/6dbfb3f2ec8e0bfa5a42c6f8ab882893bfe3f534)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4dcc6cc2..1a487bf16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.1.2](https://github.com/appium/WebDriverAgent/compare/v7.1.1...v7.1.2) (2024-03-14) + + +### Bug Fixes + +* Always assume en0 is the WiFi interface ([#864](https://github.com/appium/WebDriverAgent/issues/864)) ([6dbfb3f](https://github.com/appium/WebDriverAgent/commit/6dbfb3f2ec8e0bfa5a42c6f8ab882893bfe3f534)) + ## [7.1.1](https://github.com/appium/WebDriverAgent/compare/v7.1.0...v7.1.1) (2024-03-13) diff --git a/package.json b/package.json index 81fd20534..99e7d6832 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.1.1", + "version": "7.1.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 7c684e2def9dd968de1cf89e4ec26403a52ba805 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 21 Mar 2024 10:55:00 +0100 Subject: [PATCH 037/368] feat: Enable usePreinstalledWDA feature for simulators (#866) --- lib/webdriveragent.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index fdae2bff6..a80909954 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -301,9 +301,19 @@ class WebDriverAgent { 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(); + if (this.isRealDevice) { + this.xctestApiClient = new Xctest(this.device.udid, this.bundleIdForXctest, null, {env: xctestEnv}); + await this.xctestApiClient.start(); + } else { + await this.device.simctl.exec('launch', { + args: [ + '--terminate-running-process', + this.device.udid, + this.bundleIdForXctest, + ], + env: xctestEnv, + }); + } this.setupProxies(sessionId); const status = await this.getStatus(); @@ -343,10 +353,7 @@ class WebDriverAgent { } if (this.usePreinstalledWDA) { - if (this.isRealDevice) { - return await this.launchWithPreinstalledWDA(sessionId); - } - throw new Error('usePreinstalledWDA is available only for a real device.'); + return await this.launchWithPreinstalledWDA(sessionId); } this.log.info('Launching WebDriverAgent on the device'); @@ -460,10 +467,16 @@ class WebDriverAgent { async quit () { if (this.usePreinstalledWDA) { + this.log.info('Stopping the XCTest session'); if (this.xctestApiClient) { - this.log.info('Stopping the XCTest session'); this.xctestApiClient.stop(); this.xctestApiClient = null; + } else { + try { + await this.device.simctl.terminateApp(this.bundleIdForXctest); + } catch (e) { + this.log.warn(e.message); + } } } else if (!this.args.webDriverAgentUrl) { this.log.info('Shutting down sub-processes'); From f42fb707e6e887ec6aa6784ffc141adc6adf3350 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 21 Mar 2024 10:00:39 +0000 Subject: [PATCH 038/368] chore(release): 7.2.0 [skip ci] ## [7.2.0](https://github.com/appium/WebDriverAgent/compare/v7.1.2...v7.2.0) (2024-03-21) ### Features * Enable usePreinstalledWDA feature for simulators ([#866](https://github.com/appium/WebDriverAgent/issues/866)) ([7c684e2](https://github.com/appium/WebDriverAgent/commit/7c684e2def9dd968de1cf89e4ec26403a52ba805)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a487bf16..a98d10c3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.2.0](https://github.com/appium/WebDriverAgent/compare/v7.1.2...v7.2.0) (2024-03-21) + + +### Features + +* Enable usePreinstalledWDA feature for simulators ([#866](https://github.com/appium/WebDriverAgent/issues/866)) ([7c684e2](https://github.com/appium/WebDriverAgent/commit/7c684e2def9dd968de1cf89e4ec26403a52ba805)) + ## [7.1.2](https://github.com/appium/WebDriverAgent/compare/v7.1.1...v7.1.2) (2024-03-14) diff --git a/package.json b/package.json index 99e7d6832..ed8374537 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.1.2", + "version": "7.2.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 39194d4ac6d0072c1214088ff5c15c986969914c Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 23 Mar 2024 11:34:45 -0700 Subject: [PATCH 039/368] feat: Support prebuiltWDAPath for iOS 17 (#868) * feat: add a method to launch wda via devicectl * reflect review and updates * update type, use waitForCondition * adjust * fix lint * update review --- lib/webdriveragent.js | 83 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index a80909954..0d3a60188 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -1,3 +1,4 @@ +import { waitForCondition } from 'asyncbox'; import _ from 'lodash'; import path from 'path'; import url from 'url'; @@ -66,6 +67,7 @@ class WebDriverAgent { this.updatedWDABundleId = args.updatedWDABundleId; + this.wdaLaunchTimeout = args.wdaLaunchTimeout || WDA_LAUNCH_TIMEOUT; this.usePreinstalledWDA = args.usePreinstalledWDA; this.xctestApiClient = null; @@ -87,7 +89,7 @@ class WebDriverAgent { useSimpleBuildTest: args.useSimpleBuildTest, usePrebuiltWDA: args.usePrebuiltWDA, updatedWDABundleId: this.updatedWDABundleId, - launchTimeout: args.wdaLaunchTimeout || WDA_LAUNCH_TIMEOUT, + launchTimeout: this.wdaLaunchTimeout, wdaRemotePort: this.wdaRemotePort, useXctestrunFile: this.useXctestrunFile, derivedDataPath: args.derivedDataPath, @@ -184,7 +186,6 @@ class WebDriverAgent { * } * * @return {Promise} State Object - * @throws {Error} If there was invalid response code or body */ async getStatus () { const noSessionProxy = new NoSessionProxy({ @@ -287,6 +288,73 @@ class WebDriverAgent { } } + + /** + * @typedef {Object} LaunchWdaViaDeviceCtlOptions + * @property {Record} [env] environment variables for the launching WDA process + */ + + /** + * Launch WDA with preinstalled package with 'xcrun devicectl device process launch'. + * The WDA package must be prepared properly like published via + * https://github.com/appium/WebDriverAgent/releases + * with proper sign for this case. + * + * When we implement launching XCTest service via appium-ios-device, + * this implementation can be replaced with it. + * + * @param {LaunchWdaViaDeviceCtlOptions} [opts={}] launching WDA with devicectl command options. + * @return {Promise} + */ + async _launchViaDevicectl(opts = {}) { + // FIXME: use appium-xcuitest-driver's Devicectl. Maybe it needs to be included in the `this.device`? + // + + const {env} = opts; + + let xcrunBinnaryPath; + try { + xcrunBinnaryPath = await fs.which('xcrun'); + } catch (e) { + throw new Error( + `xcrun has not been found in PATH. ` + + `Please make sure XCode development tools are installed`, + ); + } + + const cmd = [ + 'devicectl', + 'device', + 'process', + 'launch', + `--device`, this.device.udid, + '--terminate-existing' + ]; + if (!_.isEmpty(env)) { + cmd.push('--environment-variables', JSON.stringify(_.mapValues(env, (v) => _.toString(v)))); + }; + cmd.push(this.bundleIdForXctest); + + const {stdout} = await exec(xcrunBinnaryPath, cmd); + this.log.debug(`The output of devicectl command: ${stdout}`); + + // Launching app via decictl does not wait for the app start. + // We should wait for the app start by ourselves. + try { + await waitForCondition(async () => !_.isNull(await this.getStatus()), { + waitMs: this.wdaLaunchTimeout, + intervalMs: 300, + }); + + } catch (err) { + throw new Error( + `Failed to start the preinstalled WebDriverAgent in ${this.wdaLaunchTimeout} ms. ` + + `The WebDriverAgent might not be properly built or the device might be locked. ` + + 'appium:wdaLaunchTimeout capability modifies the timeout.' + ); + } + } + /** * Launch WDA with preinstalled package without xcodebuild. * @param {string} sessionId Launch WDA and establish the session with this sessionId @@ -302,8 +370,15 @@ class WebDriverAgent { } this.log.info('Launching WebDriverAgent on the device without xcodebuild'); if (this.isRealDevice) { - this.xctestApiClient = new Xctest(this.device.udid, this.bundleIdForXctest, null, {env: xctestEnv}); - await this.xctestApiClient.start(); + // Current method to launch WDA process can be done via 'xcrun devicectl', + // but it has limitation about the WDA preinstalled package. + // https://github.com/appium/appium/issues/19206#issuecomment-2014182674 + if (util.compareVersions(this.platformVersion, '>=', '17.0')) { + await this._launchViaDevicectl({env: xctestEnv}); + } else { + this.xctestApiClient = new Xctest(this.device.udid, this.bundleIdForXctest, null, {env: xctestEnv}); + await this.xctestApiClient.start(); + } } else { await this.device.simctl.exec('launch', { args: [ From 10743e7714ea857e2844ece6a1d9e6d76cfe4be9 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 23 Mar 2024 18:50:28 +0000 Subject: [PATCH 040/368] chore(release): 7.3.0 [skip ci] ## [7.3.0](https://github.com/appium/WebDriverAgent/compare/v7.2.0...v7.3.0) (2024-03-23) ### Features * Support prebuiltWDAPath for iOS 17 ([#868](https://github.com/appium/WebDriverAgent/issues/868)) ([39194d4](https://github.com/appium/WebDriverAgent/commit/39194d4ac6d0072c1214088ff5c15c986969914c)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a98d10c3f..3025d7b98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.3.0](https://github.com/appium/WebDriverAgent/compare/v7.2.0...v7.3.0) (2024-03-23) + + +### Features + +* Support prebuiltWDAPath for iOS 17 ([#868](https://github.com/appium/WebDriverAgent/issues/868)) ([39194d4](https://github.com/appium/WebDriverAgent/commit/39194d4ac6d0072c1214088ff5c15c986969914c)) + ## [7.2.0](https://github.com/appium/WebDriverAgent/compare/v7.1.2...v7.2.0) (2024-03-21) diff --git a/package.json b/package.json index ed8374537..587b5f539 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.2.0", + "version": "7.3.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 90337597e6c480c790cf299e160bc53731c0a87d Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 24 Mar 2024 01:32:11 -0700 Subject: [PATCH 041/368] chore: move node-simctl to dev deps (#869) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 587b5f539..03d62d841 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "eslint-plugin-import": "^2.28.0", "eslint-plugin-mocha": "^10.1.0", "eslint-plugin-promise": "^6.1.1", + "node-simctl": "^7.0.1", "mocha": "^10.0.0", "prettier": "^3.0.0", "semantic-release": "^23.0.0", @@ -91,7 +92,6 @@ "axios": "^1.4.0", "bluebird": "^3.5.5", "lodash": "^4.17.11", - "node-simctl": "^7.0.1", "source-map-support": "^0.x", "teen_process": "^2.0.0" }, From d7dc6c64d01d018c8f2bacb1351ac1f873ce0171 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 24 Mar 2024 08:52:34 +0000 Subject: [PATCH 042/368] chore(release): 7.3.1 [skip ci] ## [7.3.1](https://github.com/appium/WebDriverAgent/compare/v7.3.0...v7.3.1) (2024-03-24) ### Miscellaneous Chores * move node-simctl to dev deps ([#869](https://github.com/appium/WebDriverAgent/issues/869)) ([9033759](https://github.com/appium/WebDriverAgent/commit/90337597e6c480c790cf299e160bc53731c0a87d)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3025d7b98..dffe1af31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.3.1](https://github.com/appium/WebDriverAgent/compare/v7.3.0...v7.3.1) (2024-03-24) + + +### Miscellaneous Chores + +* move node-simctl to dev deps ([#869](https://github.com/appium/WebDriverAgent/issues/869)) ([9033759](https://github.com/appium/WebDriverAgent/commit/90337597e6c480c790cf299e160bc53731c0a87d)) + ## [7.3.0](https://github.com/appium/WebDriverAgent/compare/v7.2.0...v7.3.0) (2024-03-23) diff --git a/package.json b/package.json index 03d62d841..97cc267ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.3.0", + "version": "7.3.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 090b815ae47e1ef0e0a9842fac6828346bc38fe6 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 25 Mar 2024 00:32:03 -0700 Subject: [PATCH 043/368] feat: launch WDA via devicectl object (#870) BREAKING CHANGE: calls launch app process command with devicectl via this.device.devicectl --- lib/webdriveragent.js | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 0d3a60188..11aec45f9 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -307,36 +307,11 @@ class WebDriverAgent { * @return {Promise} */ async _launchViaDevicectl(opts = {}) { - // FIXME: use appium-xcuitest-driver's Devicectl. Maybe it needs to be included in the `this.device`? - // - const {env} = opts; - let xcrunBinnaryPath; - try { - xcrunBinnaryPath = await fs.which('xcrun'); - } catch (e) { - throw new Error( - `xcrun has not been found in PATH. ` + - `Please make sure XCode development tools are installed`, - ); - } - - const cmd = [ - 'devicectl', - 'device', - 'process', - 'launch', - `--device`, this.device.udid, - '--terminate-existing' - ]; - if (!_.isEmpty(env)) { - cmd.push('--environment-variables', JSON.stringify(_.mapValues(env, (v) => _.toString(v)))); - }; - cmd.push(this.bundleIdForXctest); - - const {stdout} = await exec(xcrunBinnaryPath, cmd); - this.log.debug(`The output of devicectl command: ${stdout}`); + await this.device.devicectl.launchApp({ + bundleId: this.bundleIdForXctest, env, terminateExisting: true, + }); // Launching app via decictl does not wait for the app start. // We should wait for the app start by ourselves. @@ -350,7 +325,7 @@ class WebDriverAgent { throw new Error( `Failed to start the preinstalled WebDriverAgent in ${this.wdaLaunchTimeout} ms. ` + `The WebDriverAgent might not be properly built or the device might be locked. ` + - 'appium:wdaLaunchTimeout capability modifies the timeout.' + `The 'appium:wdaLaunchTimeout' capability modifies the timeout.` ); } } From 411669b2ef4760b8aff324d642c0e21cb8ecd4da Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 25 Mar 2024 07:42:18 +0000 Subject: [PATCH 044/368] chore(release): 8.0.0 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [8.0.0](https://github.com/appium/WebDriverAgent/compare/v7.3.1...v8.0.0) (2024-03-25) ### ⚠ BREAKING CHANGES * calls launch app process command with devicectl via this.device.devicectl ### Features * launch WDA via devicectl object ([#870](https://github.com/appium/WebDriverAgent/issues/870)) ([090b815](https://github.com/appium/WebDriverAgent/commit/090b815ae47e1ef0e0a9842fac6828346bc38fe6)) --- CHANGELOG.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dffe1af31..bbb267b38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [8.0.0](https://github.com/appium/WebDriverAgent/compare/v7.3.1...v8.0.0) (2024-03-25) + + +### ⚠ BREAKING CHANGES + +* calls launch app process command with devicectl via this.device.devicectl + +### Features + +* launch WDA via devicectl object ([#870](https://github.com/appium/WebDriverAgent/issues/870)) ([090b815](https://github.com/appium/WebDriverAgent/commit/090b815ae47e1ef0e0a9842fac6828346bc38fe6)) + ## [7.3.1](https://github.com/appium/WebDriverAgent/compare/v7.3.0...v7.3.1) (2024-03-24) diff --git a/package.json b/package.json index 97cc267ff..5db4a1c66 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "7.3.1", + "version": "8.0.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From e2aeda2f2020f4014cba478b459e47954175f597 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 26 Mar 2024 01:21:21 -0700 Subject: [PATCH 045/368] chore: use bundle id outside opts for this.device.devicectl.launchApp (#872) --- lib/webdriveragent.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 11aec45f9..113269228 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -309,9 +309,9 @@ class WebDriverAgent { async _launchViaDevicectl(opts = {}) { const {env} = opts; - await this.device.devicectl.launchApp({ - bundleId: this.bundleIdForXctest, env, terminateExisting: true, - }); + await this.device.devicectl.launchApp( + this.bundleIdForXctest, { env, terminateExisting: true } + ); // Launching app via decictl does not wait for the app start. // We should wait for the app start by ourselves. From da589f02ee6c9fb100c6ab96a96775c0bef83a93 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 26 Mar 2024 08:28:50 +0000 Subject: [PATCH 046/368] chore(release): 8.0.1 [skip ci] ## [8.0.1](https://github.com/appium/WebDriverAgent/compare/v8.0.0...v8.0.1) (2024-03-26) ### Miscellaneous Chores * use bundle id outside opts for this.device.devicectl.launchApp ([#872](https://github.com/appium/WebDriverAgent/issues/872)) ([e2aeda2](https://github.com/appium/WebDriverAgent/commit/e2aeda2f2020f4014cba478b459e47954175f597)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbb267b38..36307b7a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.0.1](https://github.com/appium/WebDriverAgent/compare/v8.0.0...v8.0.1) (2024-03-26) + + +### Miscellaneous Chores + +* use bundle id outside opts for this.device.devicectl.launchApp ([#872](https://github.com/appium/WebDriverAgent/issues/872)) ([e2aeda2](https://github.com/appium/WebDriverAgent/commit/e2aeda2f2020f4014cba478b459e47954175f597)) + ## [8.0.0](https://github.com/appium/WebDriverAgent/compare/v7.3.1...v8.0.0) (2024-03-25) diff --git a/package.json b/package.json index 5db4a1c66..0dbff9931 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.0.0", + "version": "8.0.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 72f2a97ec31dbb3c66e5f459e0d7fd417c197d5d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Mar 2024 12:59:48 +0100 Subject: [PATCH 047/368] chore(deps): bump appium-ios-simulator from 5.5.3 to 6.0.0 (#874) Bumps [appium-ios-simulator](https://github.com/appium/appium-ios-simulator) from 5.5.3 to 6.0.0. - [Release notes](https://github.com/appium/appium-ios-simulator/releases) - [Changelog](https://github.com/appium/appium-ios-simulator/blob/master/CHANGELOG.md) - [Commits](https://github.com/appium/appium-ios-simulator/compare/v5.5.3...v6.0.0) --- updated-dependencies: - dependency-name: appium-ios-simulator 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 0dbff9931..4308835ef 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "@appium/strongbox": "^0.x", "@appium/support": "^4.0.0", "appium-ios-device": "^2.5.0", - "appium-ios-simulator": "^5.0.1", + "appium-ios-simulator": "^6.0.0", "async-lock": "^1.0.0", "asyncbox": "^3.0.0", "axios": "^1.4.0", From e86c4b221d1a6f9d4fd75f6ae178ecfeb8b82c63 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 26 Mar 2024 12:14:06 +0000 Subject: [PATCH 048/368] chore(release): 8.0.2 [skip ci] ## [8.0.2](https://github.com/appium/WebDriverAgent/compare/v8.0.1...v8.0.2) (2024-03-26) ### Miscellaneous Chores * **deps:** bump appium-ios-simulator from 5.5.3 to 6.0.0 ([#874](https://github.com/appium/WebDriverAgent/issues/874)) ([72f2a97](https://github.com/appium/WebDriverAgent/commit/72f2a97ec31dbb3c66e5f459e0d7fd417c197d5d)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36307b7a4..72451ba30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.0.2](https://github.com/appium/WebDriverAgent/compare/v8.0.1...v8.0.2) (2024-03-26) + + +### Miscellaneous Chores + +* **deps:** bump appium-ios-simulator from 5.5.3 to 6.0.0 ([#874](https://github.com/appium/WebDriverAgent/issues/874)) ([72f2a97](https://github.com/appium/WebDriverAgent/commit/72f2a97ec31dbb3c66e5f459e0d7fd417c197d5d)) + ## [8.0.1](https://github.com/appium/WebDriverAgent/compare/v8.0.0...v8.0.1) (2024-03-26) diff --git a/package.json b/package.json index 4308835ef..20c0c5080 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.0.1", + "version": "8.0.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From d79b6245966baaa57f7a1f785d7f9b4ea5a7f104 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 26 Mar 2024 11:52:52 -0700 Subject: [PATCH 049/368] feat: add updatedWDABundleIdSuffix to handle bundle id for updatedWDABundleId with usePreinstalledWDA (#871) * feat: do not add xctrunner automatiocally with usePreinstalledWDA * add tests * revert bad commit * tweak if condition * update lint * define updatedWDABundleIdSuffix instead * simplify --- lib/constants.js | 5 ++-- lib/webdriveragent.js | 13 +++++++--- test/unit/webdriveragent-specs.js | 42 +++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/lib/constants.js b/lib/constants.js index 82f005d1c..fd6ed4803 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,7 +1,8 @@ import path from 'path'; +const DEFAULT_TEST_BUNDLE_SUFFIX = '.xctrunner'; const WDA_RUNNER_BUNDLE_ID = 'com.facebook.WebDriverAgentRunner'; -const WDA_RUNNER_BUNDLE_ID_FOR_XCTEST = `${WDA_RUNNER_BUNDLE_ID}.xctrunner`; +const WDA_RUNNER_BUNDLE_ID_FOR_XCTEST = `${WDA_RUNNER_BUNDLE_ID}${DEFAULT_TEST_BUNDLE_SUFFIX}`; const WDA_RUNNER_APP = 'WebDriverAgentRunner-Runner.app'; const WDA_SCHEME = 'WebDriverAgentRunner'; const PROJECT_FILE = 'project.pbxproj'; @@ -19,5 +20,5 @@ 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, - WDA_RUNNER_BUNDLE_ID_FOR_XCTEST + WDA_RUNNER_BUNDLE_ID_FOR_XCTEST, DEFAULT_TEST_BUNDLE_SUFFIX }; diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 113269228..885291e76 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -15,8 +15,8 @@ import AsyncLock from 'async-lock'; 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_RUNNER_BUNDLE_ID, WDA_RUNNER_APP, + WDA_BASE_URL, WDA_UPGRADE_TIMESTAMP_PATH, DEFAULT_TEST_BUNDLE_SUFFIX } from './constants'; import {Xctest} from 'appium-ios-device'; import {strongbox} from '@appium/strongbox'; @@ -70,6 +70,7 @@ class WebDriverAgent { this.wdaLaunchTimeout = args.wdaLaunchTimeout || WDA_LAUNCH_TIMEOUT; this.usePreinstalledWDA = args.usePreinstalledWDA; this.xctestApiClient = null; + this.updatedWDABundleIdSuffix = args.updatedWDABundleIdSuffix ?? DEFAULT_TEST_BUNDLE_SUFFIX; this.xcodebuild = this.canSkipXcodebuild ? null @@ -111,11 +112,15 @@ class WebDriverAgent { } /** + * Return bundle id for WebDriverAgent to launch the WDA. + * The primary usage is with 'this.usePreinstalledWDA'. + * It adds `.xctrunner` as suffix by default but 'this.updatedWDABundleIdSuffix' + * lets skip it. * * @returns {string} Bundle ID for Xctest. */ get bundleIdForXctest () { - return this.updatedWDABundleId ? `${this.updatedWDABundleId}.xctrunner` : WDA_RUNNER_BUNDLE_ID_FOR_XCTEST; + return `${this.updatedWDABundleId ? this.updatedWDABundleId : WDA_RUNNER_BUNDLE_ID}${this.updatedWDABundleIdSuffix}`; } setWDAPaths (bootstrapPath, agentPath) { @@ -449,7 +454,7 @@ class WebDriverAgent { const {wdaBundleId, testBundleId} = await this.prepareWDA(); const env = { USE_PORT: this.wdaRemotePort, - WDA_PRODUCT_BUNDLE_IDENTIFIER: this.updatedWDABundleId, + WDA_PRODUCT_BUNDLE_IDENTIFIER: this.bundleIdForXctest, }; if (this.mjpegServerPort) { env.MJPEG_SERVER_PORT = this.mjpegServerPort; diff --git a/test/unit/webdriveragent-specs.js b/test/unit/webdriveragent-specs.js index 6eac94c5b..7887fbaef 100644 --- a/test/unit/webdriveragent-specs.js +++ b/test/unit/webdriveragent-specs.js @@ -340,3 +340,45 @@ describe('setupCaching()', function () { }); }); }); + + +describe('usePreinstalledWDA related functions', function () { + describe('bundleIdForXctest', function () { + it('should have xctrunner automatically', function () { + const args = Object.assign({}, fakeConstructorArgs); + args.updatedWDABundleId = 'io.appium.wda'; + const agent = new WebDriverAgent({}, args); + agent.bundleIdForXctest.should.equal('io.appium.wda.xctrunner'); + }); + + it('should have xctrunner automatically with default bundle id', function () { + const args = Object.assign({}, fakeConstructorArgs); + const agent = new WebDriverAgent({}, args); + agent.bundleIdForXctest.should.equal('com.facebook.WebDriverAgentRunner.xctrunner'); + }); + + it('should allow an empty string as xctrunner suffix', function () { + const args = Object.assign({}, fakeConstructorArgs); + args.updatedWDABundleId = 'io.appium.wda'; + args.updatedWDABundleIdSuffix = ''; + const agent = new WebDriverAgent({}, args); + agent.bundleIdForXctest.should.equal('io.appium.wda'); + }); + + it('should allow an empty string as xctrunner suffix with default bundle id', function () { + const args = Object.assign({}, fakeConstructorArgs); + args.updatedWDABundleIdSuffix = ''; + const agent = new WebDriverAgent({}, args); + agent.bundleIdForXctest.should.equal('com.facebook.WebDriverAgentRunner'); + }); + + it('should have an arbitrary xctrunner suffix', function () { + const args = Object.assign({}, fakeConstructorArgs); + args.updatedWDABundleId = 'io.appium.wda'; + args.updatedWDABundleIdSuffix = '.customsuffix'; + const agent = new WebDriverAgent({}, args); + agent.bundleIdForXctest.should.equal('io.appium.wda.customsuffix'); + }); + + }); +}); From 1b97df47f5f3485a054823e5bc711b5becadec8d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 26 Mar 2024 18:58:17 +0000 Subject: [PATCH 050/368] chore(release): 8.1.0 [skip ci] ## [8.1.0](https://github.com/appium/WebDriverAgent/compare/v8.0.2...v8.1.0) (2024-03-26) ### Features * add updatedWDABundleIdSuffix to handle bundle id for updatedWDABundleId with usePreinstalledWDA ([#871](https://github.com/appium/WebDriverAgent/issues/871)) ([d79b624](https://github.com/appium/WebDriverAgent/commit/d79b6245966baaa57f7a1f785d7f9b4ea5a7f104)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72451ba30..ad6c92a78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.1.0](https://github.com/appium/WebDriverAgent/compare/v8.0.2...v8.1.0) (2024-03-26) + + +### Features + +* add updatedWDABundleIdSuffix to handle bundle id for updatedWDABundleId with usePreinstalledWDA ([#871](https://github.com/appium/WebDriverAgent/issues/871)) ([d79b624](https://github.com/appium/WebDriverAgent/commit/d79b6245966baaa57f7a1f785d7f9b4ea5a7f104)) + ## [8.0.2](https://github.com/appium/WebDriverAgent/compare/v8.0.1...v8.0.2) (2024-03-26) diff --git a/package.json b/package.json index 20c0c5080..952dc1699 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.0.2", + "version": "8.1.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 98351c358367e67e63701612fd3702d53437e12e Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 28 Mar 2024 09:05:42 +0100 Subject: [PATCH 051/368] feat: Add a capability to customize the default state change timeout on app startup (#877) --- .../Commands/FBSessionCommands.m | 71 ++++++++++++++----- WebDriverAgentLib/Utilities/FBCapabilities.h | 4 +- WebDriverAgentLib/Utilities/FBCapabilities.m | 1 + 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 38def9553..380dfcc79 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -156,19 +156,25 @@ + (NSArray *)routes if (app.running) { [app terminate]; } - NSError *openError; - if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl - withApplication:bundleID - error:&openError]) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", - initialUrl, bundleID, openError.localizedDescription]; - return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + id errorResponse = [self openDeepLink:initialUrl + withApplication:bundleID + timeout:capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]]; + if (nil != errorResponse) { + return errorResponse; } } else { + NSTimeInterval defaultTimeout = _XCTApplicationStateTimeout(); + if (nil != capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]) { + _XCTSetApplicationStateTimeout([capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC] doubleValue]); + } @try { [app launch]; } @catch (NSException *e) { return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:e.reason traceback:nil]); + } @finally { + if (nil != capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]) { + _XCTSetApplicationStateTimeout(defaultTimeout); + } } } if (!app.running) { @@ -178,13 +184,11 @@ + (NSArray *)routes } } else if (appState == XCUIApplicationStateRunningBackground && !forceAppLaunch) { if (nil != initialUrl) { - NSError *openError; - if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl - withApplication:bundleID - error:&openError]) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", - initialUrl, bundleID, openError.localizedDescription]; - return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + id errorResponse = [self openDeepLink:initialUrl + withApplication:bundleID + timeout:nil]; + if (nil != errorResponse) { + return errorResponse; } } else { [app activate]; @@ -193,11 +197,11 @@ + (NSArray *)routes } if (nil != initialUrl && nil == bundleID) { - NSError *openError; - if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl error:&openError]) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@. Original error: %@", - initialUrl, openError.localizedDescription]; - return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + id errorResponse = [self openDeepLink:initialUrl + withApplication:nil + timeout:capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]]; + if (nil != errorResponse) { + return errorResponse; } } @@ -492,4 +496,33 @@ + (NSDictionary *)currentCapabilities }; } ++(nullable id)openDeepLink:(NSString *)initialUrl + withApplication:(nullable NSString *)bundleID + timeout:(nullable NSNumber *)timeout +{ + NSError *openError; + NSTimeInterval defaultTimeout = _XCTApplicationStateTimeout(); + if (nil != timeout) { + _XCTSetApplicationStateTimeout([timeout doubleValue]); + } + @try { + BOOL result = nil == bundleID + ? [XCUIDevice.sharedDevice fb_openUrl:initialUrl + error:&openError] + : [XCUIDevice.sharedDevice fb_openUrl:initialUrl + withApplication:(id)bundleID + error:&openError]; + if (result) { + return nil; + } + NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", + initialUrl, bundleID ?: @"default", openError.localizedDescription]; + return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + } @finally { + if (nil != timeout) { + _XCTSetApplicationStateTimeout(defaultTimeout); + } + } +} + @end diff --git a/WebDriverAgentLib/Utilities/FBCapabilities.h b/WebDriverAgentLib/Utilities/FBCapabilities.h index 1045a9855..20dad743e 100644 --- a/WebDriverAgentLib/Utilities/FBCapabilities.h +++ b/WebDriverAgentLib/Utilities/FBCapabilities.h @@ -11,7 +11,7 @@ /** Whether to use alternative elements visivility detection method */ extern NSString* const FB_CAP_USE_TEST_MANAGER_FOR_VISIBLITY_DETECTION; -/** Set the maximum amount of charatcers that could be typed within a minute (60 by default) */ +/** Set the maximum amount of characters that could be typed within a minute (60 by default) */ extern NSString* const FB_CAP_MAX_TYPING_FREQUENCY; /** this setting was needed for some legacy stuff */ extern NSString* const FB_CAP_USE_SINGLETON_TEST_MANAGER; @@ -42,3 +42,5 @@ extern NSString* const FB_CAP_ENVIRNOMENT; extern NSString* const FB_CAP_USE_NATIVE_CACHING_STRATEGY; /** Whether to enforce software keyboard presence on simulator */ extern NSString* const FB_CAP_FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE; +/** Sets the application state change timeout for the initial app startup */ +extern NSString* const FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC; diff --git a/WebDriverAgentLib/Utilities/FBCapabilities.m b/WebDriverAgentLib/Utilities/FBCapabilities.m index 1798c2195..b6ccc9ce4 100644 --- a/WebDriverAgentLib/Utilities/FBCapabilities.m +++ b/WebDriverAgentLib/Utilities/FBCapabilities.m @@ -23,3 +23,4 @@ NSString* const FB_CAP_ENVIRNOMENT = @"environment"; NSString* const FB_CAP_USE_NATIVE_CACHING_STRATEGY = @"useNativeCachingStrategy"; NSString* const FB_CAP_FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE = @"forceSimulatorSoftwareKeyboardPresence"; +NSString* const FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC = @"appLaunchStateTimeoutSec"; From 31b5b9d70c3ae6b50bac7f7edd5ea23a350e9644 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 28 Mar 2024 08:10:46 +0000 Subject: [PATCH 052/368] chore(release): 8.2.0 [skip ci] ## [8.2.0](https://github.com/appium/WebDriverAgent/compare/v8.1.0...v8.2.0) (2024-03-28) ### Features * Add a capability to customize the default state change timeout on app startup ([#877](https://github.com/appium/WebDriverAgent/issues/877)) ([98351c3](https://github.com/appium/WebDriverAgent/commit/98351c358367e67e63701612fd3702d53437e12e)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad6c92a78..397fa105a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.2.0](https://github.com/appium/WebDriverAgent/compare/v8.1.0...v8.2.0) (2024-03-28) + + +### Features + +* Add a capability to customize the default state change timeout on app startup ([#877](https://github.com/appium/WebDriverAgent/issues/877)) ([98351c3](https://github.com/appium/WebDriverAgent/commit/98351c358367e67e63701612fd3702d53437e12e)) + ## [8.1.0](https://github.com/appium/WebDriverAgent/compare/v8.0.2...v8.1.0) (2024-03-26) diff --git a/package.json b/package.json index 952dc1699..d773c755b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.1.0", + "version": "8.2.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 6c8920adddb373b463259c3e6c14cb3c49ecbf2b Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 28 Mar 2024 01:34:14 -0700 Subject: [PATCH 053/368] chore: wait for wda start in sim as well for preinstalled wda start (#876) * chore: wait for wda start in sim as well for preinstalled wda start * move to inner func * modify a bit * remove redundant new line * add wait for logic in getStatus * remoe a new line * use waitForCondition in getSttus * modify error handling * tweak error log * tweak log further * Update webdriveragent.js --- lib/webdriveragent.js | 73 +++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index 885291e76..e374eb6ad 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -190,21 +190,53 @@ class WebDriverAgent { * } * } * - * @return {Promise} State Object + * @param {number} [timeoutMs=0] If the given timeoutMs is zero or negative number, + * this function will return the response of `/status` immediately. If the given timeoutMs, + * this function will try to get the response of `/status` up to the timeoutMs. + * @return {Promise} State Object + * @throws {Error} If there was an error within timeoutMs timeout. + * No error is raised if zero or negative number for the timeoutMs. */ - async getStatus () { + async getStatus (timeoutMs = 0) { const noSessionProxy = new NoSessionProxy({ server: this.url.hostname, port: this.url.port, base: this.basePath, timeout: 3000, }); + + const sendGetStatus = async () => await /** @type import('@appium/types').StringRecord */ (noSessionProxy.command('/status', 'GET')); + + if (_.isNil(timeoutMs) || timeoutMs <= 0) { + try { + return await sendGetStatus(); + } catch (err) { + this.log.debug(`WDA is not listening at '${this.url.href}'. Original error:: ${err.message}`); + return null; + } + } + + let lastError = null; + let status = null; try { - return await noSessionProxy.command('/status', 'GET'); + await waitForCondition(async () => { + try { + status = await sendGetStatus(); + return true; + } catch (err) { + lastError = err; + } + return false; + }, { + waitMs: timeoutMs, + intervalMs: 300, + }); } catch (err) { - this.log.debug(`WDA is not listening at '${this.url.href}'`); - return null; + this.log.debug(`Failed to get the status endpoint in ${timeoutMs} ms. ` + + `The last error while accessing ${this.url.href}: ${lastError}. Original error:: ${err.message}.`); + throw new Error(`WDA was not ready in ${timeoutMs} ms.`); } + return status; } /** @@ -317,28 +349,14 @@ class WebDriverAgent { await this.device.devicectl.launchApp( this.bundleIdForXctest, { env, terminateExisting: true } ); - - // Launching app via decictl does not wait for the app start. - // We should wait for the app start by ourselves. - try { - await waitForCondition(async () => !_.isNull(await this.getStatus()), { - waitMs: this.wdaLaunchTimeout, - intervalMs: 300, - }); - - } catch (err) { - throw new Error( - `Failed to start the preinstalled WebDriverAgent in ${this.wdaLaunchTimeout} ms. ` + - `The WebDriverAgent might not be properly built or the device might be locked. ` + - `The 'appium:wdaLaunchTimeout' capability modifies the timeout.` - ); - } } /** * Launch WDA with preinstalled package without xcodebuild. * @param {string} sessionId Launch WDA and establish the session with this sessionId - * @return {Promise} State Object + * @return {Promise} State Object + * @throws {Error} If there was an error within timeoutMs timeout. + * No error is raised if zero or negative number for the timeoutMs. */ async launchWithPreinstalledWDA(sessionId) { const xctestEnv = { @@ -371,7 +389,16 @@ class WebDriverAgent { } this.setupProxies(sessionId); - const status = await this.getStatus(); + let status; + try { + status = await this.getStatus(this.wdaLaunchTimeout); + } catch (err) { + throw new Error( + `Failed to start the preinstalled WebDriverAgent in ${this.wdaLaunchTimeout} ms. ` + + `The WebDriverAgent might not be properly built or the device might be locked. ` + + `The 'appium:wdaLaunchTimeout' capability modifies the timeout.` + ); + } this.started = true; return status; } From 8e7f17bae7dc3d21b45fbcbe5b5429104f2d9882 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 28 Mar 2024 08:39:03 +0000 Subject: [PATCH 054/368] chore(release): 8.2.1 [skip ci] ## [8.2.1](https://github.com/appium/WebDriverAgent/compare/v8.2.0...v8.2.1) (2024-03-28) ### Miscellaneous Chores * wait for wda start in sim as well for preinstalled wda start ([#876](https://github.com/appium/WebDriverAgent/issues/876)) ([6c8920a](https://github.com/appium/WebDriverAgent/commit/6c8920adddb373b463259c3e6c14cb3c49ecbf2b)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 397fa105a..d0a28325b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.2.1](https://github.com/appium/WebDriverAgent/compare/v8.2.0...v8.2.1) (2024-03-28) + + +### Miscellaneous Chores + +* wait for wda start in sim as well for preinstalled wda start ([#876](https://github.com/appium/WebDriverAgent/issues/876)) ([6c8920a](https://github.com/appium/WebDriverAgent/commit/6c8920adddb373b463259c3e6c14cb3c49ecbf2b)) + ## [8.2.0](https://github.com/appium/WebDriverAgent/compare/v8.1.0...v8.2.0) (2024-03-28) diff --git a/package.json b/package.json index d773c755b..0ce67cfc9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.2.0", + "version": "8.2.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From a9603f82acbdacdeb7a55b857512ba35353a4bc3 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 29 Mar 2024 09:26:58 +0100 Subject: [PATCH 055/368] feat: Add module version to the /status output (#878) --- Scripts/update-wda-version.js | 40 +++++++++++++++++++ .../Commands/FBSessionCommands.m | 5 +++ package.json | 6 ++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 Scripts/update-wda-version.js diff --git a/Scripts/update-wda-version.js b/Scripts/update-wda-version.js new file mode 100644 index 000000000..37102345a --- /dev/null +++ b/Scripts/update-wda-version.js @@ -0,0 +1,40 @@ +const {plist} = require('@appium/support'); +const path = require('node:path'); +const semver = require('semver'); +const log = require('fancy-log'); + +/** + * @param {string} argName + * @returns {string|null} + */ +function parseArgValue (argName) { + const argNamePattern = new RegExp(`^--${argName}\\b`); + for (let i = 1; i < process.argv.length; ++i) { + const arg = process.argv[i]; + if (argNamePattern.test(arg)) { + return arg.includes('=') ? arg.split('=')[1] : process.argv[i + 1]; + } + } + return null; +} + +async function updateWdaVersion() { + const newVersion = parseArgValue('package-version'); + if (!newVersion) { + throw new Error('No package version argument (use `--package-version=xxx`)'); + } + if (!semver.valid(newVersion)) { + throw new Error( + `Invalid version specified '${newVersion}'. Version should be in the form '1.2.3'` + ); + } + + const libManifest = path.resolve('WebDriverAgentLib', 'Info.plist'); + log.info(`Updating the WebDriverAgent manifest at '${libManifest}' to version '${newVersion}'`); + await plist.updatePlistFile(libManifest, { + CFBundleShortVersionString: newVersion, + CFBundleVersion: newVersion, + }, false); +} + +(async () => await updateWdaVersion())(); diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 380dfcc79..cd6a28a90 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -279,6 +279,11 @@ + (NSArray *)routes if (nil != upgradeTimestamp && upgradeTimestamp.length > 0) { [buildInfo setObject:upgradeTimestamp forKey:@"upgradedAt"]; } + NSDictionary *infoDict = [[NSBundle bundleForClass:self.class] infoDictionary]; + NSString *version = [infoDict objectForKey:@"CFBundleShortVersionString"]; + if (nil != version) { + [buildInfo setObject:version forKey:@"version"]; + } return FBResponseWithObject( @{ diff --git a/package.json b/package.json index 0ce67cfc9..1d0466a30 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,14 @@ "format": "prettier -w ./lib", "lint:fix": "npm run lint -- --fix", "prepare": "npm run build", + "version": "npm run sync-wda-version", "test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.js\"", "e2e-test": "mocha --exit --timeout 10m \"./test/functional/**/*-specs.js\"", "bundle": "npm run bundle:ios && npm run bundle:tv", "bundle:ios": "TARGET=runner SDK=sim node ./Scripts/build-webdriveragent.js", "bundle:tv": "TARGET=tv_runner SDK=tv_sim node ./Scripts/build-webdriveragent.js", - "fetch-prebuilt-wda": "node ./Scripts/fetch-prebuilt-wda.js" + "fetch-prebuilt-wda": "node ./Scripts/fetch-prebuilt-wda.js", + "sync-wda-version": "node ./scripts/update-wda-version.js --package-version=${npm_package_version} && git add WebDriverAgentLib/Info.plist" }, "engines": { "node": ">=14", @@ -73,10 +75,12 @@ "eslint-plugin-import": "^2.28.0", "eslint-plugin-mocha": "^10.1.0", "eslint-plugin-promise": "^6.1.1", + "fancy-log": "^2.0.0", "node-simctl": "^7.0.1", "mocha": "^10.0.0", "prettier": "^3.0.0", "semantic-release": "^23.0.0", + "semver": "^7.3.7", "sinon": "^17.0.0", "ts-node": "^10.9.1", "typescript": "^5.4.2" From e030c2e3eb25c9efe187ec86ff64c4cd220db164 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 29 Mar 2024 08:31:26 +0000 Subject: [PATCH 056/368] chore(release): 8.3.0 [skip ci] ## [8.3.0](https://github.com/appium/WebDriverAgent/compare/v8.2.1...v8.3.0) (2024-03-29) ### Features * Add module version to the /status output ([#878](https://github.com/appium/WebDriverAgent/issues/878)) ([a9603f8](https://github.com/appium/WebDriverAgent/commit/a9603f82acbdacdeb7a55b857512ba35353a4bc3)) --- CHANGELOG.md | 7 ++++++ WebDriverAgentLib/Info.plist | 46 ++++++++++++++++++------------------ package.json | 2 +- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0a28325b..f25272474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.3.0](https://github.com/appium/WebDriverAgent/compare/v8.2.1...v8.3.0) (2024-03-29) + + +### Features + +* Add module version to the /status output ([#878](https://github.com/appium/WebDriverAgent/issues/878)) ([a9603f8](https://github.com/appium/WebDriverAgent/commit/a9603f82acbdacdeb7a55b857512ba35353a4bc3)) + ## [8.2.1](https://github.com/appium/WebDriverAgent/compare/v8.2.0...v8.2.1) (2024-03-28) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 1b89f4fcd..502e342aa 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -1,26 +1,26 @@ - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - com.facebook.wda.lib - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + com.facebook.wda.lib + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 8.3.0 + CFBundleSignature + ???? + CFBundleVersion + 8.3.0 + NSPrincipalClass + + + \ No newline at end of file diff --git a/package.json b/package.json index 1d0466a30..6fd1c4b40 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.2.1", + "version": "8.3.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 0436e95752826bee7786577ac1bc0d056af11bc8 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 31 Mar 2024 01:20:36 -0700 Subject: [PATCH 057/368] chore: do not cleanup with this.usePrebuiltWDA (#882) --- lib/webdriveragent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index e374eb6ad..a4b316637 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -449,7 +449,7 @@ class WebDriverAgent { // useXctestrunFile and usePrebuiltWDA use existing dependencies // It depends on user side - if (this.idb || this.useXctestrunFile || (this.derivedDataPath && this.usePrebuiltWDA)) { + if (this.idb || this.useXctestrunFile || this.usePrebuiltWDA) { this.log.info('Skipped WDA project cleanup according to the provided capabilities'); } else { const synchronizationKey = path.normalize(this.bootstrapPath); From d89424b168c01a8d91f875029e3316ac7c26eac2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 31 Mar 2024 08:33:50 +0000 Subject: [PATCH 058/368] chore(release): 8.3.1 [skip ci] ## [8.3.1](https://github.com/appium/WebDriverAgent/compare/v8.3.0...v8.3.1) (2024-03-31) ### Miscellaneous Chores * do not cleanup with this.usePrebuiltWDA ([#882](https://github.com/appium/WebDriverAgent/issues/882)) ([0436e95](https://github.com/appium/WebDriverAgent/commit/0436e95752826bee7786577ac1bc0d056af11bc8)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f25272474..e18fb4419 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.3.1](https://github.com/appium/WebDriverAgent/compare/v8.3.0...v8.3.1) (2024-03-31) + + +### Miscellaneous Chores + +* do not cleanup with this.usePrebuiltWDA ([#882](https://github.com/appium/WebDriverAgent/issues/882)) ([0436e95](https://github.com/appium/WebDriverAgent/commit/0436e95752826bee7786577ac1bc0d056af11bc8)) + ## [8.3.0](https://github.com/appium/WebDriverAgent/compare/v8.2.1...v8.3.0) (2024-03-29) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 502e342aa..2a758e151 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.3.0 + 8.3.1 CFBundleSignature ???? CFBundleVersion - 8.3.0 + 8.3.1 NSPrincipalClass diff --git a/package.json b/package.json index 6fd1c4b40..05bbda32e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.3.0", + "version": "8.3.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 5ebc71c6ca2b364d44a44716e794885f8d3b6d9c Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 31 Mar 2024 23:56:33 -0700 Subject: [PATCH 059/368] feat: add system screen size/width in the system info endpoint (#881) * feat: add system screen size/width * simplify * add nil statusBar case * tune --- WebDriverAgentLib/Commands/FBCustomCommands.m | 18 ++++++++++++++++-- WebDriverAgentLib/Utilities/FBScreen.h | 5 ----- WebDriverAgentLib/Utilities/FBScreen.m | 13 ------------- .../IntegrationTests/FBScreenTests.m | 7 ------- 4 files changed, 16 insertions(+), 27 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index f31c96739..2ab039e6b 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -15,6 +15,7 @@ #import "FBConfiguration.h" #import "FBKeyboard.h" #import "FBNotificationsHelper.h" +#import "FBMathUtils.h" #import "FBPasteboard.h" #import "FBResponsePayload.h" #import "FBRoute.h" @@ -48,6 +49,7 @@ + (NSArray *)routes [[FBRoute GET:@"/wda/locked"].withoutSession respondWithTarget:self action:@selector(handleIsLocked:)], [[FBRoute GET:@"/wda/locked"] respondWithTarget:self action:@selector(handleIsLocked:)], [[FBRoute GET:@"/wda/screen"] respondWithTarget:self action:@selector(handleGetScreen:)], + [[FBRoute GET:@"/wda/screen"].withoutSession respondWithTarget:self action:@selector(handleGetScreen:)], [[FBRoute GET:@"/wda/activeAppInfo"] respondWithTarget:self action:@selector(handleActiveAppInfo:)], [[FBRoute GET:@"/wda/activeAppInfo"].withoutSession respondWithTarget:self action:@selector(handleActiveAppInfo:)], #if !TARGET_OS_TV // tvOS does not provide relevant APIs @@ -134,10 +136,22 @@ + (NSArray *)routes + (id)handleGetScreen:(FBRouteRequest *)request { - FBSession *session = request.session; - CGSize statusBarSize = [FBScreen statusBarSizeForApplication:session.activeApplication]; + XCUIApplication *app = XCUIApplication.fb_systemApplication; + + XCUIElement *mainStatusBar = app.statusBars.allElementsBoundByIndex.firstObject; + CGSize statusBarSize = (nil == mainStatusBar) ? CGSizeZero : mainStatusBar.frame.size; + +#if TARGET_OS_TV + CGSize screenSize = app.frame.size; +#else + CGSize screenSize = FBAdjustDimensionsForApplication(app.wdFrame.size, app.interfaceOrientation); +#endif + return FBResponseWithObject( @{ + @"screenSize":@{@"width": @(screenSize.width), + @"height": @(screenSize.height) + }, @"statusBarSize": @{@"width": @(statusBarSize.width), @"height": @(statusBarSize.height), }, diff --git a/WebDriverAgentLib/Utilities/FBScreen.h b/WebDriverAgentLib/Utilities/FBScreen.h index 61dc4aeb4..9c4cca87e 100644 --- a/WebDriverAgentLib/Utilities/FBScreen.h +++ b/WebDriverAgentLib/Utilities/FBScreen.h @@ -18,11 +18,6 @@ NS_ASSUME_NONNULL_BEGIN */ + (double)scale; -/** - The absolute size of application's status bar or CGSizeZero if it's hidden or does not exist - */ -+ (CGSize)statusBarSizeForApplication:(XCUIApplication *)application; - @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBScreen.m b/WebDriverAgentLib/Utilities/FBScreen.m index 8ebe080d5..17b7d8b19 100644 --- a/WebDriverAgentLib/Utilities/FBScreen.m +++ b/WebDriverAgentLib/Utilities/FBScreen.m @@ -19,17 +19,4 @@ + (double)scale return [XCUIScreen.mainScreen scale]; } -+ (CGSize)statusBarSizeForApplication:(XCUIApplication *)application -{ - XCUIApplication *app = XCUIApplication.fb_systemApplication; - // Since iOS 13 the status bar is no longer part of the application, it’s part of the SpringBoard - XCUIElement *mainStatusBar = app.statusBars.allElementsBoundByIndex.firstObject; - if (nil == mainStatusBar) { - return CGSizeZero; - } - CGSize result = mainStatusBar.frame.size; - // Workaround for https://github.com/appium/appium/issues/15961 - return CGSizeMake(MAX(result.width, result.height), MIN(result.width, result.height)); -} - @end diff --git a/WebDriverAgentTests/IntegrationTests/FBScreenTests.m b/WebDriverAgentTests/IntegrationTests/FBScreenTests.m index 4eff7fcd9..0f5bb5bbc 100644 --- a/WebDriverAgentTests/IntegrationTests/FBScreenTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBScreenTests.m @@ -28,12 +28,5 @@ - (void)testScreenScale XCTAssertTrue([FBScreen scale] >= 2); } -- (void)testStatusBarSize -{ - CGSize statusBarSize = [FBScreen statusBarSizeForApplication:self.testedApplication]; - BOOL statusBarSizeIsZero = CGSizeEqualToSize(CGSizeZero, statusBarSize); - XCTAssertFalse(statusBarSizeIsZero); -} - @end From 00513be53ec2231e81747b9974e5c687e25cbbc9 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 1 Apr 2024 07:04:07 +0000 Subject: [PATCH 060/368] chore(release): 8.4.0 [skip ci] ## [8.4.0](https://github.com/appium/WebDriverAgent/compare/v8.3.1...v8.4.0) (2024-04-01) ### Features * add system screen size/width in the system info endpoint ([#881](https://github.com/appium/WebDriverAgent/issues/881)) ([5ebc71c](https://github.com/appium/WebDriverAgent/commit/5ebc71c6ca2b364d44a44716e794885f8d3b6d9c)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e18fb4419..4ab2a7823 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.4.0](https://github.com/appium/WebDriverAgent/compare/v8.3.1...v8.4.0) (2024-04-01) + + +### Features + +* add system screen size/width in the system info endpoint ([#881](https://github.com/appium/WebDriverAgent/issues/881)) ([5ebc71c](https://github.com/appium/WebDriverAgent/commit/5ebc71c6ca2b364d44a44716e794885f8d3b6d9c)) + ## [8.3.1](https://github.com/appium/WebDriverAgent/compare/v8.3.0...v8.3.1) (2024-03-31) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 2a758e151..7df0f70a3 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.3.1 + 8.4.0 CFBundleSignature ???? CFBundleVersion - 8.3.1 + 8.4.0 NSPrincipalClass diff --git a/package.json b/package.json index 05bbda32e..54ba7aa1d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.3.1", + "version": "8.4.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "scripts": { From 4b3c220c0c609802924b7b6ff9a4dfa7a98eb5f4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 7 Apr 2024 21:48:06 +0200 Subject: [PATCH 061/368] feat: Add types for WDA caps and settings (#885) --- index.js | 22 ---------------------- index.ts | 7 +++++++ lib/types.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 +++-- tsconfig.json | 2 +- 5 files changed, 61 insertions(+), 25 deletions(-) delete mode 100644 index.js create mode 100644 index.ts create mode 100644 lib/types.ts diff --git a/index.js b/index.js deleted file mode 100644 index 3513d683b..000000000 --- a/index.js +++ /dev/null @@ -1,22 +0,0 @@ -import * as dependencies from './lib/check-dependencies'; -import * as proxies from './lib/no-session-proxy'; -import * as driver from './lib/webdriveragent'; -import * as constants from './lib/constants'; -import * as utils from './lib/utils'; - - -const { checkForDependencies, bundleWDASim } = dependencies; -const { NoSessionProxy } = proxies; -const { WebDriverAgent } = driver; -const { WDA_BASE_URL, WDA_RUNNER_BUNDLE_ID, PROJECT_FILE } = constants; -const { resetTestProcesses, BOOTSTRAP_PATH } = utils; - -export { - WebDriverAgent, - NoSessionProxy, - checkForDependencies, bundleWDASim, - resetTestProcesses, - BOOTSTRAP_PATH, - WDA_RUNNER_BUNDLE_ID, PROJECT_FILE, - WDA_BASE_URL, -}; diff --git a/index.ts b/index.ts new file mode 100644 index 000000000..d8e3996bd --- /dev/null +++ b/index.ts @@ -0,0 +1,7 @@ +export { checkForDependencies, bundleWDASim } from './lib/check-dependencies'; +export { NoSessionProxy } from './lib/no-session-proxy'; +export { WebDriverAgent } from './lib/webdriveragent'; +export { WDA_BASE_URL, WDA_RUNNER_BUNDLE_ID, PROJECT_FILE } from './lib/constants'; +export { resetTestProcesses, BOOTSTRAP_PATH } from './lib/utils'; + +export * from './lib/types'; diff --git a/lib/types.ts b/lib/types.ts new file mode 100644 index 000000000..3c6a22538 --- /dev/null +++ b/lib/types.ts @@ -0,0 +1,50 @@ +// WebDriverAgentLib/Utilities/FBSettings.h +export interface WDASettings { + elementResponseAttribute?: string; + shouldUseCompactResponses?: boolean; + mjpegServerScreenshotQuality?: number; + mjpegServerFramerate?: number; + screenshotQuality?: number; + elementResponseAttributes?: string; + mjpegScalingFactor?: number; + mjpegFixOrientation?: boolean; + keyboardAutocorrection?: boolean; + keyboardPrediction?: boolean; + customSnapshotTimeout?: number; + snapshotMaxDepth?: number; + useFirstMatch?: boolean; + boundElementsByIndex?: boolean; + reduceMotion?: boolean; + defaultActiveApplication?: string; + activeAppDetectionPoint?: string; + includeNonModalElements?: boolean; + defaultAlertAction?: 'accept' | 'dismiss'; + acceptAlertButtonSelector?: string; + dismissAlertButtonSelector?: string; + screenshotOrientation?: 'auto' | 'portrait' | 'portraitUpsideDown' | 'landscapeRight' | 'landscapeLeft' + waitForIdleTimeout?: number; + animationCoolOffTimeout?: number; +} + +// WebDriverAgentLib/Utilities/FBCapabilities.h +export interface WDACapabilities { + bundleId?: string; + initialUrl?: string; + arguments?: string[]; + environment?: Record; + eventloopIdleDelaySec?: number; + shouldWaitForQuiescence?: boolean; + shouldUseTestManagerForVisibilityDetection?: boolean; + maxTypingFrequency?: number; + shouldUseSingletonTestManager?: boolean; + waitForIdleTimeout?: number; + shouldUseCompactResponses?: number; + elementResponseFields?: unknown; + disableAutomaticScreenshots?: boolean; + shouldTerminateApp?: boolean; + forceAppLaunch?: boolean; + useNativeCachingStrategy?: boolean; + forceSimulatorSoftwareKeyboardPresence?: boolean; + defaultAlertAction?: 'accept' | 'dismiss'; + appLaunchStateTimeoutSec?: number; +} diff --git a/package.json b/package.json index 54ba7aa1d..0bca8c797 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "8.4.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", + "types": "./build/index.d.ts", "scripts": { "build": "tsc -b", "dev": "npm run build -- --watch", @@ -100,9 +101,9 @@ "teen_process": "^2.0.0" }, "files": [ - "index.js", + "index.ts", "lib", - "build/index.js", + "build/index.*", "build/lib", "Scripts/build.sh", "Scripts/fetch-prebuilt-wda.js", diff --git a/tsconfig.json b/tsconfig.json index 33d83ef45..678d20ad0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "checkJs": true }, "include": [ - "index.js", + "index.ts", "lib" ] } From 4c7f168f81affc5a5d18ae6f9f46f65ab462a6cf Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 7 Apr 2024 19:54:31 +0000 Subject: [PATCH 062/368] chore(release): 8.5.0 [skip ci] ## [8.5.0](https://github.com/appium/WebDriverAgent/compare/v8.4.0...v8.5.0) (2024-04-07) ### Features * Add types for WDA caps and settings ([#885](https://github.com/appium/WebDriverAgent/issues/885)) ([4b3c220](https://github.com/appium/WebDriverAgent/commit/4b3c220c0c609802924b7b6ff9a4dfa7a98eb5f4)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ab2a7823..3ed596fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.5.0](https://github.com/appium/WebDriverAgent/compare/v8.4.0...v8.5.0) (2024-04-07) + + +### Features + +* Add types for WDA caps and settings ([#885](https://github.com/appium/WebDriverAgent/issues/885)) ([4b3c220](https://github.com/appium/WebDriverAgent/commit/4b3c220c0c609802924b7b6ff9a4dfa7a98eb5f4)) + ## [8.4.0](https://github.com/appium/WebDriverAgent/compare/v8.3.1...v8.4.0) (2024-04-01) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 7df0f70a3..682c59594 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.4.0 + 8.5.0 CFBundleSignature ???? CFBundleVersion - 8.4.0 + 8.5.0 NSPrincipalClass diff --git a/package.json b/package.json index 0bca8c797..f6c3756fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.4.0", + "version": "8.5.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 9ca7632faf999931e7f5edf47267fcce6d6392b2 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 8 Apr 2024 08:22:46 +0200 Subject: [PATCH 063/368] chore: Add more type declarations (#886) --- lib/check-dependencies.js | 17 ++++++--- lib/webdriveragent.js | 79 +++++++++++++++++++++++++++++++++++---- lib/xcodebuild.js | 63 +++++++++++++++++++++++++------ 3 files changed, 135 insertions(+), 24 deletions(-) diff --git a/lib/check-dependencies.js b/lib/check-dependencies.js index ce145f5a1..21c68de60 100644 --- a/lib/check-dependencies.js +++ b/lib/check-dependencies.js @@ -3,6 +3,7 @@ import _ from 'lodash'; import { exec } from 'teen_process'; import path from 'path'; import XcodeBuild from './xcodebuild'; +import xcode from 'appium-xcode'; import { WDA_SCHEME, SDK_SIMULATOR, WDA_RUNNER_APP } from './constants'; @@ -22,17 +23,25 @@ async function buildWDASim () { } // eslint-disable-next-line require-await -async function checkForDependencies () { +export async function checkForDependencies () { log.debug('Dependencies are up to date'); return false; } -async function bundleWDASim (xcodebuild) { +/** + * + * @param {XcodeBuild} xcodebuild + * @returns {Promise} + */ +export async function bundleWDASim (xcodebuild) { if (xcodebuild && !_.isFunction(xcodebuild.retrieveDerivedDataPath)) { - xcodebuild = new XcodeBuild('', {}); + xcodebuild = new XcodeBuild(/** @type {import('appium-xcode').XcodeVersion} */ (await xcode.getVersion(true)), {}); } const derivedDataPath = await xcodebuild.retrieveDerivedDataPath(); + if (!derivedDataPath) { + throw new Error('Cannot retrieve the path to the Xcode derived data folder'); + } const wdaBundlePath = path.join(derivedDataPath, 'Build', 'Products', 'Debug-iphonesimulator', WDA_RUNNER_APP); if (await fs.exists(wdaBundlePath)) { return wdaBundlePath; @@ -40,5 +49,3 @@ async function bundleWDASim (xcodebuild) { await buildWDASim(); return wdaBundlePath; } - -export { checkForDependencies, bundleWDASim }; diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index a4b316637..c69666f4e 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -27,7 +27,19 @@ const WDA_CF_BUNDLE_NAME = 'WebDriverAgentRunner-Runner'; const SHARED_RESOURCES_GUARD = new AsyncLock(); const RECENT_MODULE_VERSION_ITEM_NAME = 'recentWdaModuleVersion'; -class WebDriverAgent { +export class WebDriverAgent { + /** @type {string} */ + bootstrapPath; + + /** @type {string} */ + agentPath; + + /** + * @param {import('appium-xcode').XcodeVersion} xcodeVersion + * // TODO: make args typed + * @param {import('@appium/types').StringRecord} [args={}] + * @param {import('@appium/types').AppiumLogger?} [log=null] + */ constructor (xcodeVersion, args = {}, log = null) { this.xcodeVersion = xcodeVersion; @@ -123,6 +135,10 @@ class WebDriverAgent { return `${this.updatedWDABundleId ? this.updatedWDABundleId : WDA_RUNNER_BUNDLE_ID}${this.updatedWDABundleIdSuffix}`; } + /** + * @param {string} [bootstrapPath] + * @param {string} [agentPath] + */ setWDAPaths (bootstrapPath, agentPath) { // allow the user to specify a place for WDA. This is undocumented and // only here for the purposes of testing development of WDA @@ -134,8 +150,11 @@ class WebDriverAgent { this.log.info(`Using WDA agent: '${this.agentPath}'`); } + /** + * @returns {Promise} + */ async cleanupObsoleteProcesses () { - const obsoletePids = await getPIDsListeningOnPort(this.url.port, + const obsoletePids = await getPIDsListeningOnPort(/** @type {string} */ (this.url.port), (cmdLine) => cmdLine.includes('/WebDriverAgentRunner') && !cmdLine.toLowerCase().includes(this.device.udid.toLowerCase())); @@ -164,6 +183,9 @@ class WebDriverAgent { return !!(await this.getStatus()); } + /** + * @returns {string} + */ get basePath () { if (this.url.path === '/') { return ''; @@ -243,6 +265,8 @@ class WebDriverAgent { * Uninstall WDAs from the test device. * Over Xcode 11, multiple WDA can be in the device since Xcode 11 generates different WDA. * Appium does not expect multiple WDAs are running on a device. + * + * @returns {Promise} */ async uninstall () { try { @@ -476,6 +500,9 @@ class WebDriverAgent { return await this.xcodebuild.start(); } + /** + * @returns {Promise} + */ async startWithIDB () { this.log.info('Will launch WDA with idb instead of xcodebuild since the corresponding flag is enabled'); const {wdaBundleId, testBundleId} = await this.prepareWDA(); @@ -490,6 +517,11 @@ class WebDriverAgent { return await this.idb.runXCUITest(wdaBundleId, wdaBundleId, testBundleId, {env}); } + /** + * + * @param {string} wdaBundlePath + * @returns {Promise} + */ async parseBundleId (wdaBundlePath) { const infoPlistPath = path.join(wdaBundlePath, 'Info.plist'); const infoPlist = await plist.parsePlist(await fs.readFile(infoPlistPath)); @@ -499,6 +531,9 @@ class WebDriverAgent { return infoPlist.CFBundleIdentifier; } + /** + * @returns {Promise<{wdaBundleId: string, testBundleId: string, wdaBundlePath: string}>} + */ async prepareWDA () { const wdaBundlePath = this.wdaBundlePath || await this.fetchWDABundle(); const wdaBundleId = await this.parseBundleId(wdaBundlePath); @@ -509,9 +544,12 @@ class WebDriverAgent { return {wdaBundleId, testBundleId, wdaBundlePath}; } + /** + * @returns {Promise} + */ async fetchWDABundle () { if (!this.derivedDataPath) { - return await bundleWDASim(this.xcodebuild); + return await bundleWDASim(/** @type {XcodeBuild} */ (this.xcodebuild)); } const wdaBundlePaths = await fs.glob(`${this.derivedDataPath}/**/*${WDA_RUNNER_APP}/`, { absolute: true, @@ -522,14 +560,21 @@ class WebDriverAgent { return wdaBundlePaths[0]; } + /** + * @returns {Promise} + */ async isSourceFresh () { const existsPromises = [ 'Resources', `Resources${path.sep}WebDriverAgent.bundle`, - ].map((subPath) => fs.exists(path.resolve(this.bootstrapPath, subPath))); + ].map((subPath) => fs.exists(path.resolve(/** @type {String} */ (this.bootstrapPath), subPath))); return (await B.all(existsPromises)).some((v) => v === false); } + /** + * @param {string} sessionId + * @returns {void} + */ setupProxies (sessionId) { const proxyOpts = { log: this.log, @@ -547,6 +592,9 @@ class WebDriverAgent { this.noSessionProxy = new NoSessionProxy(proxyOpts); } + /** + * @returns {Promise} + */ async quit () { if (this.usePreinstalledWDA) { this.log.info('Stopping the XCTest session'); @@ -582,6 +630,9 @@ class WebDriverAgent { } } + /** + * @returns {import('url').UrlWithStringQuery} + */ get url () { if (!this._url) { if (this.webDriverAgentUrl) { @@ -595,30 +646,44 @@ class WebDriverAgent { return this._url; } + /** + * @param {string} _url + * @returns {void} + */ set url (_url) { this._url = url.parse(_url); } + /** + * @returns {boolean} + */ get fullyStarted () { return this.started; } + /** + * @param {boolean} started + * @returns {void}s + */ set fullyStarted (started) { this.started = started ?? false; } + /** + * @returns {Promise} + */ async retrieveDerivedDataPath () { if (this.canSkipXcodebuild) { return; } - // @ts-ignore xcodebuild should be set - return await this.xcodebuild.retrieveDerivedDataPath(); + return await /** @type {XcodeBuild} */ (this.xcodebuild).retrieveDerivedDataPath(); } /** * 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. + * @returns {Promise} */ async setupCaching () { const status = await this.getStatus(); @@ -660,6 +725,7 @@ class WebDriverAgent { /** * Quit and uninstall running WDA. + * @returns {Promise} */ async quitAndUninstall () { await this.quit(); @@ -668,4 +734,3 @@ class WebDriverAgent { } export default WebDriverAgent; -export { WebDriverAgent }; diff --git a/lib/xcodebuild.js b/lib/xcodebuild.js index bdd484db2..2862cb6a0 100644 --- a/lib/xcodebuild.js +++ b/lib/xcodebuild.js @@ -33,15 +33,16 @@ const LIB_SCHEME_TV = 'WebDriverAgentLib_tvOS'; const xcodeLog = logger.getLogger('Xcode'); -class XcodeBuild { +export class XcodeBuild { /** @type {SubProcess} */ xcodebuild; /** - * @param {string} xcodeVersion + * @param {import('appium-xcode').XcodeVersion} xcodeVersion * @param {any} device - * @param {any} args - * @param {import('@appium/types').AppiumLogger?} log + * // TODO: make args typed + * @param {import('@appium/types').StringRecord} [args={}] + * @param {import('@appium/types').AppiumLogger?} [log=null] */ constructor (xcodeVersion, device, args = {}, log = null) { this.xcodeVersion = xcodeVersion; @@ -92,6 +93,11 @@ class XcodeBuild { this._didProcessExit = false; } + /** + * + * @param {any} noSessionProxy + * @returns {Promise} + */ async init (noSessionProxy) { this.noSessionProxy = noSessionProxy; @@ -120,6 +126,9 @@ class XcodeBuild { } } + /** + * @returns {Promise} + */ async retrieveDerivedDataPath () { if (this.derivedDataPath) { return this.derivedDataPath; @@ -154,6 +163,9 @@ class XcodeBuild { return await this._derivedDataPathPromise; } + /** + * @returns {Promise} + */ async reset () { // if necessary, reset the bundleId to original value if (this.realDevice && this.updatedWDABundleId) { @@ -161,6 +173,9 @@ class XcodeBuild { } } + /** + * @returns {Promise} + */ async prebuild () { // first do a build phase this.log.debug('Pre-building WDA before launching test'); @@ -173,6 +188,9 @@ class XcodeBuild { } } + /** + * @returns {Promise} + */ async cleanProject () { const libScheme = isTvOS(this.platformName) ? LIB_SCHEME_TV : LIB_SCHEME_IOS; const runnerScheme = isTvOS(this.platformName) ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS; @@ -187,18 +205,24 @@ class XcodeBuild { } } + /** + * + * @param {boolean} [buildOnly=false] + * @returns {{cmd: string, args: string[]}} + */ getCommand (buildOnly = false) { - let cmd = 'xcodebuild'; - let args; + const cmd = 'xcodebuild'; + /** @type {string[]} */ + const args = []; // figure out the targets for xcodebuild const [buildCmd, testCmd] = this.useSimpleBuildTest ? ['build', 'test'] : ['build-for-testing', 'test-without-building']; if (buildOnly) { - args = [buildCmd]; + args.push(buildCmd); } else if (this.usePrebuiltWDA || this.useXctestrunFile) { - args = [testCmd]; + args.push(testCmd); } else { - args = [buildCmd, testCmd]; + args.push(buildCmd, testCmd); } if (this.allowProvisioningDeviceRegistration) { @@ -260,6 +284,10 @@ class XcodeBuild { return {cmd, args}; } + /** + * @param {boolean} [buildOnly=false] + * @returns {Promise} + */ async createSubProcess (buildOnly = false) { if (!this.useXctestrunFile && this.realDevice) { if (this.keychainPath && this.keychainPassword) { @@ -321,6 +349,11 @@ class XcodeBuild { return xcodebuild; } + + /** + * @param {boolean} [buildOnly=false] + * @returns {Promise} + */ async start (buildOnly = false) { this.xcodebuild = await this.createSubProcess(buildOnly); @@ -356,8 +389,7 @@ class XcodeBuild { const timer = new timing.Timer().start(); await this.xcodebuild.start(true); if (!buildOnly) { - let status = await this.waitForStart(timer); - resolve(status); + resolve(/** @type {import('@appium/types').StringRecord} */ (await this.waitForStart(timer))); } } catch (err) { let msg = `Unable to start WebDriverAgent: ${err}`; @@ -368,6 +400,11 @@ class XcodeBuild { }); } + /** + * + * @param {any} timer + * @returns {Promise} + */ async waitForStart (timer) { // try to connect once every 0.5 seconds, until `launchTimeout` is up this.log.debug(`Waiting up to ${this.launchTimeout}ms for WebDriverAgent to start`); @@ -412,10 +449,12 @@ class XcodeBuild { return currentStatus; } + /** + * @returns {Promise} + */ async quit () { await killProcess('xcodebuild', this.xcodebuild); } } -export { XcodeBuild }; export default XcodeBuild; From b8d80fa4c297b11882346051b93d1e1cd0ff448e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 8 Apr 2024 06:28:09 +0000 Subject: [PATCH 064/368] chore(release): 8.5.1 [skip ci] ## [8.5.1](https://github.com/appium/WebDriverAgent/compare/v8.5.0...v8.5.1) (2024-04-08) ### Miscellaneous Chores * Add more type declarations ([#886](https://github.com/appium/WebDriverAgent/issues/886)) ([9ca7632](https://github.com/appium/WebDriverAgent/commit/9ca7632faf999931e7f5edf47267fcce6d6392b2)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ed596fa1..40b7bcfe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.5.1](https://github.com/appium/WebDriverAgent/compare/v8.5.0...v8.5.1) (2024-04-08) + + +### Miscellaneous Chores + +* Add more type declarations ([#886](https://github.com/appium/WebDriverAgent/issues/886)) ([9ca7632](https://github.com/appium/WebDriverAgent/commit/9ca7632faf999931e7f5edf47267fcce6d6392b2)) + ## [8.5.0](https://github.com/appium/WebDriverAgent/compare/v8.4.0...v8.5.0) (2024-04-07) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 682c59594..20adc0628 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.5.0 + 8.5.1 CFBundleSignature ???? CFBundleVersion - 8.5.0 + 8.5.1 NSPrincipalClass diff --git a/package.json b/package.json index f6c3756fb..9e5a582c7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.5.0", + "version": "8.5.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From ead75eb87a5c8e94088bace8f372ab137dcf57ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:42:50 +0200 Subject: [PATCH 065/368] chore(deps-dev): bump @typescript-eslint/parser from 6.21.0 to 7.6.0 (#888) * chore(deps-dev): bump @typescript-eslint/parser from 6.21.0 to 7.6.0 Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.21.0 to 7.6.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v7.6.0/packages/parser) --- updated-dependencies: - dependency-name: "@typescript-eslint/parser" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * bump to v7 --------- 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 9e5a582c7..0101e541e 100644 --- a/package.json +++ b/package.json @@ -64,8 +64,8 @@ "@types/sinon": "^17.0.0", "@types/sinon-chai": "^3.2.9", "@types/teen_process": "^2.0.1", - "@typescript-eslint/eslint-plugin": "^6.9.0", - "@typescript-eslint/parser": "^6.9.0", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", "appium-xcode": "^5.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", From fb25742a07a2fbcb0365a48d54117267c7c916df Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 9 Apr 2024 22:54:27 +0200 Subject: [PATCH 066/368] chore: Remove extra imports --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index 0101e541e..15c86c806 100644 --- a/package.json +++ b/package.json @@ -64,8 +64,6 @@ "@types/sinon": "^17.0.0", "@types/sinon-chai": "^3.2.9", "@types/teen_process": "^2.0.1", - "@typescript-eslint/eslint-plugin": "^7.0.0", - "@typescript-eslint/parser": "^7.0.0", "appium-xcode": "^5.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", From 32be3b4ac3970200c09060f0a239566c4c853fe0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 9 Apr 2024 22:42:19 +0000 Subject: [PATCH 067/368] chore(release): 8.5.2 [skip ci] ## [8.5.2](https://github.com/appium/WebDriverAgent/compare/v8.5.1...v8.5.2) (2024-04-09) ### Miscellaneous Chores * **deps-dev:** bump @typescript-eslint/parser from 6.21.0 to 7.6.0 ([#888](https://github.com/appium/WebDriverAgent/issues/888)) ([ead75eb](https://github.com/appium/WebDriverAgent/commit/ead75eb87a5c8e94088bace8f372ab137dcf57ad)) * Remove extra imports ([fb25742](https://github.com/appium/WebDriverAgent/commit/fb25742a07a2fbcb0365a48d54117267c7c916df)) --- CHANGELOG.md | 8 ++++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40b7bcfe8..e67ab24cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [8.5.2](https://github.com/appium/WebDriverAgent/compare/v8.5.1...v8.5.2) (2024-04-09) + + +### Miscellaneous Chores + +* **deps-dev:** bump @typescript-eslint/parser from 6.21.0 to 7.6.0 ([#888](https://github.com/appium/WebDriverAgent/issues/888)) ([ead75eb](https://github.com/appium/WebDriverAgent/commit/ead75eb87a5c8e94088bace8f372ab137dcf57ad)) +* Remove extra imports ([fb25742](https://github.com/appium/WebDriverAgent/commit/fb25742a07a2fbcb0365a48d54117267c7c916df)) + ## [8.5.1](https://github.com/appium/WebDriverAgent/compare/v8.5.0...v8.5.1) (2024-04-08) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 20adc0628..a07dd0e72 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.5.1 + 8.5.2 CFBundleSignature ???? CFBundleVersion - 8.5.1 + 8.5.2 NSPrincipalClass diff --git a/package.json b/package.json index 15c86c806..6d0a94ae0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.5.1", + "version": "8.5.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 2c7834842afeb1aec77e953ce11ac3c43c839431 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 19 Apr 2024 15:52:22 -0400 Subject: [PATCH 068/368] chore: update integerationapp for newer OS env (#891) * fix deprecated self.interfaceOrientation * fix notification * fix typo * tweak indentations --- WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h | 3 ++- .../IntegrationApp/Classes/FBAlertViewController.h | 1 + .../IntegrationApp/Classes/FBAlertViewController.m | 9 ++++++++- .../IntegrationApp/Classes/ViewController.m | 8 +++++++- WebDriverAgentTests/IntegrationApp/Info.plist | 6 +++--- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h b/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h index ae3920f7f..9561057fd 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h @@ -8,8 +8,9 @@ */ #import +#import -@interface AppDelegate : UIResponder +@interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h b/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h index c657ab618..deb3ddfb4 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h @@ -8,6 +8,7 @@ */ #import +#import @interface FBAlertViewController : UIViewController diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m b/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m index c90b58ab4..e431e8684 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m @@ -37,7 +37,14 @@ - (IBAction)createAppSheet:(UIButton *)sender - (IBAction)createNotificationAlert:(UIButton *)sender { - [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert categories:nil]]; + UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; + [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound|UNAuthorizationOptionAlert|UNAuthorizationOptionBadge) + completionHandler:^(BOOL granted, NSError * _Nullable error) + { + dispatch_async(dispatch_get_main_queue(), ^{ + [[UIApplication sharedApplication] registerForRemoteNotifications]; + }); + }]; } - (IBAction)createCameraRollAccessAlert:(UIButton *)sender diff --git a/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m b/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m index 6a0d0441a..7807e59f1 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m @@ -37,7 +37,7 @@ - (void)viewDidLayoutSubviews - (void)updateOrentationLabel { NSString *orientation = nil; - switch (self.interfaceOrientation) { + switch (UIDevice.currentDevice.orientation) { case UIInterfaceOrientationPortrait: orientation = @"Portrait"; break; @@ -50,6 +50,12 @@ - (void)updateOrentationLabel case UIInterfaceOrientationLandscapeRight: orientation = @"LandscapeRight"; break; + case UIDeviceOrientationFaceUp: + orientation = @"FaceUp"; + break; + case UIDeviceOrientationFaceDown: + orientation = @"FaceDown"; + break; case UIInterfaceOrientationUnknown: orientation = @"Unknown"; break; diff --git a/WebDriverAgentTests/IntegrationApp/Info.plist b/WebDriverAgentTests/IntegrationApp/Info.plist index 2f4f17529..2dfb754cd 100644 --- a/WebDriverAgentTests/IntegrationApp/Info.plist +++ b/WebDriverAgentTests/IntegrationApp/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.wda.integrationApp + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -22,12 +22,12 @@ 1 LSRequiresIPhoneOS + NSLocationAlwaysAndWhenInUseUsageDescription + Yo Yo NSLocationAlwaysUsageDescription Yo Yo NSLocationWhenInUseUsageDescription Yo Yo - NSLocationAlwaysAndWhenInUseUsageDescription - Yo Yo NSPhotoLibraryUsageDescription Yo Yo UILaunchStoryboardName From 99c01bb00cb1acf0f5c07c58fe6db0dd160b1b2f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 19 Apr 2024 20:00:26 +0000 Subject: [PATCH 069/368] chore(release): 8.5.3 [skip ci] ## [8.5.3](https://github.com/appium/WebDriverAgent/compare/v8.5.2...v8.5.3) (2024-04-19) ### Miscellaneous Chores * update integerationapp for newer OS env ([#891](https://github.com/appium/WebDriverAgent/issues/891)) ([2c78348](https://github.com/appium/WebDriverAgent/commit/2c7834842afeb1aec77e953ce11ac3c43c839431)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e67ab24cc..20d4ce072 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.5.3](https://github.com/appium/WebDriverAgent/compare/v8.5.2...v8.5.3) (2024-04-19) + + +### Miscellaneous Chores + +* update integerationapp for newer OS env ([#891](https://github.com/appium/WebDriverAgent/issues/891)) ([2c78348](https://github.com/appium/WebDriverAgent/commit/2c7834842afeb1aec77e953ce11ac3c43c839431)) + ## [8.5.2](https://github.com/appium/WebDriverAgent/compare/v8.5.1...v8.5.2) (2024-04-09) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index a07dd0e72..d83132bb6 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.5.2 + 8.5.3 CFBundleSignature ???? CFBundleVersion - 8.5.2 + 8.5.3 NSPrincipalClass diff --git a/package.json b/package.json index 6d0a94ae0..5f9238b06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.5.2", + "version": "8.5.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 2fd0dead0c86d6be08e040360dec9ea085ba0392 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 19 Apr 2024 22:00:59 -0400 Subject: [PATCH 070/368] chore: remove old iOS/Xcode related test code and errors (#890) * chore: remove old Xcode 12 and below stuff * keep comment * cleanup more * remove included ones * Update XCUIElementFBFindTests.m --- .../Commands/FBElementCommands.m | 8 --- .../FBElementAttributeTests.m | 11 +--- .../FBElementVisibilityTests.m | 5 -- .../IntegrationTests/XCUIElementFBFindTests.m | 60 +++++-------------- 4 files changed, 18 insertions(+), 66 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 0313302f2..762bad327 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -352,10 +352,6 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [self targetFromRequest:request]; - if (![element respondsToSelector:@selector(pressForDuration:thenDragToElement:withVelocity:thenHoldForDuration:)]) { - return FBResponseWithStatus([FBCommandStatus unsupportedOperationErrorWithMessage:@"This method is only supported in Xcode 12 and above" - traceback:nil]); - } [element pressForDuration:[request.arguments[@"pressDuration"] doubleValue] thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"]] withVelocity:[request.arguments[@"velocity"] doubleValue] @@ -370,10 +366,6 @@ + (NSArray *)routes (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 diff --git a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m index 13cba4e57..2d6f30c5b 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m @@ -48,14 +48,9 @@ - (void)testContainerAccessibilityAttributes XCUIElement *inaccessibleButtonElement = self.testedApplication.buttons[@"not_accessible"]; XCTAssertTrue(inaccessibleButtonElement.exists); XCTAssertFalse(inaccessibleButtonElement.fb_isAccessibilityElement); - if (@available(iOS 13.0, *)) { - // FIXME: Xcode 11 environment returns false even if iOS 12 - // We must fix here to XCTAssertTrue if Xcode version will return the value properly - XCTAssertFalse(inaccessibleButtonElement.isWDAccessibilityContainer); - } else { - // Xcode 10 and the below works fine - XCTAssertTrue(inaccessibleButtonElement.isWDAccessibilityContainer); - } + // FIXME: Xcode 11 environment returns false even if iOS 12 + // We must fix here to XCTAssertTrue if Xcode version will return the value properly + XCTAssertFalse(inaccessibleButtonElement.isWDAccessibilityContainer); } - (void)testIgnoredAccessibilityAttributes diff --git a/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m b/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m index d791e8ab5..1449e1ae8 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementVisibilityTests.m @@ -63,11 +63,6 @@ - (void)disabled_testIconsFromSearchDashboard - (void)testTableViewCells { - if (SYSTEM_VERSION_GREATER_THAN(@"12.0")) { - // The test is flacky on iOS 12+ in Travis env - return; - } - [self launchApplication]; [self goToScrollPageWithCells:YES]; for (int i = 0 ; i < 10 ; i++) { diff --git a/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m b/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m index 243ebec5d..713aee760 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m @@ -71,10 +71,7 @@ - (void)testDescendantsWithIdentifier { NSArray *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"Alerts" shouldReturnAfterFirstMatch:NO]; - int snapshotsCount = 1; - if (@available(iOS 13.0, *)) { - snapshotsCount = 2; - } + int snapshotsCount = 2; XCTAssertEqual(matchingSnapshots.count, snapshotsCount); XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton); XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts"); @@ -162,10 +159,7 @@ - (void)testDescendantsWithComplexXPathQuery { NSArray *matchingSnapshots = [self.testedView fb_descendantsMatchingXPathQuery:@"//*[@label='Scrolling']/preceding::*[boolean(string(@label))]" shouldReturnAfterFirstMatch:NO]; - int snapshotsCount = 3; - if (@available(iOS 13.0, *)) { - snapshotsCount = 6; - } + int snapshotsCount = 6; XCTAssertEqual(matchingSnapshots.count, snapshotsCount); } @@ -198,10 +192,7 @@ - (void)testDescendantsWithPredicateString NSPredicate *predicate = [NSPredicate predicateWithFormat:@"label = 'Alerts'"]; NSArray *matchingSnapshots = [self.testedView fb_descendantsMatchingPredicate:predicate shouldReturnAfterFirstMatch:NO]; - int snapshotsCount = 1; - if (@available(iOS 13.0, *)) { - snapshotsCount = 2; - } + int snapshotsCount = 2; XCTAssertEqual(matchingSnapshots.count, snapshotsCount); XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton); XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts"); @@ -243,10 +234,7 @@ - (void)testDescendantsWithPropertyStrict partialSearch:NO]; XCTAssertEqual(matchingSnapshots.count, 0); matchingSnapshots = [self.testedView fb_descendantsMatchingProperty:@"label" value:@"Alerts" partialSearch:NO]; - int snapshotsCount = 1; - if (@available(iOS 13.0, *)) { - snapshotsCount = 2; - } + int snapshotsCount = 2; XCTAssertEqual(matchingSnapshots.count, snapshotsCount); XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton); XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts"); @@ -259,10 +247,7 @@ - (void)testGlobalWithPropertyStrict partialSearch:NO]; XCTAssertEqual(matchingSnapshots.count, 0); matchingSnapshots = [self.testedApplication fb_descendantsMatchingProperty:@"label" value:@"Alerts" partialSearch:NO]; - int snapshotsCount = 1; - if (@available(iOS 13.0, *)) { - snapshotsCount = 2; - } + int snapshotsCount = 2; XCTAssertEqual(matchingSnapshots.count, snapshotsCount); XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton); XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts"); @@ -273,10 +258,7 @@ - (void)testDescendantsWithPropertyPartial NSArray *matchingSnapshots = [self.testedView fb_descendantsMatchingProperty:@"label" value:@"Alerts" partialSearch:NO]; - int snapshotsCount = 1; - if (@available(iOS 13.0, *)) { - snapshotsCount = 2; - } + int snapshotsCount = 2; XCTAssertEqual(matchingSnapshots.count, snapshotsCount); XCTAssertEqual(matchingSnapshots.firstObject.elementType, XCUIElementTypeButton); XCTAssertEqualObjects(matchingSnapshots.lastObject.label, @"Alerts"); @@ -297,19 +279,13 @@ - (void)testDescendantsWithClassChain - (void)testDescendantsWithClassChainWithIndex { NSArray *matchingSnapshots; - NSString *queryString = @"XCUIElementTypeWindow/*/*[2]/*/*/XCUIElementTypeButton"; - if (@available(iOS 13.0, *)) { - // iPhone - queryString = @"XCUIElementTypeWindow/*/*/*/*[2]/*/*/XCUIElementTypeButton"; - matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString - shouldReturnAfterFirstMatch:NO]; - if (matchingSnapshots.count == 0) { - // iPad - queryString = @"XCUIElementTypeWindow/*/*/*/*/*[2]/*/*/XCUIElementTypeButton"; - matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString - shouldReturnAfterFirstMatch:NO]; - } - } else { + // iPhone + NSString *queryString = @"XCUIElementTypeWindow/*/*/*/*[2]/*/*/XCUIElementTypeButton"; + matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString + shouldReturnAfterFirstMatch:NO]; + if (matchingSnapshots.count == 0) { + // iPad + queryString = @"XCUIElementTypeWindow/*/*/*/*/*[2]/*/*/XCUIElementTypeButton"; matchingSnapshots = [self.testedApplication fb_descendantsMatchingClassChain:queryString shouldReturnAfterFirstMatch:NO]; } @@ -444,10 +420,7 @@ - (void)setUp - (void)testNestedQueryWithClassChain { - NSString *queryString = @"XCUIElementTypeOther"; - if (@available(iOS 13.0, *)) { - queryString = @"XCUIElementTypePicker"; - } + NSString *queryString = @"XCUIElementTypePicker"; FBAssertWaitTillBecomesTrue(self.testedApplication.buttons[@"Button"].fb_isVisible); XCUIElement *datePicker = [self.testedApplication descendantsMatchingType:XCUIElementTypeDatePicker].allElementsBoundByIndex.firstObject; @@ -455,10 +428,7 @@ - (void)testNestedQueryWithClassChain shouldReturnAfterFirstMatch:NO]; XCTAssertEqual(matches.count, 1); - XCUIElementType expectedType = XCUIElementTypeOther; - if (@available(iOS 13.0, *)) { - expectedType = XCUIElementTypePicker; - } + XCUIElementType expectedType = XCUIElementTypePicker; XCTAssertEqual([matches firstObject].elementType, expectedType); } From e1801729711e57bb03529979ce1a7833f0fd447e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 20 Apr 2024 02:08:38 +0000 Subject: [PATCH 071/368] chore(release): 8.5.4 [skip ci] ## [8.5.4](https://github.com/appium/WebDriverAgent/compare/v8.5.3...v8.5.4) (2024-04-20) ### Miscellaneous Chores * remove old iOS/Xcode related test code and errors ([#890](https://github.com/appium/WebDriverAgent/issues/890)) ([2fd0dea](https://github.com/appium/WebDriverAgent/commit/2fd0dead0c86d6be08e040360dec9ea085ba0392)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20d4ce072..28f05f2cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.5.4](https://github.com/appium/WebDriverAgent/compare/v8.5.3...v8.5.4) (2024-04-20) + + +### Miscellaneous Chores + +* remove old iOS/Xcode related test code and errors ([#890](https://github.com/appium/WebDriverAgent/issues/890)) ([2fd0dea](https://github.com/appium/WebDriverAgent/commit/2fd0dead0c86d6be08e040360dec9ea085ba0392)) + ## [8.5.3](https://github.com/appium/WebDriverAgent/compare/v8.5.2...v8.5.3) (2024-04-19) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index d83132bb6..4903191d6 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.5.3 + 8.5.4 CFBundleSignature ???? CFBundleVersion - 8.5.3 + 8.5.4 NSPrincipalClass diff --git a/package.json b/package.json index 5f9238b06..189cff481 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.5.3", + "version": "8.5.4", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 63980796d8f40bd68ffb5af4b085a2348e544a13 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 20 Apr 2024 03:16:45 -0400 Subject: [PATCH 072/368] fix: xcode warning about com.facebook.wda.lib (#892) --- WebDriverAgentLib/Info.plist | 46 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 4903191d6..6320d4152 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -1,26 +1,26 @@ - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - com.facebook.wda.lib - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 8.5.4 - CFBundleSignature - ???? - CFBundleVersion - 8.5.4 - NSPrincipalClass - - - \ No newline at end of file + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 8.5.4 + CFBundleSignature + ???? + CFBundleVersion + 8.5.4 + NSPrincipalClass + + + From 96f1e23eabcb9486f75887ec993d75cf03330b0b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 20 Apr 2024 07:22:57 +0000 Subject: [PATCH 073/368] chore(release): 8.5.5 [skip ci] ## [8.5.5](https://github.com/appium/WebDriverAgent/compare/v8.5.4...v8.5.5) (2024-04-20) ### Bug Fixes * xcode warning about com.facebook.wda.lib ([#892](https://github.com/appium/WebDriverAgent/issues/892)) ([6398079](https://github.com/appium/WebDriverAgent/commit/63980796d8f40bd68ffb5af4b085a2348e544a13)) --- CHANGELOG.md | 7 ++++++ WebDriverAgentLib/Info.plist | 46 ++++++++++++++++++------------------ package.json | 2 +- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28f05f2cf..5aac3fd4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.5.5](https://github.com/appium/WebDriverAgent/compare/v8.5.4...v8.5.5) (2024-04-20) + + +### Bug Fixes + +* xcode warning about com.facebook.wda.lib ([#892](https://github.com/appium/WebDriverAgent/issues/892)) ([6398079](https://github.com/appium/WebDriverAgent/commit/63980796d8f40bd68ffb5af4b085a2348e544a13)) + ## [8.5.4](https://github.com/appium/WebDriverAgent/compare/v8.5.3...v8.5.4) (2024-04-20) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 6320d4152..d3379111e 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -1,26 +1,26 @@ - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 8.5.4 - CFBundleSignature - ???? - CFBundleVersion - 8.5.4 - NSPrincipalClass - - - + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 8.5.5 + CFBundleSignature + ???? + CFBundleVersion + 8.5.5 + NSPrincipalClass + + + \ No newline at end of file diff --git a/package.json b/package.json index 189cff481..8bb133a01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.5.4", + "version": "8.5.5", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 31c385394c6a619631138752ee1515361628aaec Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 20 Apr 2024 03:38:07 -0400 Subject: [PATCH 074/368] ci: use Xcode 15.3 to build wda (#893) --- .github/workflows/publish.js.yml | 4 ++-- .github/workflows/wda-package.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.js.yml b/.github/workflows/publish.js.yml index 92299e7a8..5295e5802 100644 --- a/.github/workflows/publish.js.yml +++ b/.github/workflows/publish.js.yml @@ -10,10 +10,10 @@ on: jobs: build: - runs-on: macos-13 + runs-on: macos-14 env: - XCODE_VERSION: 14.3.1 + XCODE_VERSION: 15.3 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 b4b4223f2..8a7d7a526 100644 --- a/.github/workflows/wda-package.yml +++ b/.github/workflows/wda-package.yml @@ -8,10 +8,10 @@ on: - completed env: - 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 + HOST: macos-14 + XCODE_VERSION: 15.3 + DESTINATION_SIM: platform=iOS Simulator,name=iPhone 15 Pro + DESTINATION_SIM_tvOS: platform=tvOS Simulator,name=Apple TV 4K (3rd generation) jobs: host_machine: From 2e34cffe21b8d5552f41771fbdf854ca6ea6403c Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 20 Apr 2024 01:15:30 -0700 Subject: [PATCH 075/368] test: fix test for arm64 --- test/unit/utils-specs.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/test/unit/utils-specs.js b/test/unit/utils-specs.js index 1d61b4854..392d3d16f 100644 --- a/test/unit/utils-specs.js +++ b/test/unit/utils-specs.js @@ -6,10 +6,15 @@ import { withMocks } from '@appium/test-support'; import { fs } from '@appium/support'; import path from 'path'; import { fail } from 'assert'; +import { arch } from 'os'; chai.should(); chai.use(chaiAsPromised); +function get_arch() { + return arch() === 'arm64' ? 'arm64' : 'x86_64'; +} + describe('utils', function () { describe('#getXctestrunFilePath', withMocks({fs}, function (mocks) { const platformVersion = '12.0'; @@ -38,7 +43,7 @@ describe('utils', function () { .withExactArgs(path.resolve(`${bootstrapPath}/${udid}_${sdkVersion}.xctestrun`)) .returns(false); mocks.fs.expects('exists') - .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphoneos${sdkVersion}-arm64.xctestrun`)) + .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphoneos${sdkVersion}-${get_arch()}.xctestrun`)) .returns(true); mocks.fs.expects('copyFile') .withExactArgs( @@ -56,7 +61,7 @@ describe('utils', function () { .withExactArgs(path.resolve(`${bootstrapPath}/${udid}_${sdkVersion}.xctestrun`)) .returns(false); mocks.fs.expects('exists') - .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${sdkVersion}-x86_64.xctestrun`)) + .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${sdkVersion}-${get_arch()}.xctestrun`)) .returns(false); mocks.fs.expects('exists') .withExactArgs(path.resolve(`${bootstrapPath}/${udid}_${platformVersion}.xctestrun`)) @@ -73,17 +78,17 @@ describe('utils', function () { .withExactArgs(path.resolve(`${bootstrapPath}/${udid}_${sdkVersion}.xctestrun`)) .returns(false); mocks.fs.expects('exists') - .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${sdkVersion}-x86_64.xctestrun`)) + .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${sdkVersion}-${get_arch()}.xctestrun`)) .returns(false); mocks.fs.expects('exists') .withExactArgs(path.resolve(`${bootstrapPath}/${udid}_${platformVersion}.xctestrun`)) .returns(false); mocks.fs.expects('exists') - .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${platformVersion}-x86_64.xctestrun`)) + .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${platformVersion}-${get_arch()}.xctestrun`)) .returns(true); mocks.fs.expects('copyFile') .withExactArgs( - path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${platformVersion}-x86_64.xctestrun`), + path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${platformVersion}-${get_arch()}.xctestrun`), path.resolve(`${bootstrapPath}/${udid}_${platformVersion}.xctestrun`) ) .returns(true); @@ -94,7 +99,7 @@ describe('utils', function () { }); it('should raise an exception because of no files', async function () { - const expected = path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${sdkVersion}-x86_64.xctestrun`); + const expected = path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphonesimulator${sdkVersion}-${get_arch()}.xctestrun`); mocks.fs.expects('exists').exactly(4).returns(false); const deviceInfo = {isRealDevice: false, udid, platformVersion}; @@ -140,7 +145,7 @@ describe('utils', function () { const deviceInfo = {isRealDevice: false, udid, platformVersion, platformName}; getXctestrunFileName(deviceInfo, '10.2.0').should.equal( - 'WebDriverAgentRunner_iphonesimulator10.2.0-x86_64.xctestrun'); + `WebDriverAgentRunner_iphonesimulator10.2.0-${get_arch()}.xctestrun`); }); it('should return tvos format, real device', function () { @@ -156,7 +161,7 @@ describe('utils', function () { const deviceInfo = {isRealDevice: false, udid, platformVersion, platformName}; getXctestrunFileName(deviceInfo, '10.2.0').should.equal( - 'WebDriverAgentRunner_tvOS_appletvsimulator10.2.0-x86_64.xctestrun'); + `WebDriverAgentRunner_tvOS_appletvsimulator10.2.0-${get_arch()}.xctestrun`); }); }); }); From 2e287e7a837685b80b5077ca650eb21b91b68d97 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 20 Apr 2024 01:20:27 -0700 Subject: [PATCH 076/368] test: fix unit test one more --- test/unit/utils-specs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/utils-specs.js b/test/unit/utils-specs.js index 392d3d16f..afd13479b 100644 --- a/test/unit/utils-specs.js +++ b/test/unit/utils-specs.js @@ -47,7 +47,7 @@ describe('utils', function () { .returns(true); mocks.fs.expects('copyFile') .withExactArgs( - path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphoneos${sdkVersion}-arm64.xctestrun`), + path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphoneos${sdkVersion}-${get_arch()}.xctestrun`), path.resolve(`${bootstrapPath}/${udid}_${sdkVersion}.xctestrun`) ) .returns(true); From 3a9015898d70b177cb6cbfcaf412dfa3c4ec3865 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 20 Apr 2024 04:32:19 -0400 Subject: [PATCH 077/368] fix: unit test for linux (#894) * fix: unit test for linux * keep arm64 --- test/unit/utils-specs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/utils-specs.js b/test/unit/utils-specs.js index afd13479b..ad0548e5e 100644 --- a/test/unit/utils-specs.js +++ b/test/unit/utils-specs.js @@ -43,11 +43,11 @@ describe('utils', function () { .withExactArgs(path.resolve(`${bootstrapPath}/${udid}_${sdkVersion}.xctestrun`)) .returns(false); mocks.fs.expects('exists') - .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphoneos${sdkVersion}-${get_arch()}.xctestrun`)) + .withExactArgs(path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphoneos${sdkVersion}-arm64.xctestrun`)) .returns(true); mocks.fs.expects('copyFile') .withExactArgs( - path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphoneos${sdkVersion}-${get_arch()}.xctestrun`), + path.resolve(`${bootstrapPath}/WebDriverAgentRunner_iphoneos${sdkVersion}-arm64.xctestrun`), path.resolve(`${bootstrapPath}/${udid}_${sdkVersion}.xctestrun`) ) .returns(true); From 53bcaa87ba45dcda433daf23631e245139599413 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 20 Apr 2024 08:35:12 +0000 Subject: [PATCH 078/368] chore(release): 8.5.6 [skip ci] ## [8.5.6](https://github.com/appium/WebDriverAgent/compare/v8.5.5...v8.5.6) (2024-04-20) ### Bug Fixes * unit test for linux ([#894](https://github.com/appium/WebDriverAgent/issues/894)) ([3a90158](https://github.com/appium/WebDriverAgent/commit/3a9015898d70b177cb6cbfcaf412dfa3c4ec3865)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5aac3fd4a..624ae23fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.5.6](https://github.com/appium/WebDriverAgent/compare/v8.5.5...v8.5.6) (2024-04-20) + + +### Bug Fixes + +* unit test for linux ([#894](https://github.com/appium/WebDriverAgent/issues/894)) ([3a90158](https://github.com/appium/WebDriverAgent/commit/3a9015898d70b177cb6cbfcaf412dfa3c4ec3865)) + ## [8.5.5](https://github.com/appium/WebDriverAgent/compare/v8.5.4...v8.5.5) (2024-04-20) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index d3379111e..89830e689 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.5.5 + 8.5.6 CFBundleSignature ???? CFBundleVersion - 8.5.5 + 8.5.6 NSPrincipalClass diff --git a/package.json b/package.json index 8bb133a01..1e0047bc5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.5.5", + "version": "8.5.6", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 130352cc3151c71acb674861f1443af7035a9e35 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 9 May 2024 10:20:47 +0200 Subject: [PATCH 079/368] ci: Bump conventional-pr-action to v3 (#898) --- .github/workflows/pr-title.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 9a192aec5..0ff687ca8 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -8,7 +8,7 @@ jobs: name: https://www.conventionalcommits.org runs-on: ubuntu-latest steps: - - uses: beemojs/conventional-pr-action@v2 + - uses: beemojs/conventional-pr-action@v3 with: config-preset: angular env: From 4236dc5323d6d16259898a2e419b438abd9f6b5a Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 14 May 2024 09:18:39 -0700 Subject: [PATCH 080/368] ci: use macos14 for functional test (#901) * ci: use newer instance * Update functional-test.yml * Update functional-test.yml * add matrix * move env * revert project changes * add cancel * ci: fix env place --- .github/workflows/functional-test.yml | 43 +++++++++++++++++++-------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index e5c1ebad9..90bacdc9a 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -2,17 +2,25 @@ name: Functional Tests on: [pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: test: - env: - CI: true - _FORCE_LOGS: 1 - XCODE_VERSION: 13.4 - DEVICE_NAME: iPhone 11 - PLATFORM_VERSION: 15.5 - # https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md - runs-on: macos-12 + strategy: + fail-fast: false + matrix: + test_targets: + - XCODE_VERSION: 15.3 + IOS_VERSION: 17.4 + IOS_MODEL: iPhone 15 Plus + - XCODE_VERSION: 14.3.1 + IOS_VERSION: 16.4 + IOS_MODEL: iPhone 14 Plus + + # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md + runs-on: macos-14 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 @@ -20,17 +28,26 @@ jobs: node-version: lts/* - uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: "${{ env.XCODE_VERSION }}" + xcode-version: ${{matrix.test_targets.XCODE_VERSION}} - run: | 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 + - uses: futureware-tech/simulator-action@v3 + with: + model: ${{matrix.test_targets.IOS_MODEL}} + os: iOS + os_version: ${{matrix.test_targets.IOS_VERSION}} + erase_before_boot: true + # to prevent unexpected shutdown failure error + shutdown_after_job: false name: Preboot Simulator - run: npm run e2e-test name: Run functional tests + env: + CI: true + _FORCE_LOGS: 1 + DEVICE_NAME: ${{matrix.test_targets.IOS_MODEL}} + PLATFORM_VERSION: ${{matrix.test_targets.IOS_VERSION}} From e49dcf2afb0a10edc7085ac56d297234c00d57b0 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 16 May 2024 17:39:20 +0200 Subject: [PATCH 081/368] chore: Update dev dependencies --- package.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/package.json b/package.json index 1e0047bc5..045666885 100644 --- a/package.json +++ b/package.json @@ -68,12 +68,6 @@ "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "conventional-changelog-conventionalcommits": "^7.0.1", - "eslint": "^8.46.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", - "eslint-plugin-promise": "^6.1.1", "fancy-log": "^2.0.0", "node-simctl": "^7.0.1", "mocha": "^10.0.0", From 3f40861fff23c5c1db0fab156cfaf7694007b7eb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 16 May 2024 15:56:31 +0000 Subject: [PATCH 082/368] chore(release): 8.5.7 [skip ci] ## [8.5.7](https://github.com/appium/WebDriverAgent/compare/v8.5.6...v8.5.7) (2024-05-16) ### Miscellaneous Chores * Update dev dependencies ([e49dcf2](https://github.com/appium/WebDriverAgent/commit/e49dcf2afb0a10edc7085ac56d297234c00d57b0)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 624ae23fd..b30c55df8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.5.7](https://github.com/appium/WebDriverAgent/compare/v8.5.6...v8.5.7) (2024-05-16) + + +### Miscellaneous Chores + +* Update dev dependencies ([e49dcf2](https://github.com/appium/WebDriverAgent/commit/e49dcf2afb0a10edc7085ac56d297234c00d57b0)) + ## [8.5.6](https://github.com/appium/WebDriverAgent/compare/v8.5.5...v8.5.6) (2024-04-20) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 89830e689..16152a570 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.5.6 + 8.5.7 CFBundleSignature ???? CFBundleVersion - 8.5.6 + 8.5.7 NSPrincipalClass diff --git a/package.json b/package.json index 045666885..cfbf4e3d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.5.6", + "version": "8.5.7", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From fa4776a2bfa15cbec8bba35d8ed11318d9629934 Mon Sep 17 00:00:00 2001 From: KAdachi <27220367+ppken@users.noreply.github.com> Date: Sat, 18 May 2024 01:59:41 +0900 Subject: [PATCH 083/368] feat: support maxTypingFrequency in settings api (#904) * feat: support maxTypingFrequency in settings api * fix: keep FB_CAP_MAX_TYPING_FREQUENCY --- WebDriverAgentLib/Commands/FBSessionCommands.m | 4 ++++ WebDriverAgentLib/Utilities/FBSettings.h | 1 + WebDriverAgentLib/Utilities/FBSettings.m | 1 + lib/types.ts | 1 + 4 files changed, 7 insertions(+) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index cd6a28a90..c490a6820 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -344,6 +344,7 @@ + (NSArray *)routes FB_SETTING_ACCEPT_ALERT_BUTTON_SELECTOR: FBConfiguration.acceptAlertButtonSelector, FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR: FBConfiguration.dismissAlertButtonSelector, FB_SETTING_DEFAULT_ALERT_ACTION: request.session.defaultAlertAction ?: @"", + FB_SETTING_MAX_TYPING_FREQUENCY: @([FBConfiguration maxTypingFrequency]), #if !TARGET_OS_TV FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation], #endif @@ -436,6 +437,9 @@ + (NSArray *)routes if ([[settings objectForKey:FB_SETTING_DEFAULT_ALERT_ACTION] isKindOfClass:NSString.class]) { request.session.defaultAlertAction = [settings[FB_SETTING_DEFAULT_ALERT_ACTION] lowercaseString]; } + if (nil != [settings objectForKey:FB_SETTING_MAX_TYPING_FREQUENCY]) { + [FBConfiguration setMaxTypingFrequency:[[settings objectForKey:FB_SETTING_MAX_TYPING_FREQUENCY] unsignedIntegerValue]]; + } #if !TARGET_OS_TV if (nil != [settings objectForKey:FB_SETTING_SCREENSHOT_ORIENTATION]) { diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index dd82d740c..98862f0a0 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -38,6 +38,7 @@ extern NSString* const FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR; extern NSString* const FB_SETTING_SCREENSHOT_ORIENTATION; extern NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT; extern NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT; +extern NSString* const FB_SETTING_MAX_TYPING_FREQUENCY; NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index 6b12a4cd4..d4715d9a0 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -33,3 +33,4 @@ NSString* const FB_SETTING_SCREENSHOT_ORIENTATION = @"screenshotOrientation"; NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT = @"waitForIdleTimeout"; NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT = @"animationCoolOffTimeout"; +NSString* const FB_SETTING_MAX_TYPING_FREQUENCY = @"maxTypingFrequency"; diff --git a/lib/types.ts b/lib/types.ts index 3c6a22538..8b41dfc4e 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -24,6 +24,7 @@ export interface WDASettings { screenshotOrientation?: 'auto' | 'portrait' | 'portraitUpsideDown' | 'landscapeRight' | 'landscapeLeft' waitForIdleTimeout?: number; animationCoolOffTimeout?: number; + maxTypingFrequency?: number; } // WebDriverAgentLib/Utilities/FBCapabilities.h From 62f68cd5fdbf877c3d1f9b5c0da7cbbae941cc7a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 17 May 2024 17:06:00 +0000 Subject: [PATCH 084/368] chore(release): 8.6.0 [skip ci] ## [8.6.0](https://github.com/appium/WebDriverAgent/compare/v8.5.7...v8.6.0) (2024-05-17) ### Features * support maxTypingFrequency in settings api ([#904](https://github.com/appium/WebDriverAgent/issues/904)) ([fa4776a](https://github.com/appium/WebDriverAgent/commit/fa4776a2bfa15cbec8bba35d8ed11318d9629934)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b30c55df8..2053ab6e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.6.0](https://github.com/appium/WebDriverAgent/compare/v8.5.7...v8.6.0) (2024-05-17) + + +### Features + +* support maxTypingFrequency in settings api ([#904](https://github.com/appium/WebDriverAgent/issues/904)) ([fa4776a](https://github.com/appium/WebDriverAgent/commit/fa4776a2bfa15cbec8bba35d8ed11318d9629934)) + ## [8.5.7](https://github.com/appium/WebDriverAgent/compare/v8.5.6...v8.5.7) (2024-05-16) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 16152a570..1d6637a44 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.5.7 + 8.6.0 CFBundleSignature ???? CFBundleVersion - 8.5.7 + 8.6.0 NSPrincipalClass diff --git a/package.json b/package.json index cfbf4e3d4..371d8b480 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.5.7", + "version": "8.6.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 5c82d66890b1a74f9b6f698c87590b2154a6c1bd Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 1 Jun 2024 22:58:36 +0200 Subject: [PATCH 085/368] feat: Add a setting to respect system alerts while detecting active apps (#907) --- WebDriverAgentLib/Commands/FBSessionCommands.m | 4 ++++ WebDriverAgentLib/Routing/FBSession.m | 4 ++++ WebDriverAgentLib/Utilities/FBConfiguration.h | 4 ++++ WebDriverAgentLib/Utilities/FBConfiguration.m | 11 +++++++++++ WebDriverAgentLib/Utilities/FBSettings.h | 1 + WebDriverAgentLib/Utilities/FBSettings.m | 1 + 6 files changed, 25 insertions(+) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index c490a6820..7b3c4dbb5 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -345,6 +345,7 @@ + (NSArray *)routes FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR: FBConfiguration.dismissAlertButtonSelector, FB_SETTING_DEFAULT_ALERT_ACTION: request.session.defaultAlertAction ?: @"", FB_SETTING_MAX_TYPING_FREQUENCY: @([FBConfiguration maxTypingFrequency]), + FB_SETTING_RESPECT_SYSTEM_ALERTS: @([FBConfiguration shouldRespectSystemAlerts]), #if !TARGET_OS_TV FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation], #endif @@ -385,6 +386,9 @@ + (NSArray *)routes if (nil != [settings objectForKey:FB_SETTING_KEYBOARD_PREDICTION]) { [FBConfiguration setKeyboardPrediction:[[settings objectForKey:FB_SETTING_KEYBOARD_PREDICTION] boolValue]]; } + if (nil != [settings objectForKey:FB_SETTING_RESPECT_SYSTEM_ALERTS]) { + [FBConfiguration setShouldRespectSystemAlerts:[[settings objectForKey:FB_SETTING_RESPECT_SYSTEM_ALERTS] boolValue]]; + } // SNAPSHOT_TIMEOUT setting is deprecated. Please use CUSTOM_SNAPSHOT_TIMEOUT instead if (nil != [settings objectForKey:FB_SETTING_SNAPSHOT_TIMEOUT]) { [FBConfiguration setCustomSnapshotTimeout:[[settings objectForKey:FB_SETTING_SNAPSHOT_TIMEOUT] doubleValue]]; diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index 82134e0cc..2b1753cd2 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -176,6 +176,10 @@ - (XCUIApplication *)activeApplication if (nil != self.testedApplication) { XCUIApplicationState testedAppState = self.testedApplication.state; if (testedAppState >= XCUIApplicationStateRunningForeground) { + if ([FBConfiguration shouldRespectSystemAlerts] + && [XCUIApplication.fb_systemApplication descendantsMatchingType:XCUIElementTypeAlert].count > 0) { + return XCUIApplication.fb_systemApplication; + } return (XCUIApplication *)self.testedApplication; } if (self.isTestedApplicationExpectedToRun && testedAppState <= XCUIApplicationStateNotRunning) { diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index c07c31a1e..dc2018928 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -66,6 +66,10 @@ extern NSString *const FBSnapshotMaxDepthKey; + (void)setShouldUseSingletonTestManager:(BOOL)value; + (BOOL)shouldUseSingletonTestManager; +/* Enforces WDA to verify the presense of system alerts while checking for an active app */ ++ (void)setShouldRespectSystemAlerts:(BOOL)value; ++ (BOOL)shouldRespectSystemAlerts; + /** * Extract switch value from arguments * diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index 3bb740a0b..1d7438ae1 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -31,6 +31,7 @@ static BOOL FBShouldUseTestManagerForVisibilityDetection = NO; static BOOL FBShouldUseSingletonTestManager = YES; +static BOOL FBShouldRespectSystemAlerts = NO; static NSUInteger FBMjpegScalingFactor = 100; static BOOL FBMjpegShouldFixOrientation = NO; @@ -373,6 +374,16 @@ + (int)snapshotMaxDepth return [FBGetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey) intValue]; } ++ (void)setShouldRespectSystemAlerts:(BOOL)value +{ + FBShouldRespectSystemAlerts = value; +} + ++ (BOOL)shouldRespectSystemAlerts +{ + return FBShouldRespectSystemAlerts; +} + + (void)setUseFirstMatch:(BOOL)enabled { FBShouldUseFirstMatch = enabled; diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index 98862f0a0..5f4450110 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -39,6 +39,7 @@ extern NSString* const FB_SETTING_SCREENSHOT_ORIENTATION; extern NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT; extern NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT; extern NSString* const FB_SETTING_MAX_TYPING_FREQUENCY; +extern NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS; NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index d4715d9a0..a45afeb90 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -34,3 +34,4 @@ NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT = @"waitForIdleTimeout"; NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT = @"animationCoolOffTimeout"; NSString* const FB_SETTING_MAX_TYPING_FREQUENCY = @"maxTypingFrequency"; +NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS = @"respectSystemAlerts"; From c1d57f61f5befd1a3e8ded5a4005ca69f18f947a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 1 Jun 2024 21:02:59 +0000 Subject: [PATCH 086/368] chore(release): 8.7.0 [skip ci] ## [8.7.0](https://github.com/appium/WebDriverAgent/compare/v8.6.0...v8.7.0) (2024-06-01) ### Features * Add a setting to respect system alerts while detecting active apps ([#907](https://github.com/appium/WebDriverAgent/issues/907)) ([5c82d66](https://github.com/appium/WebDriverAgent/commit/5c82d66890b1a74f9b6f698c87590b2154a6c1bd)) --- CHANGELOG.md | 7 +++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2053ab6e5..63a285a38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [8.7.0](https://github.com/appium/WebDriverAgent/compare/v8.6.0...v8.7.0) (2024-06-01) + + +### Features + +* Add a setting to respect system alerts while detecting active apps ([#907](https://github.com/appium/WebDriverAgent/issues/907)) ([5c82d66](https://github.com/appium/WebDriverAgent/commit/5c82d66890b1a74f9b6f698c87590b2154a6c1bd)) + ## [8.6.0](https://github.com/appium/WebDriverAgent/compare/v8.5.7...v8.6.0) (2024-05-17) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 1d6637a44..f4acb11de 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.6.0 + 8.7.0 CFBundleSignature ???? CFBundleVersion - 8.6.0 + 8.7.0 NSPrincipalClass diff --git a/package.json b/package.json index 371d8b480..c53f7eb20 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.6.0", + "version": "8.7.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 26019eca9b7331353e26a1014bc4afcecc0450f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 22:22:25 -0700 Subject: [PATCH 087/368] chore(deps-dev): bump semantic-release from 23.1.1 to 24.0.0 and conventional-changelog-conventionalcommits to 8.0.0 (#908) * chore(deps-dev): bump semantic-release from 23.1.1 to 24.0.0 Bumps [semantic-release](https://github.com/semantic-release/semantic-release) from 23.1.1 to 24.0.0. - [Release notes](https://github.com/semantic-release/semantic-release/releases) - [Commits](https://github.com/semantic-release/semantic-release/compare/v23.1.1...v24.0.0) --- updated-dependencies: - dependency-name: semantic-release dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update package.json --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kazuaki Matsuo --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c53f7eb20..a9206a8a2 100644 --- a/package.json +++ b/package.json @@ -67,12 +67,12 @@ "appium-xcode": "^5.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "conventional-changelog-conventionalcommits": "^7.0.1", + "conventional-changelog-conventionalcommits": "^8.0.0", "fancy-log": "^2.0.0", "node-simctl": "^7.0.1", "mocha": "^10.0.0", "prettier": "^3.0.0", - "semantic-release": "^23.0.0", + "semantic-release": "^24.0.0", "semver": "^7.3.7", "sinon": "^17.0.0", "ts-node": "^10.9.1", From f26f732fd9f87ba172f30b867090ed4e27a9c634 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 4 Jun 2024 05:27:06 +0000 Subject: [PATCH 088/368] chore(release): 8.7.1 [skip ci] ## [8.7.1](https://github.com/appium/WebDriverAgent/compare/v8.7.0...v8.7.1) (2024-06-04) ### Miscellaneous Chores * **deps-dev:** bump semantic-release from 23.1.1 to 24.0.0 and conventional-changelog-conventionalcommits to 8.0.0 ([#908](https://github.com/appium/WebDriverAgent/issues/908)) ([26019ec](https://github.com/appium/WebDriverAgent/commit/26019eca9b7331353e26a1014bc4afcecc0450f3)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a285a38..c013d00c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.1](https://github.com/appium/WebDriverAgent/compare/v8.7.0...v8.7.1) (2024-06-04) + +### Miscellaneous Chores + +* **deps-dev:** bump semantic-release from 23.1.1 to 24.0.0 and conventional-changelog-conventionalcommits to 8.0.0 ([#908](https://github.com/appium/WebDriverAgent/issues/908)) ([26019ec](https://github.com/appium/WebDriverAgent/commit/26019eca9b7331353e26a1014bc4afcecc0450f3)) + ## [8.7.0](https://github.com/appium/WebDriverAgent/compare/v8.6.0...v8.7.0) (2024-06-01) diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index f4acb11de..ddfc9de35 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.0 + 8.7.1 CFBundleSignature ???? CFBundleVersion - 8.7.0 + 8.7.1 NSPrincipalClass diff --git a/package.json b/package.json index a9206a8a2..d2e8020be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.0", + "version": "8.7.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 87e4ba5ce3868d99ac889795039936be119ef87a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 14:50:14 +0300 Subject: [PATCH 089/368] chore(deps-dev): bump sinon from 17.0.2 to 18.0.0 (#903) Bumps [sinon](https://github.com/sinonjs/sinon) from 17.0.2 to 18.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/v17.0.2...v18.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 d2e8020be..b8db2877d 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "prettier": "^3.0.0", "semantic-release": "^24.0.0", "semver": "^7.3.7", - "sinon": "^17.0.0", + "sinon": "^18.0.0", "ts-node": "^10.9.1", "typescript": "^5.4.2" }, From 4684a2a56980c9d6038f7218b511a6f0f0207ad6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 4 Jun 2024 11:55:23 +0000 Subject: [PATCH 090/368] chore(release): 8.7.2 [skip ci] ## [8.7.2](https://github.com/appium/WebDriverAgent/compare/v8.7.1...v8.7.2) (2024-06-04) ### Miscellaneous Chores * **deps-dev:** bump sinon from 17.0.2 to 18.0.0 ([#903](https://github.com/appium/WebDriverAgent/issues/903)) ([87e4ba5](https://github.com/appium/WebDriverAgent/commit/87e4ba5ce3868d99ac889795039936be119ef87a)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c013d00c8..0c1951fcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.2](https://github.com/appium/WebDriverAgent/compare/v8.7.1...v8.7.2) (2024-06-04) + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 17.0.2 to 18.0.0 ([#903](https://github.com/appium/WebDriverAgent/issues/903)) ([87e4ba5](https://github.com/appium/WebDriverAgent/commit/87e4ba5ce3868d99ac889795039936be119ef87a)) + ## [8.7.1](https://github.com/appium/WebDriverAgent/compare/v8.7.0...v8.7.1) (2024-06-04) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index ddfc9de35..544d8eef0 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.1 + 8.7.2 CFBundleSignature ???? CFBundleVersion - 8.7.1 + 8.7.2 NSPrincipalClass diff --git a/package.json b/package.json index b8db2877d..14cb9d2ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.1", + "version": "8.7.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 936005b458e7b5b64b60d9bda37d45bb5a90e615 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 18:26:10 +0200 Subject: [PATCH 091/368] chore(deps): bump @appium/support from 4.5.0 to 5.0.3 (#910) Bumps [@appium/support](https://github.com/appium/appium/tree/HEAD/packages/support) from 4.5.0 to 5.0.3. - [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@5.0.3/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 14cb9d2ca..759724595 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "dependencies": { "@appium/base-driver": "^9.0.0", "@appium/strongbox": "^0.x", - "@appium/support": "^4.0.0", + "@appium/support": "^5.0.3", "appium-ios-device": "^2.5.0", "appium-ios-simulator": "^6.0.0", "async-lock": "^1.0.0", From 41472d2fad9332c3b83a07454ae1113b97b7cab6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 12 Jun 2024 16:31:28 +0000 Subject: [PATCH 092/368] chore(release): 8.7.3 [skip ci] ## [8.7.3](https://github.com/appium/WebDriverAgent/compare/v8.7.2...v8.7.3) (2024-06-12) ### Miscellaneous Chores * **deps:** bump @appium/support from 4.5.0 to 5.0.3 ([#910](https://github.com/appium/WebDriverAgent/issues/910)) ([936005b](https://github.com/appium/WebDriverAgent/commit/936005b458e7b5b64b60d9bda37d45bb5a90e615)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1951fcc..2170bbdbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.3](https://github.com/appium/WebDriverAgent/compare/v8.7.2...v8.7.3) (2024-06-12) + +### Miscellaneous Chores + +* **deps:** bump @appium/support from 4.5.0 to 5.0.3 ([#910](https://github.com/appium/WebDriverAgent/issues/910)) ([936005b](https://github.com/appium/WebDriverAgent/commit/936005b458e7b5b64b60d9bda37d45bb5a90e615)) + ## [8.7.2](https://github.com/appium/WebDriverAgent/compare/v8.7.1...v8.7.2) (2024-06-04) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 544d8eef0..6df348aeb 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.2 + 8.7.3 CFBundleSignature ???? CFBundleVersion - 8.7.2 + 8.7.3 NSPrincipalClass diff --git a/package.json b/package.json index 759724595..11bcdd145 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.2", + "version": "8.7.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 90867832ec3077f0036938aa68a168a5702fc90a Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 20 Jun 2024 07:48:52 +0200 Subject: [PATCH 093/368] chore: Bump chai and chai-as-promised (#913) --- .github/workflows/unit-test.yml | 6 +++--- package.json | 8 ++------ test/functional/webdriveragent-e2e-specs.js | 15 ++++++++------- test/unit/utils-specs.js | 15 ++++++++++----- test/unit/webdriveragent-specs.js | 16 ++++++++++------ 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index ef98e4ca6..b23ecbee6 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -7,11 +7,11 @@ jobs: prepare_matrix: runs-on: ubuntu-latest outputs: - versions: ${{ steps.generate-matrix.outputs.versions }} + versions: ${{ steps.generate-matrix.outputs.active }} steps: - - name: Select 3 most recent LTS versions of Node.js + - name: Select all active LTS versions of Node.js id: generate-matrix - run: echo "versions=$(curl -s https://endoflife.date/api/nodejs.json | jq -c '[[.[] | select(.lts != false)][:3] | .[].cycle | tonumber]')" >> "$GITHUB_OUTPUT" + uses: msimerson/node-lts-versions@v1 test: needs: diff --git a/package.json b/package.json index 11bcdd145..00d29235e 100644 --- a/package.json +++ b/package.json @@ -56,17 +56,13 @@ "@semantic-release/changelog": "^6.0.1", "@semantic-release/git": "^10.0.1", "@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": "^17.0.0", - "@types/sinon-chai": "^3.2.9", "@types/teen_process": "^2.0.1", "appium-xcode": "^5.0.0", - "chai": "^4.2.0", - "chai-as-promised": "^7.1.1", + "chai": "^5.1.1", + "chai-as-promised": "^8.0.0", "conventional-changelog-conventionalcommits": "^8.0.0", "fancy-log": "^2.0.0", "node-simctl": "^7.0.1", diff --git a/test/functional/webdriveragent-e2e-specs.js b/test/functional/webdriveragent-e2e-specs.js index e715fb6d4..1a1a4324f 100644 --- a/test/functional/webdriveragent-e2e-specs.js +++ b/test/functional/webdriveragent-e2e-specs.js @@ -1,5 +1,3 @@ -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; import Simctl from 'node-simctl'; import { getVersion } from 'appium-xcode'; import { getSimulator } from 'appium-ios-simulator'; @@ -15,10 +13,6 @@ const MOCHA_TIMEOUT_MS = 60 * 1000 * 4; const SIM_DEVICE_NAME = 'webDriverAgentTest'; const SIM_STARTUP_TIMEOUT_MS = MOCHA_TIMEOUT_MS; - -chai.should(); -chai.use(chaiAsPromised); - let testUrl = 'http://localhost:8100/tree'; function getStartOpts (device) { @@ -36,9 +30,16 @@ function getStartOpts (device) { describe('WebDriverAgent', function () { this.timeout(MOCHA_TIMEOUT_MS); - + let chai; let xcodeVersion; + before(async function () { + chai = await import('chai'); + const chaiAsPromised = await import('chai-as-promised'); + + chai.should(); + chai.use(chaiAsPromised.default); + // Don't do these tests on Sauce Labs if (process.env.CLOUD) { this.skip(); diff --git a/test/unit/utils-specs.js b/test/unit/utils-specs.js index ad0548e5e..c8002ea43 100644 --- a/test/unit/utils-specs.js +++ b/test/unit/utils-specs.js @@ -1,21 +1,26 @@ import { getXctestrunFilePath, getAdditionalRunContent, getXctestrunFileName } from '../../lib/utils'; import { PLATFORM_NAME_IOS, PLATFORM_NAME_TVOS } from '../../lib/constants'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; import { withMocks } from '@appium/test-support'; import { fs } from '@appium/support'; import path from 'path'; import { fail } from 'assert'; import { arch } from 'os'; -chai.should(); -chai.use(chaiAsPromised); - function get_arch() { return arch() === 'arm64' ? 'arm64' : 'x86_64'; } describe('utils', function () { + let chai; + + before(async function() { + chai = await import('chai'); + const chaiAsPromised = await import('chai-as-promised'); + + chai.should(); + chai.use(chaiAsPromised.default); + }); + describe('#getXctestrunFilePath', withMocks({fs}, function (mocks) { const platformVersion = '12.0'; const sdkVersion = '12.2'; diff --git a/test/unit/webdriveragent-specs.js b/test/unit/webdriveragent-specs.js index 7887fbaef..1b844e08a 100644 --- a/test/unit/webdriveragent-specs.js +++ b/test/unit/webdriveragent-specs.js @@ -1,16 +1,10 @@ import { BOOTSTRAP_PATH } from '../../lib/utils'; import { WebDriverAgent } from '../../lib/webdriveragent'; import * as utils from '../../lib/utils'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; import path from 'path'; import _ from 'lodash'; import sinon from 'sinon'; - -chai.should(); -chai.use(chaiAsPromised); - const fakeConstructorArgs = { device: 'some sim', platformVersion: '9', @@ -25,6 +19,16 @@ const customAgentPath = '/path/to/some/agent/WebDriverAgent.xcodeproj'; const customDerivedDataPath = '/path/to/some/agent/DerivedData/'; describe('Constructor', function () { + let chai; + + before(async function() { + chai = await import('chai'); + const chaiAsPromised = await import('chai-as-promised'); + + chai.should(); + chai.use(chaiAsPromised.default); + }); + it('should have a default wda agent if not specified', function () { let agent = new WebDriverAgent({}, fakeConstructorArgs); agent.bootstrapPath.should.eql(BOOTSTRAP_PATH); From 2b598bd5b06dd73712250febae9d81b9768adce0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 20 Jun 2024 05:53:23 +0000 Subject: [PATCH 094/368] chore(release): 8.7.4 [skip ci] ## [8.7.4](https://github.com/appium/WebDriverAgent/compare/v8.7.3...v8.7.4) (2024-06-20) ### Miscellaneous Chores * Bump chai and chai-as-promised ([#913](https://github.com/appium/WebDriverAgent/issues/913)) ([9086783](https://github.com/appium/WebDriverAgent/commit/90867832ec3077f0036938aa68a168a5702fc90a)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2170bbdbb..3b6f56b6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.4](https://github.com/appium/WebDriverAgent/compare/v8.7.3...v8.7.4) (2024-06-20) + +### Miscellaneous Chores + +* Bump chai and chai-as-promised ([#913](https://github.com/appium/WebDriverAgent/issues/913)) ([9086783](https://github.com/appium/WebDriverAgent/commit/90867832ec3077f0036938aa68a168a5702fc90a)) + ## [8.7.3](https://github.com/appium/WebDriverAgent/compare/v8.7.2...v8.7.3) (2024-06-12) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 6df348aeb..37be07184 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.3 + 8.7.4 CFBundleSignature ???? CFBundleVersion - 8.7.3 + 8.7.4 NSPrincipalClass diff --git a/package.json b/package.json index 00d29235e..98933c16f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.3", + "version": "8.7.4", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 03ea1439a9cc5b6495be60707bc474e3ae9bdb06 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 26 Jun 2024 20:31:40 +0200 Subject: [PATCH 095/368] fix: Respect wdaRemotePort capability for real devices (#915) --- lib/webdriveragent.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index c69666f4e..f5cda7ee3 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -58,7 +58,8 @@ export class WebDriverAgent { this.setWDAPaths(args.bootstrapPath, args.agentPath); this.wdaLocalPort = args.wdaLocalPort; - this.wdaRemotePort = args.wdaLocalPort || WDA_AGENT_PORT; + this.wdaRemotePort = ((this.isRealDevice ? args.wdaRemotePort : null) ?? args.wdaLocalPort) + || WDA_AGENT_PORT; this.wdaBaseUrl = args.wdaBaseUrl || WDA_BASE_URL; this.prebuildWDA = args.prebuildWDA; From d0c518ad4ac25a5b50508aeac94a1d734c7ed35a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 26 Jun 2024 18:36:18 +0000 Subject: [PATCH 096/368] chore(release): 8.7.5 [skip ci] ## [8.7.5](https://github.com/appium/WebDriverAgent/compare/v8.7.4...v8.7.5) (2024-06-26) ### Bug Fixes * Respect wdaRemotePort capability for real devices ([#915](https://github.com/appium/WebDriverAgent/issues/915)) ([03ea143](https://github.com/appium/WebDriverAgent/commit/03ea1439a9cc5b6495be60707bc474e3ae9bdb06)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b6f56b6d..9c5e5d3c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.5](https://github.com/appium/WebDriverAgent/compare/v8.7.4...v8.7.5) (2024-06-26) + +### Bug Fixes + +* Respect wdaRemotePort capability for real devices ([#915](https://github.com/appium/WebDriverAgent/issues/915)) ([03ea143](https://github.com/appium/WebDriverAgent/commit/03ea1439a9cc5b6495be60707bc474e3ae9bdb06)) + ## [8.7.4](https://github.com/appium/WebDriverAgent/compare/v8.7.3...v8.7.4) (2024-06-20) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 37be07184..73830cd33 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.4 + 8.7.5 CFBundleSignature ???? CFBundleVersion - 8.7.4 + 8.7.5 NSPrincipalClass diff --git a/package.json b/package.json index 98933c16f..116d14b43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.4", + "version": "8.7.5", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 87678f260c98b3a3bc3d37017e9ef39098ccb3c4 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 2 Jul 2024 18:32:32 +0200 Subject: [PATCH 097/368] chore: Simplify xcodebuild lines monitoring (#916) --- lib/xcodebuild.js | 31 ++++++++++++++++++------------- package.json | 3 +-- tsconfig.json | 1 + 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/xcodebuild.js b/lib/xcodebuild.js index 2862cb6a0..54add615e 100644 --- a/lib/xcodebuild.js +++ b/lib/xcodebuild.js @@ -10,7 +10,6 @@ import { } from './utils'; import _ from 'lodash'; import path from 'path'; -import { EOL } from 'os'; import { WDA_RUNNER_BUNDLE_ID } from './constants'; @@ -26,6 +25,13 @@ const IGNORED_ERRORS = [ ERROR_COPYING_ATTACHMENT, 'Failed to remove screenshot at path', ]; +const IGNORED_ERRORS_PATTERN = new RegExp( + '(' + + IGNORED_ERRORS + .map((errStr) => _.escapeRegExp(errStr)) + .join('|') + + ')' +); const RUNNER_SCHEME_TV = 'WebDriverAgentRunner_tvOS'; const LIB_SCHEME_TV = 'WebDriverAgentLib_tvOS'; @@ -324,27 +330,26 @@ export class XcodeBuild { ? `Output from xcodebuild ${this.showXcodeLog ? 'will' : 'will not'} be logged` : 'Output from xcodebuild will only be logged if any errors are present there'; this.log.debug(`${logMsg}. To change this, use 'showXcodeLog' desired capability`); - xcodebuild.on('output', (stdout, stderr) => { - let out = stdout || stderr; + const onStreamLine = (/** @type {string} */ line) => { + if (this.showXcodeLog === false || IGNORED_ERRORS_PATTERN.test(line)) { + return; + } // if we have an error we want to output the logs // otherwise the failure is inscrutible // but do not log permission errors from trying to write to attachments folder - const ignoreError = IGNORED_ERRORS.some((x) => out.includes(x)); - if (this.showXcodeLog !== false && out.includes('Error Domain=') && !ignoreError) { + if (line.includes('Error Domain=')) { logXcodeOutput = 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 - if (logXcodeOutput && !ignoreError) { - for (const line of out.split(EOL)) { - xcodeLog.error(line); - } + if (logXcodeOutput) { + xcodeLog.info(line); } - }); + }; + for (const streamName of ['stderr', 'stdout']) { + xcodebuild.on(`line-${streamName}`, onStreamLine); + } return xcodebuild; } diff --git a/package.json b/package.json index 116d14b43..9883bc788 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ }, "homepage": "https://github.com/appium/WebDriverAgent#readme", "devDependencies": { - "@appium/eslint-config-appium": "^8.0.4", "@appium/eslint-config-appium-ts": "^0.x", "@appium/test-support": "^3.0.0", "@appium/tsconfig": "^0.x", @@ -86,7 +85,7 @@ "bluebird": "^3.5.5", "lodash": "^4.17.11", "source-map-support": "^0.x", - "teen_process": "^2.0.0" + "teen_process": "^2.2.0" }, "files": [ "index.ts", diff --git a/tsconfig.json b/tsconfig.json index 678d20ad0..e7becfe3b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ "extends": "@appium/tsconfig/tsconfig.json", "compilerOptions": { "strict": false, // TODO: make this flag true + "esModuleInterop": true, "outDir": "build", "types": ["node"], "checkJs": true From 2a1a4e78f51de11a8cb4197dfbaa075b8d035705 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 2 Jul 2024 16:39:34 +0000 Subject: [PATCH 098/368] chore(release): 8.7.6 [skip ci] ## [8.7.6](https://github.com/appium/WebDriverAgent/compare/v8.7.5...v8.7.6) (2024-07-02) ### Miscellaneous Chores * Simplify xcodebuild lines monitoring ([#916](https://github.com/appium/WebDriverAgent/issues/916)) ([87678f2](https://github.com/appium/WebDriverAgent/commit/87678f260c98b3a3bc3d37017e9ef39098ccb3c4)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c5e5d3c6..0d88f6f03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.6](https://github.com/appium/WebDriverAgent/compare/v8.7.5...v8.7.6) (2024-07-02) + +### Miscellaneous Chores + +* Simplify xcodebuild lines monitoring ([#916](https://github.com/appium/WebDriverAgent/issues/916)) ([87678f2](https://github.com/appium/WebDriverAgent/commit/87678f260c98b3a3bc3d37017e9ef39098ccb3c4)) + ## [8.7.5](https://github.com/appium/WebDriverAgent/compare/v8.7.4...v8.7.5) (2024-06-26) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 73830cd33..d2bd731c0 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.5 + 8.7.6 CFBundleSignature ???? CFBundleVersion - 8.7.5 + 8.7.6 NSPrincipalClass diff --git a/package.json b/package.json index 9883bc788..293626a48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.5", + "version": "8.7.6", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 29d0e5cb2a19809e1babb06e5adaa49b43c754a5 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 18 Jul 2024 07:45:08 +0200 Subject: [PATCH 099/368] fix: Pass-through modifier keys (#918) --- .../Utilities/FBW3CActionsHelpers.h | 13 +--- .../Utilities/FBW3CActionsHelpers.m | 76 ++++++++++++++----- .../Utilities/FBW3CActionsSynthesizer.m | 54 +------------ .../IntegrationTests/FBW3CTypeActionsTests.m | 8 +- 4 files changed, 69 insertions(+), 82 deletions(-) diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h b/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h index afd8249f8..3c194d4cd 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h +++ b/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h @@ -30,19 +30,14 @@ NSString *_Nullable FBRequireValue(NSDictionary *actionItem, NSE */ NSNumber *_Nullable FBOptDuration(NSDictionary *actionItem, NSNumber *_Nullable defaultValue, NSError **error); -/** - * Checks whether the given key action value is a W3C meta modifier - * @param value key action value - * @returns YES if the value is a meta modifier - */ -BOOL FBIsMetaModifier(NSString *value); - /** * Maps W3C meta modifier to XCUITest compatible-one + * See https://w3c.github.io/webdriver/#keyboard-actions * * @param value key action value - * @returns the mapped modifier value or 0 in case of failure + * @returns the mapped modifier value or the same input character + * if no mapped value could be found for it. */ -NSUInteger FBToMetaModifier(NSString *value); +NSString * FBMapIfSpecialCharacter(NSString *value); NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m b/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m index bcbf5a783..ae0270dc3 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m @@ -53,32 +53,68 @@ return durationObj; } -BOOL FBIsMetaModifier(NSString *value) +NSString *FBMapIfSpecialCharacter(NSString *value) { - unichar charCode = [value characterAtIndex:0]; - return charCode >= 0xE000 && charCode <= 0xF8FF; -} - -NSUInteger FBToMetaModifier(NSString *value) -{ - if (!FBIsMetaModifier(value)) { - return 0; + if (0 == [value length]) { + return value; } unichar charCode = [value characterAtIndex:0]; switch (charCode) { case 0xE000: - return XCUIKeyModifierNone; - case 0xE03D: - return XCUIKeyModifierCommand; - case 0xE009: - return XCUIKeyModifierControl; - case 0xE00A: - return XCUIKeyModifierOption; - case 0xE008: - return XCUIKeyModifierShift; + return @""; + case 0xE003: + return [NSString stringWithFormat:@"%C", 0x0008]; + case 0xE004: + return [NSString stringWithFormat:@"%C", 0x0009]; + case 0xE006: + return [NSString stringWithFormat:@"%C", 0x000D]; + case 0xE007: + return [NSString stringWithFormat:@"%C", 0x000A]; + case 0xE00C: + return [NSString stringWithFormat:@"%C", 0x001B]; + case 0xE00D: + case 0xE05D: + return @" "; + case 0xE017: + return [NSString stringWithFormat:@"%C", 0x007F]; + case 0xE018: + return @";"; + case 0xE019: + return @"="; + case 0xE01A: + return @"0"; + case 0xE01B: + return @"1"; + case 0xE01C: + return @"2"; + case 0xE01D: + return @"3"; + case 0xE01E: + return @"4"; + case 0xE01F: + return @"5"; + case 0xE020: + return @"6"; + case 0xE021: + return @"7"; + case 0xE022: + return @"8"; + case 0xE023: + return @"9"; + case 0xE024: + return @"*"; + case 0xE025: + return @"+"; + case 0xE026: + return @","; + case 0xE027: + return @"-"; + case 0xE028: + return @"."; + case 0xE029: + return @"/"; default: - [FBLogger logFmt:@"Skipping the unsupported meta modifier with code %@", @(charCode)]; - return 0; + return charCode >= 0xE000 && charCode <= 0xE05D ? @"" : value; } } diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m index dc5060568..09e791836 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m @@ -410,17 +410,12 @@ - (BOOL)hasDownPairInItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex { NSInteger balance = 1; - BOOL isSelfMetaModifier = FBIsMetaModifier(self.value); for (NSInteger index = currentItemIndex - 1; index >= 0; index--) { FBW3CKeyItem *item = [allItems objectAtIndex:index]; BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class]; BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class]; if (!isKeyUp && !isKeyDown) { - if (isSelfMetaModifier) { - continue; - } else { - break; - } + break; } NSString *value = [item performSelector:@selector(value)]; @@ -434,32 +429,6 @@ - (BOOL)hasDownPairInItems:(NSArray *)allItems return 0 == balance; } -- (NSUInteger)collectModifersWithItems:(NSArray *)allItems - currentItemIndex:(NSUInteger)currentItemIndex -{ - NSUInteger modifiers = 0; - for (NSUInteger index = 0; index < currentItemIndex; index++) { - FBW3CKeyItem *item = [allItems objectAtIndex:index]; - BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class]; - BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class]; - if (!isKeyUp && !isKeyDown) { - continue; - } - - NSString *value = [item performSelector:@selector(value)]; - NSUInteger modifier = FBToMetaModifier(value); - if (modifier > 0) { - if (isKeyDown) { - modifiers |= modifier; - } else if (item.offset < self.offset) { - // only cancel the modifier if it is not in the same group - modifiers &= ~modifier; - } - } - } - return modifiers; -} - - (NSString *)collectTextWithItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex { @@ -473,12 +442,8 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems } NSString *value = [item performSelector:@selector(value)]; - if (FBIsMetaModifier(value)) { - continue; - } - if (isKeyUp) { - [result addObject:value]; + [result addObject:FBMapIfSpecialCharacter(value)]; } } return [result.reverseObjectEnumerator.allObjects componentsJoinedByString:@""]; @@ -497,10 +462,6 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems return nil; } - if (FBIsMetaModifier(self.value)) { - return @[]; - } - BOOL isLastKeyUpInGroup = currentItemIndex == allItems.count - 1 || [[allItems objectAtIndex:currentItemIndex + 1] isKindOfClass:FBKeyPauseItem.class]; if (!isLastKeyUpInGroup) { @@ -510,10 +471,6 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems NSString *text = [self collectTextWithItems:allItems currentItemIndex:currentItemIndex]; NSTimeInterval offset = FBMillisToSeconds(self.offset); XCPointerEventPath *resultPath = [[XCPointerEventPath alloc] initForTextInput]; - // TODO: Figure out how meta modifiers could be applied - // TODO: The current approach throws zero division error on execution - // NSUInteger modifiers = [self collectModifersWithItems:allItems currentItemIndex:currentItemIndex]; - // [resultPath setModifiers:modifiers mergeWithCurrentModifierFlags:NO atOffset:0]; [resultPath typeText:text atOffset:offset typingSpeed:FBConfiguration.maxTypingFrequency @@ -555,17 +512,12 @@ - (BOOL)hasUpPairInItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex { NSInteger balance = 1; - BOOL isSelfMetaModifier = FBIsMetaModifier(self.value); for (NSUInteger index = currentItemIndex + 1; index < allItems.count; index++) { FBW3CKeyItem *item = [allItems objectAtIndex:index]; BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class]; BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class]; if (!isKeyUp && !isKeyDown) { - if (isSelfMetaModifier) { - continue; - } else { - break; - } + break; } NSString *value = [item performSelector:@selector(value)]; diff --git a/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m b/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m index b202eda95..4518e4034 100644 --- a/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m @@ -140,18 +140,22 @@ - (void)testTextTyping @{@"type": @"keyUp", @"value": @"N"}, @{@"type": @"keyDown", @"value": @"B"}, @{@"type": @"keyUp", @"value": @"B"}, + @{@"type": @"keyDown", @"value": @"A"}, + @{@"type": @"keyUp", @"value": @"A"}, @{@"type": @"keyDown", @"value": @"a"}, @{@"type": @"keyUp", @"value": @"a"}, + @{@"type": @"keyDown", @"value": [NSString stringWithFormat:@"%C", 0xE003]}, + @{@"type": @"keyUp", @"value": [NSString stringWithFormat:@"%C", 0xE003]}, @{@"type": @"pause", @"duration": @500}, ], }, - ]; + ]; NSError *error; XCTAssertTrue([self.testedApplication fb_performW3CActions:typeAction elementCache:nil error:&error]); XCTAssertNil(error); - XCTAssertEqualObjects(textField.wdValue, @"🏀NBa"); + XCTAssertEqualObjects(textField.wdValue, @"🏀NBA"); } @end From 89346a58e5c837d2b180a9fcb945515e5be8f89e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 Jul 2024 05:49:36 +0000 Subject: [PATCH 100/368] chore(release): 8.7.7 [skip ci] ## [8.7.7](https://github.com/appium/WebDriverAgent/compare/v8.7.6...v8.7.7) (2024-07-18) ### Bug Fixes * Pass-through modifier keys ([#918](https://github.com/appium/WebDriverAgent/issues/918)) ([29d0e5c](https://github.com/appium/WebDriverAgent/commit/29d0e5cb2a19809e1babb06e5adaa49b43c754a5)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d88f6f03..cb5d334de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.7](https://github.com/appium/WebDriverAgent/compare/v8.7.6...v8.7.7) (2024-07-18) + +### Bug Fixes + +* Pass-through modifier keys ([#918](https://github.com/appium/WebDriverAgent/issues/918)) ([29d0e5c](https://github.com/appium/WebDriverAgent/commit/29d0e5cb2a19809e1babb06e5adaa49b43c754a5)) + ## [8.7.6](https://github.com/appium/WebDriverAgent/compare/v8.7.5...v8.7.6) (2024-07-02) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index d2bd731c0..cc811a107 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.6 + 8.7.7 CFBundleSignature ???? CFBundleVersion - 8.7.6 + 8.7.7 NSPrincipalClass diff --git a/package.json b/package.json index 293626a48..56cd32921 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.6", + "version": "8.7.7", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 9e70ec1dbec1d1844278a58297a5b956ebaeb7fc Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 18 Jul 2024 00:10:49 -0700 Subject: [PATCH 101/368] fix: do nothing for an empty array in w3c actions (#919) * fix: do nothing for an empty array actions * Update FBW3CActionsSynthesizer.m * test: add test --- .../Utilities/FBW3CActionsSynthesizer.m | 29 +++++++++---------- .../IntegrationTests/FBW3CTypeActionsTests.m | 24 +++++++++++++++ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m index 09e791836..2b0eff897 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m @@ -692,14 +692,6 @@ @implementation FBW3CActionsSynthesizer }); NSArray *> *actionItems = [actionDescription objectForKey:FB_KEY_ACTIONS]; - if (nil == actionItems || 0 == actionItems.count) { - NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one item defined for each action. Action with id '%@' contains none", actionId]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - FBW3CKeyItemsChain *chain = [[FBW3CKeyItemsChain alloc] init]; NSArray *> *processedItems = [self preprocessedActionItemsWith:actionItems]; for (NSDictionary *actionItem in processedItems) { @@ -770,14 +762,6 @@ @implementation FBW3CActionsSynthesizer } NSArray *> *actionItems = [actionDescription objectForKey:FB_KEY_ACTIONS]; - if (nil == actionItems || 0 == actionItems.count) { - NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one gesture item defined for each action. Action with id '%@' contains none", actionId]; - if (error) { - *error = [[FBErrorBuilder.builder withDescription:description] build]; - } - return nil; - } - FBW3CGestureItemsChain *chain = [[FBW3CGestureItemsChain alloc] init]; NSArray *> *processedItems = [self preprocessedActionItemsWith:actionItems]; for (NSDictionary *actionItem in processedItems) { @@ -852,7 +836,20 @@ - (nullable XCSynthesizedEventRecord *)synthesizeWithError:(NSError **)error *error = [[FBErrorBuilder.builder withDescription:description] build]; } return nil; + } + NSArray *> *actionItems = [action objectForKey:FB_KEY_ACTIONS]; + if (nil == actionItems) { + NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one item defined for each action. Action with id '%@' contains none", actionId]; + if (error) { + *error = [[FBErrorBuilder.builder withDescription:description] build]; + } + return nil; + } + if (0 == actionItems.count) { + [FBLogger logFmt:@"Action items in the action id '%@' had an empty array. Skipping the action.", actionId]; + continue; } + [actionIds addObject:actionId]; [actionsMapping setObject:action forKey:actionId]; } diff --git a/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m b/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m index 4518e4034..893271e31 100644 --- a/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBW3CTypeActionsTests.m @@ -158,4 +158,28 @@ - (void)testTextTyping XCTAssertEqualObjects(textField.wdValue, @"🏀NBA"); } +- (void)testTextTypingWithEmptyActions +{ + if (![XCPointerEvent.class fb_areKeyEventsSupported]) { + return; + } + + XCUIElement *textField = self.testedApplication.textFields[@"aIdentifier"]; + [textField tap]; + NSArray *> *typeAction = + @[ + @{ + @"type": @"pointer", + @"id": @"touch", + @"actions": @[], + }, + ]; + NSError *error; + XCTAssertTrue([self.testedApplication fb_performW3CActions:typeAction + elementCache:nil + error:&error]); + XCTAssertNil(error); + XCTAssertEqualObjects(textField.value, @""); +} + @end From c61fa88d5307a90a2fb851d6eda19c3832be3a41 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 Jul 2024 07:15:59 +0000 Subject: [PATCH 102/368] chore(release): 8.7.8 [skip ci] ## [8.7.8](https://github.com/appium/WebDriverAgent/compare/v8.7.7...v8.7.8) (2024-07-18) ### Bug Fixes * do nothing for an empty array in w3c actions ([#919](https://github.com/appium/WebDriverAgent/issues/919)) ([9e70ec1](https://github.com/appium/WebDriverAgent/commit/9e70ec1dbec1d1844278a58297a5b956ebaeb7fc)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb5d334de..10f5d0828 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.8](https://github.com/appium/WebDriverAgent/compare/v8.7.7...v8.7.8) (2024-07-18) + +### Bug Fixes + +* do nothing for an empty array in w3c actions ([#919](https://github.com/appium/WebDriverAgent/issues/919)) ([9e70ec1](https://github.com/appium/WebDriverAgent/commit/9e70ec1dbec1d1844278a58297a5b956ebaeb7fc)) + ## [8.7.7](https://github.com/appium/WebDriverAgent/compare/v8.7.6...v8.7.7) (2024-07-18) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index cc811a107..fc6a056b0 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.7 + 8.7.8 CFBundleSignature ???? CFBundleVersion - 8.7.7 + 8.7.8 NSPrincipalClass diff --git a/package.json b/package.json index 56cd32921..491bbc268 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.7", + "version": "8.7.8", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From d2302a3e07c2c20bce7af07b727017a504a1f454 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 18 Jul 2024 01:17:05 -0700 Subject: [PATCH 103/368] ci: tune test cases associated with w3c actions (#920) * ci: combine two tests to reduce test case * test: remove no longer necessary error case * extract empty test case * Revert "ci: combine two tests to reduce test case" This reverts commit d3fd51cacde53196a17a45f493372576d7bf983d. --- .../FBW3CTouchActionsIntegrationTests.m | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m index 598cc66c9..ccb996aa3 100644 --- a/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m @@ -70,15 +70,6 @@ - (void)testErroneousGestures }, ], - // Chain element with empty 'actions' - @[@{ - @"type": @"pointer", - @"id": @"finger1", - @"parameters": @{@"pointerType": @"touch"}, - @"actions": @[], - }, - ], - // Chain element without type @[@{ @"id": @"finger1", @@ -276,6 +267,21 @@ - (void)testErroneousGestures } } +- (void)testNothingDoesWithoutError +{ + NSArray *> *gesture = + @[@{ + @"type": @"pointer", + @"id": @"finger1", + @"parameters": @{@"pointerType": @"touch"}, + @"actions": @[], + }, + ]; + NSError *error; + XCTAssertTrue([self.testedApplication fb_performW3CActions:gesture elementCache:nil error:&error]); + XCTAssertNil(error); +} + - (void)testTap { NSArray *> *gesture = From 2f90739340d70073b48c703b36b9a313d3618972 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 20 Jul 2024 18:08:44 -0700 Subject: [PATCH 104/368] chore: keep error handling for the future possible usage (#921) --- .../Utilities/FBW3CActionsSynthesizer.m | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m index 2b0eff897..c488ca4ac 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m @@ -692,6 +692,14 @@ @implementation FBW3CActionsSynthesizer }); NSArray *> *actionItems = [actionDescription objectForKey:FB_KEY_ACTIONS]; + if (nil == actionItems || 0 == actionItems.count) { + NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one item defined for each action. Action with id '%@' contains none", actionId]; + if (error) { + *error = [[FBErrorBuilder.builder withDescription:description] build]; + } + return nil; + } + FBW3CKeyItemsChain *chain = [[FBW3CKeyItemsChain alloc] init]; NSArray *> *processedItems = [self preprocessedActionItemsWith:actionItems]; for (NSDictionary *actionItem in processedItems) { @@ -762,6 +770,14 @@ @implementation FBW3CActionsSynthesizer } NSArray *> *actionItems = [actionDescription objectForKey:FB_KEY_ACTIONS]; + if (nil == actionItems || 0 == actionItems.count) { + NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one gesture item defined for each action. Action with id '%@' contains none", actionId]; + if (error) { + *error = [[FBErrorBuilder.builder withDescription:description] build]; + } + return nil; + } + FBW3CGestureItemsChain *chain = [[FBW3CGestureItemsChain alloc] init]; NSArray *> *processedItems = [self preprocessedActionItemsWith:actionItems]; for (NSDictionary *actionItem in processedItems) { From 4d11ed55b3c18e0a78637b0e0b3c3b0193e0d1a7 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 21 Jul 2024 01:13:04 +0000 Subject: [PATCH 105/368] chore(release): 8.7.9 [skip ci] ## [8.7.9](https://github.com/appium/WebDriverAgent/compare/v8.7.8...v8.7.9) (2024-07-21) ### Miscellaneous Chores * keep error handling for the future possible usage ([#921](https://github.com/appium/WebDriverAgent/issues/921)) ([2f90739](https://github.com/appium/WebDriverAgent/commit/2f90739340d70073b48c703b36b9a313d3618972)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10f5d0828..7e98a234a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.9](https://github.com/appium/WebDriverAgent/compare/v8.7.8...v8.7.9) (2024-07-21) + +### Miscellaneous Chores + +* keep error handling for the future possible usage ([#921](https://github.com/appium/WebDriverAgent/issues/921)) ([2f90739](https://github.com/appium/WebDriverAgent/commit/2f90739340d70073b48c703b36b9a313d3618972)) + ## [8.7.8](https://github.com/appium/WebDriverAgent/compare/v8.7.7...v8.7.8) (2024-07-18) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index fc6a056b0..c70df9182 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.8 + 8.7.9 CFBundleSignature ???? CFBundleVersion - 8.7.8 + 8.7.9 NSPrincipalClass diff --git a/package.json b/package.json index 491bbc268..91ffaed38 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.8", + "version": "8.7.9", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 1699023086a243c3d86ddae4da8342c6beda3f48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 17:22:12 +0200 Subject: [PATCH 106/368] chore(deps-dev): bump @types/node from 20.14.13 to 22.0.0 (#926) Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.14.13 to 22.0.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" 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 91ffaed38..2d010281a 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "@types/bluebird": "^3.5.38", "@types/lodash": "^4.14.196", "@types/mocha": "^10.0.1", - "@types/node": "^20.4.7", + "@types/node": "^22.0.0", "@types/teen_process": "^2.0.1", "appium-xcode": "^5.0.0", "chai": "^5.1.1", From 549702f034a1ff5d76f94de523ea2a15239d983a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 29 Jul 2024 15:27:22 +0000 Subject: [PATCH 107/368] chore(release): 8.7.10 [skip ci] ## [8.7.10](https://github.com/appium/WebDriverAgent/compare/v8.7.9...v8.7.10) (2024-07-29) ### Miscellaneous Chores * **deps-dev:** bump @types/node from 20.14.13 to 22.0.0 ([#926](https://github.com/appium/WebDriverAgent/issues/926)) ([1699023](https://github.com/appium/WebDriverAgent/commit/1699023086a243c3d86ddae4da8342c6beda3f48)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e98a234a..ec840893a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.10](https://github.com/appium/WebDriverAgent/compare/v8.7.9...v8.7.10) (2024-07-29) + +### Miscellaneous Chores + +* **deps-dev:** bump @types/node from 20.14.13 to 22.0.0 ([#926](https://github.com/appium/WebDriverAgent/issues/926)) ([1699023](https://github.com/appium/WebDriverAgent/commit/1699023086a243c3d86ddae4da8342c6beda3f48)) + ## [8.7.9](https://github.com/appium/WebDriverAgent/compare/v8.7.8...v8.7.9) (2024-07-21) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index c70df9182..6a9cecf8d 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.9 + 8.7.10 CFBundleSignature ???? CFBundleVersion - 8.7.9 + 8.7.10 NSPrincipalClass diff --git a/package.json b/package.json index 2d010281a..42efa02af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.9", + "version": "8.7.10", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 42c519f9df7beec81175fd38af388975d6f6b800 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 29 Jul 2024 18:40:58 +0200 Subject: [PATCH 108/368] fix: Respond to /health with a proper HTML (#925) --- WebDriverAgentLib/Routing/FBWebServer.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Routing/FBWebServer.m b/WebDriverAgentLib/Routing/FBWebServer.m index 7e991e0e2..ff9e4c424 100644 --- a/WebDriverAgentLib/Routing/FBWebServer.m +++ b/WebDriverAgentLib/Routing/FBWebServer.m @@ -217,7 +217,7 @@ - (void)handleException:(NSException *)exception forResponse:(RouteResponse *)re - (void)registerServerKeyRouteHandlers { [self.server get:@"/health" withBlock:^(RouteRequest *request, RouteResponse *response) { - [response respondWithString:@"I-AM-ALIVE"]; + [response respondWithString:@"Health Check

I-AM-ALIVE

"]; }]; NSString *calibrationPage = @"" From 928965d378c38f116fe562fcd3a4e728ef1354e5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 29 Jul 2024 16:45:07 +0000 Subject: [PATCH 109/368] chore(release): 8.7.11 [skip ci] ## [8.7.11](https://github.com/appium/WebDriverAgent/compare/v8.7.10...v8.7.11) (2024-07-29) ### Bug Fixes * Respond to /health with a proper HTML ([#925](https://github.com/appium/WebDriverAgent/issues/925)) ([42c519f](https://github.com/appium/WebDriverAgent/commit/42c519f9df7beec81175fd38af388975d6f6b800)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec840893a..d5a337607 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.11](https://github.com/appium/WebDriverAgent/compare/v8.7.10...v8.7.11) (2024-07-29) + +### Bug Fixes + +* Respond to /health with a proper HTML ([#925](https://github.com/appium/WebDriverAgent/issues/925)) ([42c519f](https://github.com/appium/WebDriverAgent/commit/42c519f9df7beec81175fd38af388975d6f6b800)) + ## [8.7.10](https://github.com/appium/WebDriverAgent/compare/v8.7.9...v8.7.10) (2024-07-29) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 6a9cecf8d..baf7f8c50 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.10 + 8.7.11 CFBundleSignature ???? CFBundleVersion - 8.7.10 + 8.7.11 NSPrincipalClass diff --git a/package.json b/package.json index 42efa02af..ce1e466b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.10", + "version": "8.7.11", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 5d2ec249488655451e2d46384e560fee7e08e840 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 2 Aug 2024 11:54:51 +0200 Subject: [PATCH 110/368] chore: Replace fancy-log dependency with appium logger (#928) --- Scripts/update-wda-version.js | 5 +++-- package.json | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Scripts/update-wda-version.js b/Scripts/update-wda-version.js index 37102345a..142efdce3 100644 --- a/Scripts/update-wda-version.js +++ b/Scripts/update-wda-version.js @@ -1,7 +1,8 @@ -const {plist} = require('@appium/support'); +const {plist, logger} = require('@appium/support'); const path = require('node:path'); const semver = require('semver'); -const log = require('fancy-log'); + +const log = logger.getLogger('Versioner'); /** * @param {string} argName diff --git a/package.json b/package.json index ce1e466b3..81cf2ff04 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "chai": "^5.1.1", "chai-as-promised": "^8.0.0", "conventional-changelog-conventionalcommits": "^8.0.0", - "fancy-log": "^2.0.0", "node-simctl": "^7.0.1", "mocha": "^10.0.0", "prettier": "^3.0.0", From 3c8497be55ddad0524cfb02c6db94a9c24e5076a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 2 Aug 2024 10:00:03 +0000 Subject: [PATCH 111/368] chore(release): 8.7.12 [skip ci] ## [8.7.12](https://github.com/appium/WebDriverAgent/compare/v8.7.11...v8.7.12) (2024-08-02) ### Miscellaneous Chores * Replace fancy-log dependency with appium logger ([#928](https://github.com/appium/WebDriverAgent/issues/928)) ([5d2ec24](https://github.com/appium/WebDriverAgent/commit/5d2ec249488655451e2d46384e560fee7e08e840)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5a337607..efa7fadda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.7.12](https://github.com/appium/WebDriverAgent/compare/v8.7.11...v8.7.12) (2024-08-02) + +### Miscellaneous Chores + +* Replace fancy-log dependency with appium logger ([#928](https://github.com/appium/WebDriverAgent/issues/928)) ([5d2ec24](https://github.com/appium/WebDriverAgent/commit/5d2ec249488655451e2d46384e560fee7e08e840)) + ## [8.7.11](https://github.com/appium/WebDriverAgent/compare/v8.7.10...v8.7.11) (2024-07-29) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index baf7f8c50..7e08ded2a 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.11 + 8.7.12 CFBundleSignature ???? CFBundleVersion - 8.7.11 + 8.7.12 NSPrincipalClass diff --git a/package.json b/package.json index 81cf2ff04..50b99f867 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.11", + "version": "8.7.12", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 97cf91de34dc53e5f75f91829dc43224101c1b45 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Tue, 6 Aug 2024 08:31:20 +0200 Subject: [PATCH 112/368] feat: Open the default URL in Safari upon session startup (#929) --- .github/workflows/functional-test.yml | 26 ++++++++++--------- WebDriverAgent.xcodeproj/project.pbxproj | 12 +++++++++ .../Commands/FBSessionCommands.m | 13 ++++++++++ WebDriverAgentLib/Routing/FBSession.h | 3 +++ WebDriverAgentLib/Routing/FBSession.m | 2 ++ WebDriverAgentLib/Routing/FBWebServer.m | 3 +++ .../Utilities/FBWebServerParams.h | 23 ++++++++++++++++ .../Utilities/FBWebServerParams.m | 24 +++++++++++++++++ .../IntegrationTests/FBSafariAlertTests.m | 6 ++--- test/functional/webdriveragent-e2e-specs.js | 11 +++++++- 10 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 WebDriverAgentLib/Utilities/FBWebServerParams.h create mode 100644 WebDriverAgentLib/Utilities/FBWebServerParams.m diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index 90bacdc9a..e9bb01e19 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -12,11 +12,11 @@ jobs: fail-fast: false matrix: test_targets: - - XCODE_VERSION: 15.3 - IOS_VERSION: 17.4 + - XCODE_VERSION: '15.3' + IOS_VERSION: '17.4' IOS_MODEL: iPhone 15 Plus - XCODE_VERSION: 14.3.1 - IOS_VERSION: 16.4 + IOS_VERSION: '16.4' IOS_MODEL: iPhone 14 Plus # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md @@ -34,20 +34,22 @@ jobs: mkdir -p ./Resources/WebDriverAgent.bundle name: Install dev dependencies - - uses: futureware-tech/simulator-action@v3 - with: - model: ${{matrix.test_targets.IOS_MODEL}} - os: iOS - os_version: ${{matrix.test_targets.IOS_VERSION}} - erase_before_boot: true - # to prevent unexpected shutdown failure error - shutdown_after_job: false - name: Preboot Simulator + - name: Prepare iOS simulator + env: + DEVICE_NAME: ${{matrix.test_targets.IOS_MODEL}} + PLATFORM_VERSION: ${{matrix.test_targets.IOS_VERSION}} + run: | + open -Fn "$(xcode-select -p)/Applications/Simulator.app" + udid=$(xcrun simctl list devices available -j | \ + node -p "Object.entries(JSON.parse(fs.readFileSync(0)).devices).filter((x) => x[0].includes('$PLATFORM_VERSION'.replace('.', '-'))).reduce((acc, x) => [...acc, ...x[1]], []).find(({name}) => name === '$DEVICE_NAME').udid") + xcrun simctl bootstatus $udid -b + xcrun simctl shutdown $udid - run: npm run e2e-test name: Run functional tests env: CI: true _FORCE_LOGS: 1 + _LOG_TIMESTAMP: 1 DEVICE_NAME: ${{matrix.test_targets.IOS_MODEL}} PLATFORM_VERSION: ${{matrix.test_targets.IOS_VERSION}} diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index db4465848..055b0c6b8 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -421,6 +421,10 @@ 7182276E258744C900661B83 /* HTTPErrorResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = E444DC59249131880060D7EB /* HTTPErrorResponse.h */; }; 71822777258744CE00661B83 /* DDNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = E444DC7D249131B00060D7EB /* DDNumber.h */; }; 71822780258744D000661B83 /* DDRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E444DC7B249131B00060D7EB /* DDRange.h */; }; + 718D2C122C60BAE3000788F2 /* FBWebServerParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 718D2C112C60BAE3000788F2 /* FBWebServerParams.m */; }; + 718D2C132C60BAE3000788F2 /* FBWebServerParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 718D2C102C60BAE3000788F2 /* FBWebServerParams.h */; }; + 718D2C142C60BAE3000788F2 /* FBWebServerParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 718D2C102C60BAE3000788F2 /* FBWebServerParams.h */; }; + 718D2C152C60BAE3000788F2 /* FBWebServerParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 718D2C112C60BAE3000788F2 /* FBWebServerParams.m */; }; 718F49C8230844330045FE8B /* FBProtocolHelpersTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 718F49C7230844330045FE8B /* FBProtocolHelpersTests.m */; }; 718F49C923087ACF0045FE8B /* FBProtocolHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155DD23080CA600646AFB /* FBProtocolHelpers.h */; }; 718F49CA23087AD30045FE8B /* FBProtocolHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B155DE23080CA600646AFB /* FBProtocolHelpers.m */; }; @@ -1027,6 +1031,8 @@ 718226C72587443600661B83 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GCDAsyncSocket.h; path = WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h; sourceTree = SOURCE_ROOT; }; 718226C82587443600661B83 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GCDAsyncSocket.m; path = WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m; sourceTree = SOURCE_ROOT; }; 718226C92587443600661B83 /* GCDAsyncUdpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GCDAsyncUdpSocket.m; path = WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.m; sourceTree = SOURCE_ROOT; }; + 718D2C102C60BAE3000788F2 /* FBWebServerParams.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBWebServerParams.h; sourceTree = ""; }; + 718D2C112C60BAE3000788F2 /* FBWebServerParams.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBWebServerParams.m; sourceTree = ""; }; 718F49C7230844330045FE8B /* FBProtocolHelpersTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBProtocolHelpersTests.m; sourceTree = ""; }; 71930C4020662E1F00D3AFEC /* FBPasteboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBPasteboard.h; sourceTree = ""; }; 71930C4120662E1F00D3AFEC /* FBPasteboard.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBPasteboard.m; sourceTree = ""; }; @@ -1948,6 +1954,8 @@ 7140974A1FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.m */, 713AE573243A53BE0000D657 /* FBW3CActionsHelpers.h */, 713AE574243A53BE0000D657 /* FBW3CActionsHelpers.m */, + 718D2C102C60BAE3000788F2 /* FBWebServerParams.h */, + 718D2C112C60BAE3000788F2 /* FBWebServerParams.m */, 7157B28F221DADD2001C348C /* FBXCAXClientProxy.h */, 7157B290221DADD2001C348C /* FBXCAXClientProxy.m */, EE5A24401F136C8D0078B1D9 /* FBXCodeCompatibility.h */, @@ -2463,6 +2471,7 @@ 641EE6D62240C5CA00173FCB /* FBLogger.h in Headers */, 71BB58F72B96531900CB9BFE /* FBScreenRecordingContainer.h in Headers */, 641EE6D72240C5CA00173FCB /* XCTestObserver.h in Headers */, + 718D2C142C60BAE3000788F2 /* FBWebServerParams.h in Headers */, 641EE6D82240C5CA00173FCB /* XCUIElement.h in Headers */, 641EE6D92240C5CA00173FCB /* XCKeyboardInputSolver.h in Headers */, 718226CB2587443700661B83 /* GCDAsyncUdpSocket.h in Headers */, @@ -2718,6 +2727,7 @@ EE35AD311E3B77D600A02D78 /* XCKeyboardLayout.h in Headers */, 716C9DFA27315D21005AD475 /* FBReflectionUtils.h in Headers */, E444DCB624913C220060D7EB /* RouteRequest.h in Headers */, + 718D2C132C60BAE3000788F2 /* FBWebServerParams.h in Headers */, 71F5BE23252E576C00EE9EBA /* XCUIElement+FBSwiping.h in Headers */, 718226CC2587443700661B83 /* GCDAsyncSocket.h in Headers */, EE35AD3B1E3B77D600A02D78 /* XCTAsyncActivity-Protocol.h in Headers */, @@ -3093,6 +3103,7 @@ 641EE5D72240C5CA00173FCB /* FBScreenshotCommands.m in Sources */, 71F3E7D725417FF400E0C22B /* FBSettings.m in Sources */, 641EE5D92240C5CA00173FCB /* XCUIElement+FBPickerWheel.m in Sources */, + 718D2C152C60BAE3000788F2 /* FBWebServerParams.m in Sources */, 641EE5DA2240C5CA00173FCB /* XCUIApplicationProcessDelay.m in Sources */, 641EE5DB2240C5CA00173FCB /* FBXPath.m in Sources */, 71C8E55425399A6B008572C1 /* XCUIApplication+FBQuiescence.m in Sources */, @@ -3282,6 +3293,7 @@ AD76723E1D6B7CC000610457 /* XCUIElement+FBTyping.m in Sources */, EE158AAF1CBD456F00A3E3F0 /* XCUIElement+FBAccessibility.m in Sources */, 714E14BA29805CAE00375DD7 /* XCAXClient_iOS+FBSnapshotReqParams.m in Sources */, + 718D2C122C60BAE3000788F2 /* FBWebServerParams.m in Sources */, 7150348821A6DAD600A0F4BA /* FBImageUtils.m in Sources */, E444DCAB24913C220060D7EB /* HTTPResponseProxy.m in Sources */, E444DC6D249131890060D7EB /* HTTPErrorResponse.m in Sources */, diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 7b3c4dbb5..97baab7a1 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -20,6 +20,7 @@ #import "FBRuntimeUtils.h" #import "FBActiveAppDetectionPoint.h" #import "FBXCodeCompatibility.h" +#import "FBWebServerParams.h" #import "XCUIApplication+FBHelpers.h" #import "XCUIApplication+FBQuiescence.h" #import "XCUIDevice.h" @@ -176,6 +177,18 @@ + (NSArray *)routes _XCTSetApplicationStateTimeout(defaultTimeout); } } + if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"17.0") && [bundleID isEqualToString:FB_SAFARI_BUNDLE_ID]) { + // Opening the default URL in Safari instead of an empty page helps + // the remote debugger to avoid issues while looking for active web views + FBWebServerParams *wsParams = FBWebServerParams.sharedInstance; + NSString *healthEndpoint = [NSString stringWithFormat:@"http://127.0.0.1:%@/health", wsParams.port]; + id errorResponse = [self openDeepLink:healthEndpoint + withApplication:bundleID + timeout:capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]]; + if (nil != errorResponse) { + NSLog(@"Was not able to open the default URL %@ in Safari", healthEndpoint); + } + } } if (!app.running) { NSString *errorMsg = [NSString stringWithFormat:@"Cannot launch %@ application. Make sure the correct bundle identifier has been provided in capabilities and check the device log for possible crash report occurrences", bundleID]; diff --git a/WebDriverAgentLib/Routing/FBSession.h b/WebDriverAgentLib/Routing/FBSession.h index 9b73d4d16..b617ae096 100644 --- a/WebDriverAgentLib/Routing/FBSession.h +++ b/WebDriverAgentLib/Routing/FBSession.h @@ -14,6 +14,9 @@ NS_ASSUME_NONNULL_BEGIN +/** Bundle identifier of Mobile Safari browser */ +extern NSString* const FB_SAFARI_BUNDLE_ID; + /** Class that represents testing session */ diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index 2b1753cd2..14565ad00 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -33,6 +33,8 @@ */ NSString *const FBDefaultApplicationAuto = @"auto"; +NSString *const FB_SAFARI_BUNDLE_ID = @"com.apple.mobilesafari"; + @interface FBSession () @property (nullable, nonatomic) XCUIApplication *testedApplication; @property (nonatomic) BOOL isTestedApplicationExpectedToRun; diff --git a/WebDriverAgentLib/Routing/FBWebServer.m b/WebDriverAgentLib/Routing/FBWebServer.m index ff9e4c424..8d9c30203 100644 --- a/WebDriverAgentLib/Routing/FBWebServer.m +++ b/WebDriverAgentLib/Routing/FBWebServer.m @@ -23,6 +23,7 @@ #import "FBUnknownCommands.h" #import "FBConfiguration.h" #import "FBLogger.h" +#import "FBWebServerParams.h" #import "XCUIDevice+FBHelpers.h" @@ -102,6 +103,8 @@ - (void)startHTTPServer serverStarted = [self attemptToStartServer:self.server onPort:port withError:&error]; if (serverStarted) { + FBWebServerParams* wsParams = FBWebServerParams.sharedInstance; + wsParams.port = @(self.server.port); break; } diff --git a/WebDriverAgentLib/Utilities/FBWebServerParams.h b/WebDriverAgentLib/Utilities/FBWebServerParams.h new file mode 100644 index 000000000..c92daecb2 --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBWebServerParams.h @@ -0,0 +1,23 @@ +/** + * 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 FBWebServerParams : NSObject + +/** The local port number WDA server is running on */ +@property (nonatomic, nullable) NSNumber *port; + ++ (id)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBWebServerParams.m b/WebDriverAgentLib/Utilities/FBWebServerParams.m new file mode 100644 index 000000000..65e85f65a --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBWebServerParams.m @@ -0,0 +1,24 @@ +/** + * 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 "FBWebServerParams.h" + +@implementation FBWebServerParams + ++ (instancetype)sharedInstance +{ + static FBWebServerParams *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +@end diff --git a/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m b/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m index 73e2de337..5b49b35d9 100644 --- a/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBSafariAlertTests.m @@ -25,15 +25,13 @@ @interface FBSafariAlertIntegrationTests : FBIntegrationTestCase @end -static NSString *const SAFARI_BUNDLE_ID = @"com.apple.mobilesafari"; - @implementation FBSafariAlertIntegrationTests - (void)setUp { [super setUp]; self.session = [FBSession initWithApplication:XCUIApplication.fb_activeApplication]; - [self.session launchApplicationWithBundleId:SAFARI_BUNDLE_ID + [self.session launchApplicationWithBundleId:FB_SAFARI_BUNDLE_ID shouldWaitForQuiescence:nil arguments:nil environment:nil]; @@ -42,7 +40,7 @@ - (void)setUp - (void)tearDown { - [self.session terminateApplicationWithBundleId:SAFARI_BUNDLE_ID]; + [self.session terminateApplicationWithBundleId:FB_SAFARI_BUNDLE_ID]; } - (void)disabled_testCanHandleSafariInputPrompt diff --git a/test/functional/webdriveragent-e2e-specs.js b/test/functional/webdriveragent-e2e-specs.js index 1a1a4324f..3cf2862f1 100644 --- a/test/functional/webdriveragent-e2e-specs.js +++ b/test/functional/webdriveragent-e2e-specs.js @@ -8,7 +8,7 @@ import { retryInterval } from 'asyncbox'; import { WebDriverAgent } from '../../lib/webdriveragent'; import axios from 'axios'; -const MOCHA_TIMEOUT_MS = 60 * 1000 * 4; +const MOCHA_TIMEOUT_MS = 60 * 1000 * 5; const SIM_DEVICE_NAME = 'webDriverAgentTest'; const SIM_STARTUP_TIMEOUT_MS = MOCHA_TIMEOUT_MS; @@ -59,6 +59,15 @@ describe('WebDriverAgent', function () { PLATFORM_VERSION ); device = await getSimulator(simctl.udid); + + // Prebuild WDA + const wda = new WebDriverAgent(xcodeVersion, { + iosSdkVersion: PLATFORM_VERSION, + platformVersion: PLATFORM_VERSION, + showXcodeLog: true, + device, + }); + await wda.xcodebuild.start(true); }); after(async function () { From 71a697ca6bf2c1d735a63d79ff995b46a2b218cc Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 6 Aug 2024 06:36:47 +0000 Subject: [PATCH 113/368] chore(release): 8.8.0 [skip ci] ## [8.8.0](https://github.com/appium/WebDriverAgent/compare/v8.7.12...v8.8.0) (2024-08-06) ### Features * Open the default URL in Safari upon session startup ([#929](https://github.com/appium/WebDriverAgent/issues/929)) ([97cf91d](https://github.com/appium/WebDriverAgent/commit/97cf91de34dc53e5f75f91829dc43224101c1b45)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efa7fadda..aa45b3118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.8.0](https://github.com/appium/WebDriverAgent/compare/v8.7.12...v8.8.0) (2024-08-06) + +### Features + +* Open the default URL in Safari upon session startup ([#929](https://github.com/appium/WebDriverAgent/issues/929)) ([97cf91d](https://github.com/appium/WebDriverAgent/commit/97cf91de34dc53e5f75f91829dc43224101c1b45)) + ## [8.7.12](https://github.com/appium/WebDriverAgent/compare/v8.7.11...v8.7.12) (2024-08-02) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 7e08ded2a..da4fdff27 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.7.12 + 8.8.0 CFBundleSignature ???? CFBundleVersion - 8.7.12 + 8.8.0 NSPrincipalClass diff --git a/package.json b/package.json index 50b99f867..9a25258f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.7.12", + "version": "8.8.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 7c5114518509c9a399845283eca7708248fb838f Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 7 Aug 2024 13:48:22 +0200 Subject: [PATCH 114/368] fix: Revert the logic to open the default URL in Safari via deeplink (#932) --- WebDriverAgent.xcodeproj/project.pbxproj | 12 ------------ WebDriverAgentLib/Commands/FBSessionCommands.m | 13 ------------- WebDriverAgentLib/Routing/FBWebServer.m | 3 --- 3 files changed, 28 deletions(-) diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index 055b0c6b8..db4465848 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -421,10 +421,6 @@ 7182276E258744C900661B83 /* HTTPErrorResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = E444DC59249131880060D7EB /* HTTPErrorResponse.h */; }; 71822777258744CE00661B83 /* DDNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = E444DC7D249131B00060D7EB /* DDNumber.h */; }; 71822780258744D000661B83 /* DDRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E444DC7B249131B00060D7EB /* DDRange.h */; }; - 718D2C122C60BAE3000788F2 /* FBWebServerParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 718D2C112C60BAE3000788F2 /* FBWebServerParams.m */; }; - 718D2C132C60BAE3000788F2 /* FBWebServerParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 718D2C102C60BAE3000788F2 /* FBWebServerParams.h */; }; - 718D2C142C60BAE3000788F2 /* FBWebServerParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 718D2C102C60BAE3000788F2 /* FBWebServerParams.h */; }; - 718D2C152C60BAE3000788F2 /* FBWebServerParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 718D2C112C60BAE3000788F2 /* FBWebServerParams.m */; }; 718F49C8230844330045FE8B /* FBProtocolHelpersTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 718F49C7230844330045FE8B /* FBProtocolHelpersTests.m */; }; 718F49C923087ACF0045FE8B /* FBProtocolHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155DD23080CA600646AFB /* FBProtocolHelpers.h */; }; 718F49CA23087AD30045FE8B /* FBProtocolHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B155DE23080CA600646AFB /* FBProtocolHelpers.m */; }; @@ -1031,8 +1027,6 @@ 718226C72587443600661B83 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GCDAsyncSocket.h; path = WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h; sourceTree = SOURCE_ROOT; }; 718226C82587443600661B83 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GCDAsyncSocket.m; path = WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m; sourceTree = SOURCE_ROOT; }; 718226C92587443600661B83 /* GCDAsyncUdpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GCDAsyncUdpSocket.m; path = WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.m; sourceTree = SOURCE_ROOT; }; - 718D2C102C60BAE3000788F2 /* FBWebServerParams.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBWebServerParams.h; sourceTree = ""; }; - 718D2C112C60BAE3000788F2 /* FBWebServerParams.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBWebServerParams.m; sourceTree = ""; }; 718F49C7230844330045FE8B /* FBProtocolHelpersTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBProtocolHelpersTests.m; sourceTree = ""; }; 71930C4020662E1F00D3AFEC /* FBPasteboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBPasteboard.h; sourceTree = ""; }; 71930C4120662E1F00D3AFEC /* FBPasteboard.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBPasteboard.m; sourceTree = ""; }; @@ -1954,8 +1948,6 @@ 7140974A1FAE1B51008FB2C5 /* FBW3CActionsSynthesizer.m */, 713AE573243A53BE0000D657 /* FBW3CActionsHelpers.h */, 713AE574243A53BE0000D657 /* FBW3CActionsHelpers.m */, - 718D2C102C60BAE3000788F2 /* FBWebServerParams.h */, - 718D2C112C60BAE3000788F2 /* FBWebServerParams.m */, 7157B28F221DADD2001C348C /* FBXCAXClientProxy.h */, 7157B290221DADD2001C348C /* FBXCAXClientProxy.m */, EE5A24401F136C8D0078B1D9 /* FBXCodeCompatibility.h */, @@ -2471,7 +2463,6 @@ 641EE6D62240C5CA00173FCB /* FBLogger.h in Headers */, 71BB58F72B96531900CB9BFE /* FBScreenRecordingContainer.h in Headers */, 641EE6D72240C5CA00173FCB /* XCTestObserver.h in Headers */, - 718D2C142C60BAE3000788F2 /* FBWebServerParams.h in Headers */, 641EE6D82240C5CA00173FCB /* XCUIElement.h in Headers */, 641EE6D92240C5CA00173FCB /* XCKeyboardInputSolver.h in Headers */, 718226CB2587443700661B83 /* GCDAsyncUdpSocket.h in Headers */, @@ -2727,7 +2718,6 @@ EE35AD311E3B77D600A02D78 /* XCKeyboardLayout.h in Headers */, 716C9DFA27315D21005AD475 /* FBReflectionUtils.h in Headers */, E444DCB624913C220060D7EB /* RouteRequest.h in Headers */, - 718D2C132C60BAE3000788F2 /* FBWebServerParams.h in Headers */, 71F5BE23252E576C00EE9EBA /* XCUIElement+FBSwiping.h in Headers */, 718226CC2587443700661B83 /* GCDAsyncSocket.h in Headers */, EE35AD3B1E3B77D600A02D78 /* XCTAsyncActivity-Protocol.h in Headers */, @@ -3103,7 +3093,6 @@ 641EE5D72240C5CA00173FCB /* FBScreenshotCommands.m in Sources */, 71F3E7D725417FF400E0C22B /* FBSettings.m in Sources */, 641EE5D92240C5CA00173FCB /* XCUIElement+FBPickerWheel.m in Sources */, - 718D2C152C60BAE3000788F2 /* FBWebServerParams.m in Sources */, 641EE5DA2240C5CA00173FCB /* XCUIApplicationProcessDelay.m in Sources */, 641EE5DB2240C5CA00173FCB /* FBXPath.m in Sources */, 71C8E55425399A6B008572C1 /* XCUIApplication+FBQuiescence.m in Sources */, @@ -3293,7 +3282,6 @@ AD76723E1D6B7CC000610457 /* XCUIElement+FBTyping.m in Sources */, EE158AAF1CBD456F00A3E3F0 /* XCUIElement+FBAccessibility.m in Sources */, 714E14BA29805CAE00375DD7 /* XCAXClient_iOS+FBSnapshotReqParams.m in Sources */, - 718D2C122C60BAE3000788F2 /* FBWebServerParams.m in Sources */, 7150348821A6DAD600A0F4BA /* FBImageUtils.m in Sources */, E444DCAB24913C220060D7EB /* HTTPResponseProxy.m in Sources */, E444DC6D249131890060D7EB /* HTTPErrorResponse.m in Sources */, diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 97baab7a1..7b3c4dbb5 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -20,7 +20,6 @@ #import "FBRuntimeUtils.h" #import "FBActiveAppDetectionPoint.h" #import "FBXCodeCompatibility.h" -#import "FBWebServerParams.h" #import "XCUIApplication+FBHelpers.h" #import "XCUIApplication+FBQuiescence.h" #import "XCUIDevice.h" @@ -177,18 +176,6 @@ + (NSArray *)routes _XCTSetApplicationStateTimeout(defaultTimeout); } } - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"17.0") && [bundleID isEqualToString:FB_SAFARI_BUNDLE_ID]) { - // Opening the default URL in Safari instead of an empty page helps - // the remote debugger to avoid issues while looking for active web views - FBWebServerParams *wsParams = FBWebServerParams.sharedInstance; - NSString *healthEndpoint = [NSString stringWithFormat:@"http://127.0.0.1:%@/health", wsParams.port]; - id errorResponse = [self openDeepLink:healthEndpoint - withApplication:bundleID - timeout:capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]]; - if (nil != errorResponse) { - NSLog(@"Was not able to open the default URL %@ in Safari", healthEndpoint); - } - } } if (!app.running) { NSString *errorMsg = [NSString stringWithFormat:@"Cannot launch %@ application. Make sure the correct bundle identifier has been provided in capabilities and check the device log for possible crash report occurrences", bundleID]; diff --git a/WebDriverAgentLib/Routing/FBWebServer.m b/WebDriverAgentLib/Routing/FBWebServer.m index 8d9c30203..ff9e4c424 100644 --- a/WebDriverAgentLib/Routing/FBWebServer.m +++ b/WebDriverAgentLib/Routing/FBWebServer.m @@ -23,7 +23,6 @@ #import "FBUnknownCommands.h" #import "FBConfiguration.h" #import "FBLogger.h" -#import "FBWebServerParams.h" #import "XCUIDevice+FBHelpers.h" @@ -103,8 +102,6 @@ - (void)startHTTPServer serverStarted = [self attemptToStartServer:self.server onPort:port withError:&error]; if (serverStarted) { - FBWebServerParams* wsParams = FBWebServerParams.sharedInstance; - wsParams.port = @(self.server.port); break; } From 5e98841f56eda6454d67d813b921bfcf98f1ff78 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 7 Aug 2024 13:48:57 +0200 Subject: [PATCH 115/368] feat: Add idleTimeoutMs param to the openUrl call (#933) --- WebDriverAgentLib/Commands/FBSessionCommands.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 7b3c4dbb5..c11c5eabb 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -66,6 +66,7 @@ + (NSArray *)routes return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"URL is required" traceback:nil]); } NSString* bundleId = request.arguments[@"bundleId"]; + NSNumber* idleTimeoutMs = request.arguments[@"idleTimeoutMs"]; NSError *error; if (nil == bundleId) { if (![XCUIDevice.sharedDevice fb_openUrl:urlString error:&error]) { @@ -75,6 +76,10 @@ + (NSArray *)routes if (![XCUIDevice.sharedDevice fb_openUrl:urlString withApplication:bundleId error:&error]) { return FBResponseWithUnknownError(error); } + if (idleTimeoutMs.doubleValue > 0) { + XCUIApplication *app = [[XCUIApplication alloc] initWithBundleIdentifier:bundleId]; + [app fb_waitUntilStableWithTimeout:FBMillisToSeconds(idleTimeoutMs.doubleValue)]; + } } return FBResponseWithOK(); } From bf7652abb0379c7f6ddc81df0e524c778c1e58db Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 7 Aug 2024 12:04:47 +0000 Subject: [PATCH 116/368] chore(release): 8.9.0 [skip ci] ## [8.9.0](https://github.com/appium/WebDriverAgent/compare/v8.8.0...v8.9.0) (2024-08-07) ### Features * Add idleTimeoutMs param to the openUrl call ([#933](https://github.com/appium/WebDriverAgent/issues/933)) ([5e98841](https://github.com/appium/WebDriverAgent/commit/5e98841f56eda6454d67d813b921bfcf98f1ff78)) ### Bug Fixes * Revert the logic to open the default URL in Safari via deeplink ([#932](https://github.com/appium/WebDriverAgent/issues/932)) ([7c51145](https://github.com/appium/WebDriverAgent/commit/7c5114518509c9a399845283eca7708248fb838f)) --- CHANGELOG.md | 10 ++++++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa45b3118..784c4161f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [8.9.0](https://github.com/appium/WebDriverAgent/compare/v8.8.0...v8.9.0) (2024-08-07) + +### Features + +* Add idleTimeoutMs param to the openUrl call ([#933](https://github.com/appium/WebDriverAgent/issues/933)) ([5e98841](https://github.com/appium/WebDriverAgent/commit/5e98841f56eda6454d67d813b921bfcf98f1ff78)) + +### Bug Fixes + +* Revert the logic to open the default URL in Safari via deeplink ([#932](https://github.com/appium/WebDriverAgent/issues/932)) ([7c51145](https://github.com/appium/WebDriverAgent/commit/7c5114518509c9a399845283eca7708248fb838f)) + ## [8.8.0](https://github.com/appium/WebDriverAgent/compare/v8.7.12...v8.8.0) (2024-08-06) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index da4fdff27..d34fbd8cf 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.8.0 + 8.9.0 CFBundleSignature ???? CFBundleVersion - 8.8.0 + 8.9.0 NSPrincipalClass diff --git a/package.json b/package.json index 9a25258f2..8e2f71b1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.8.0", + "version": "8.9.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 2ccc436991ca880a1dfdec688dc8167008fe382d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 9 Aug 2024 20:06:54 +0200 Subject: [PATCH 117/368] fix: Update swizzling of waitForQuiescenceIncludingAnimationsIdle: API for Xcode16-beta5 (#935) --- .../XCTest/XCUIApplicationProcess.h | 4 ++ .../XCAXClient_iOS+FBSnapshotReqParams.m | 1 + .../Categories/XCTIssue+FBPatcher.m | 3 ++ .../XCUIApplicationProcess+FBQuiescence.h | 5 +++ .../XCUIApplicationProcess+FBQuiescence.m | 42 +++++++++++++++++++ .../Categories/XCUIElement+FBUID.m | 1 + .../Categories/XCUIElement+FBUtilities.m | 3 +- WebDriverAgentLib/Routing/FBExceptions.h | 3 ++ WebDriverAgentLib/Routing/FBExceptions.m | 1 + WebDriverAgentLib/Routing/FBRoute.m | 3 ++ .../Utilities/FBXCTestDaemonsProxy.m | 3 ++ .../Utilities/XCUIApplicationProcessDelay.m | 3 ++ 12 files changed, 71 insertions(+), 1 deletion(-) diff --git a/PrivateHeaders/XCTest/XCUIApplicationProcess.h b/PrivateHeaders/XCTest/XCUIApplicationProcess.h index f0b4d358c..64770393e 100644 --- a/PrivateHeaders/XCTest/XCUIApplicationProcess.h +++ b/PrivateHeaders/XCTest/XCUIApplicationProcess.h @@ -65,7 +65,11 @@ - (void)terminate; - (void)waitForViewControllerViewDidDisappearWithTimeout:(double)arg1; - (void)waitForAutomationSession; +// Before Xcode16-beta5 - (void)waitForQuiescenceIncludingAnimationsIdle:(BOOL)arg1; +// Since Xcode16-beta5 +- (void)waitForQuiescenceIncludingAnimationsIdle:(BOOL)arg1 isPreEvent:(BOOL)arg2; + - (id)shortDescription; - (id)_queue_description; diff --git a/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m b/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m index 356a1ea05..3dc6754d5 100644 --- a/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m +++ b/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m @@ -65,6 +65,7 @@ @implementation XCAXClient_iOS (FBSnapshotReqParams) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" +#pragma clang diagnostic ignored "-Wcast-function-type-strict" + (void)load { diff --git a/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m b/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m index dc27e86a6..a3b099309 100644 --- a/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m +++ b/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m @@ -20,6 +20,8 @@ @implementation XCTIssue (AMPatcher) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" +#pragma clang diagnostic ignored "-Wcast-function-type-strict" + + (void)load { SEL originalShouldInterruptTest = NSSelectorFromString(@"shouldInterruptTest"); @@ -28,6 +30,7 @@ + (void)load if (nil == originalShouldInterruptTestMethod) return; method_setImplementation(originalShouldInterruptTestMethod, (IMP)swizzledShouldInterruptTest); } + #pragma clang diagnostic pop @end diff --git a/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h b/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h index 0c78f2403..f7aacb5c5 100644 --- a/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h +++ b/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h @@ -18,6 +18,11 @@ NS_ASSUME_NONNULL_BEGIN /*! Defines wtether the process should perform quiescence checks. YES by default */ @property (nonatomic) NSNumber* fb_shouldWaitForQuiescence; +/** + @param waitForAnimations Set it to YES if XCTest should also wait for application animations to complete + */ +- (void)fb_waitForQuiescenceIncludingAnimationsIdle:(bool)waitForAnimations; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m b/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m index cc60e429f..9c1d06eba 100644 --- a/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m +++ b/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m @@ -12,10 +12,12 @@ #import #import "FBConfiguration.h" +#import "FBExceptions.h" #import "FBLogger.h" #import "FBSettings.h" static void (*original_waitForQuiescenceIncludingAnimationsIdle)(id, SEL, BOOL); +static void (*original_waitForQuiescenceIncludingAnimationsIdlePreEvent)(id, SEL, BOOL, BOOL); static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd, BOOL includingAnimations) { @@ -38,17 +40,43 @@ static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd, } } +static void swizzledWaitForQuiescenceIncludingAnimationsIdlePreEvent(id self, SEL _cmd, BOOL includingAnimations, BOOL isPreEvent) +{ + NSString *bundleId = [self bundleID]; + if (![[self fb_shouldWaitForQuiescence] boolValue] || FBConfiguration.waitForIdleTimeout < DBL_EPSILON) { + [FBLogger logFmt:@"Quiescence checks are disabled for %@ application. Making it to believe it is idling", + bundleId]; + return; + } + + NSTimeInterval desiredTimeout = FBConfiguration.waitForIdleTimeout; + NSTimeInterval previousTimeout = _XCTApplicationStateTimeout(); + _XCTSetApplicationStateTimeout(desiredTimeout); + [FBLogger logFmt:@"Waiting up to %@s until %@ is in idle state (%@ animations)", + @(desiredTimeout), bundleId, includingAnimations ? @"including" : @"excluding"]; + @try { + original_waitForQuiescenceIncludingAnimationsIdlePreEvent(self, _cmd, includingAnimations, isPreEvent); + } @finally { + _XCTSetApplicationStateTimeout(previousTimeout); + } +} + @implementation XCUIApplicationProcess (FBQuiescence) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" +#pragma clang diagnostic ignored "-Wcast-function-type-strict" + (void)load { Method waitForQuiescenceIncludingAnimationsIdleMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:)); + Method waitForQuiescenceIncludingAnimationsIdlePreEventMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:isPreEvent:)); if (nil != waitForQuiescenceIncludingAnimationsIdleMethod) { IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdle; original_waitForQuiescenceIncludingAnimationsIdle = (void (*)(id, SEL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdleMethod, swizzledImp); + } else if (nil != waitForQuiescenceIncludingAnimationsIdlePreEventMethod) { + IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdlePreEvent; + original_waitForQuiescenceIncludingAnimationsIdlePreEvent = (void (*)(id, SEL, BOOL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdlePreEventMethod, swizzledImp); } else { [FBLogger log:@"Could not find method -[XCUIApplicationProcess waitForQuiescenceIncludingAnimationsIdle:]"]; } @@ -74,4 +102,18 @@ - (void)setFb_shouldWaitForQuiescence:(NSNumber *)value objc_setAssociatedObject(self, &XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } +- (void)fb_waitForQuiescenceIncludingAnimationsIdle:(bool)waitForAnimations +{ + if ([self respondsToSelector:@selector(waitForQuiescenceIncludingAnimationsIdle:)]) { + [self waitForQuiescenceIncludingAnimationsIdle:waitForAnimations]; + } else if ([self respondsToSelector:@selector(waitForQuiescenceIncludingAnimationsIdle:isPreEvent:)]) { + [self waitForQuiescenceIncludingAnimationsIdle:waitForAnimations isPreEvent:NO]; + } else { + @throw [NSException exceptionWithName:FBIncompatibleWdaException + reason:@"The current WebDriverAgent build is not compatible to your device OS version" + userInfo:@{}]; + } +} + + @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUID.m b/WebDriverAgentLib/Categories/XCUIElement+FBUID.m index 765b410c1..ecac2cd91 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUID.m @@ -42,6 +42,7 @@ static void swizzled_validatePredicateWithExpressionsAllowed(id self, SEL _cmd, #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" +#pragma clang diagnostic ignored "-Wcast-function-type-strict" + (void)load { Class XCElementSnapshotCls = objc_lookUpClass("XCElementSnapshot"); diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m index b5a072c06..5f9fd96f4 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m @@ -31,6 +31,7 @@ #import "XCTElementSetTransformer-Protocol.h" #import "XCTestPrivateSymbols.h" #import "XCTRunnerDaemonSession.h" +#import "XCUIApplicationProcess+FBQuiescence.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBWebDriverAttributes.h" #import "XCUIElementQuery.h" @@ -190,7 +191,7 @@ - (void)fb_waitUntilStableWithTimeout:(NSTimeInterval)timeout self.application.fb_shouldWaitForQuiescence = YES; } [[[self.application applicationImpl] currentProcess] - waitForQuiescenceIncludingAnimationsIdle:YES]; + fb_waitForQuiescenceIncludingAnimationsIdle:YES]; if (previousQuiescence != self.application.fb_shouldWaitForQuiescence) { self.application.fb_shouldWaitForQuiescence = previousQuiescence; } diff --git a/WebDriverAgentLib/Routing/FBExceptions.h b/WebDriverAgentLib/Routing/FBExceptions.h index a7263bae4..13fda9f4c 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.h +++ b/WebDriverAgentLib/Routing/FBExceptions.h @@ -55,4 +55,7 @@ extern NSString *const FBApplicationCrashedException; /*! Exception used to notify about the application is not installed */ extern NSString *const FBApplicationMissingException; +/*! Exception used to notify about WDA incompatibility with the current platform version */ +extern NSString *const FBIncompatibleWdaException; + NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBExceptions.m b/WebDriverAgentLib/Routing/FBExceptions.m index 9e1f2141f..93c1837e7 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.m +++ b/WebDriverAgentLib/Routing/FBExceptions.m @@ -22,3 +22,4 @@ NSString *const FBClassChainQueryParseException = @"FBClassChainQueryParseException"; NSString *const FBApplicationCrashedException = @"FBApplicationCrashedException"; NSString *const FBApplicationMissingException = @"FBApplicationMissingException"; +NSString *const FBIncompatibleWdaException = @"FBIncompatibleWdaException"; diff --git a/WebDriverAgentLib/Routing/FBRoute.m b/WebDriverAgentLib/Routing/FBRoute.m index 745ddaf31..5d740de7e 100644 --- a/WebDriverAgentLib/Routing/FBRoute.m +++ b/WebDriverAgentLib/Routing/FBRoute.m @@ -39,7 +39,10 @@ @implementation FBRoute_TargetAction - (void)mountRequest:(FBRouteRequest *)request intoResponse:(RouteResponse *)response { [self decorateRequest:request]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-strict" id (*requestMsgSend)(id, SEL, FBRouteRequest *) = ((id(*)(id, SEL, FBRouteRequest *))objc_msgSend); +#pragma clang diagnostic pop id payload = requestMsgSend(self.target, self.action, request); [payload dispatchWithResponse:response]; } diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m index f71e1bd3d..59e3a64be 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m @@ -73,9 +73,12 @@ + (void)swizzleLaunchApp { [FBLogger log:@"Could not find method -[XCTRunnerDaemonSession launchApplicationWithPath:]"]; return; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-strict" // 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); +#pragma clang diagnostic pop } + (id)testRunnerProxy diff --git a/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m b/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m index c50ca4138..86c1fc45c 100644 --- a/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m +++ b/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m @@ -61,7 +61,10 @@ + (void)swizzleSetEventLoopHasIdled { [FBLogger log:@"Could not find method -[XCUIApplicationProcess setEventLoopHasIdled:]"]; return; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-strict" orig_set_event_loop_has_idled = (void(*)(id, SEL, BOOL)) method_getImplementation(original); +#pragma clang diagnostic pop Method replace = class_getClassMethod([XCUIApplicationProcessDelay class], @selector(setEventLoopHasIdled:)); method_setImplementation(original, method_getImplementation(replace)); isSwizzled = YES; From fb7932255359460b6962b14abada08ca70333195 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 9 Aug 2024 18:11:29 +0000 Subject: [PATCH 118/368] chore(release): 8.9.1 [skip ci] ## [8.9.1](https://github.com/appium/WebDriverAgent/compare/v8.9.0...v8.9.1) (2024-08-09) ### Bug Fixes * Update swizzling of waitForQuiescenceIncludingAnimationsIdle: API for Xcode16-beta5 ([#935](https://github.com/appium/WebDriverAgent/issues/935)) ([2ccc436](https://github.com/appium/WebDriverAgent/commit/2ccc436991ca880a1dfdec688dc8167008fe382d)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 784c4161f..9b79c45c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.9.1](https://github.com/appium/WebDriverAgent/compare/v8.9.0...v8.9.1) (2024-08-09) + +### Bug Fixes + +* Update swizzling of waitForQuiescenceIncludingAnimationsIdle: API for Xcode16-beta5 ([#935](https://github.com/appium/WebDriverAgent/issues/935)) ([2ccc436](https://github.com/appium/WebDriverAgent/commit/2ccc436991ca880a1dfdec688dc8167008fe382d)) + ## [8.9.0](https://github.com/appium/WebDriverAgent/compare/v8.8.0...v8.9.0) (2024-08-07) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index d34fbd8cf..28efd96d3 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.9.0 + 8.9.1 CFBundleSignature ???? CFBundleVersion - 8.9.0 + 8.9.1 NSPrincipalClass diff --git a/package.json b/package.json index 8e2f71b1f..98287ff51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.9.0", + "version": "8.9.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 3ef009317801dca47efe34bd048d3cab2e644ee2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 10:39:47 -0700 Subject: [PATCH 119/368] chore(deps-dev): bump sinon from 18.0.1 to 19.0.1 (#938) Bumps [sinon](https://github.com/sinonjs/sinon) from 18.0.1 to 19.0.1. - [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/v18.0.1...v19.0.1) --- 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 98287ff51..ad1c15632 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "prettier": "^3.0.0", "semantic-release": "^24.0.0", "semver": "^7.3.7", - "sinon": "^18.0.0", + "sinon": "^19.0.1", "ts-node": "^10.9.1", "typescript": "^5.4.2" }, From 0a08cf5e7e11e9f87ed4f83b987632605fb45008 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 13 Sep 2024 17:44:35 +0000 Subject: [PATCH 120/368] chore(release): 8.9.2 [skip ci] ## [8.9.2](https://github.com/appium/WebDriverAgent/compare/v8.9.1...v8.9.2) (2024-09-13) ### Miscellaneous Chores * **deps-dev:** bump sinon from 18.0.1 to 19.0.1 ([#938](https://github.com/appium/WebDriverAgent/issues/938)) ([3ef0093](https://github.com/appium/WebDriverAgent/commit/3ef009317801dca47efe34bd048d3cab2e644ee2)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b79c45c7..2fb98c7d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.9.2](https://github.com/appium/WebDriverAgent/compare/v8.9.1...v8.9.2) (2024-09-13) + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 18.0.1 to 19.0.1 ([#938](https://github.com/appium/WebDriverAgent/issues/938)) ([3ef0093](https://github.com/appium/WebDriverAgent/commit/3ef009317801dca47efe34bd048d3cab2e644ee2)) + ## [8.9.1](https://github.com/appium/WebDriverAgent/compare/v8.9.0...v8.9.1) (2024-08-09) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 28efd96d3..a43dfce01 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.9.1 + 8.9.2 CFBundleSignature ???? CFBundleVersion - 8.9.1 + 8.9.2 NSPrincipalClass diff --git a/package.json b/package.json index ad1c15632..ced94dc6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.9.1", + "version": "8.9.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 9fd58b6c43ddeefd22ef379f8a92c867dfb4974b Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 18 Sep 2024 09:27:21 -0700 Subject: [PATCH 121/368] ci: add Xcode 16 (#939) * docs: use Xcode 16 beta 6 * Update functional-test.yml * Update functional-test.yml --- .github/workflows/functional-test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index e9bb01e19..4e51234c4 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -12,6 +12,9 @@ jobs: fail-fast: false matrix: test_targets: + - XCODE_VERSION: '16.0.0' + IOS_VERSION: '18.0' + IOS_MODEL: iPhone 15 Plus - XCODE_VERSION: '15.3' IOS_VERSION: '17.4' IOS_MODEL: iPhone 15 Plus From a2173d05df8ef831310e805a8e6a8a8d17725201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20L=C3=BCdeke?= <311702+aluedeke@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:19:13 +0200 Subject: [PATCH 122/368] chore: remove unused FBBaseActionsParser and cleanup imports in FBConfiguration (#943) --- Configurations/IOSSettings.xcconfig | 2 +- Configurations/TVOSSettings.xcconfig | 2 +- .../Utilities/FBBaseActionsParser.m | 32 ------------------- WebDriverAgentLib/Utilities/FBConfiguration.h | 4 --- WebDriverAgentLib/Utilities/FBConfiguration.m | 4 +++ 5 files changed, 6 insertions(+), 38 deletions(-) delete mode 100644 WebDriverAgentLib/Utilities/FBBaseActionsParser.m diff --git a/Configurations/IOSSettings.xcconfig b/Configurations/IOSSettings.xcconfig index 70ae5ec68..b9969a48b 100644 --- a/Configurations/IOSSettings.xcconfig +++ b/Configurations/IOSSettings.xcconfig @@ -28,4 +28,4 @@ RUN_CLANG_STATIC_ANALYZER = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) -WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability +WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability -Wno-declaration-after-statement -Wno-objc-messaging-id -Wno-direct-ivar-access -Wno-cast-qual -Wno-deprecated-declarations diff --git a/Configurations/TVOSSettings.xcconfig b/Configurations/TVOSSettings.xcconfig index 70ae5ec68..b9969a48b 100644 --- a/Configurations/TVOSSettings.xcconfig +++ b/Configurations/TVOSSettings.xcconfig @@ -28,4 +28,4 @@ RUN_CLANG_STATIC_ANALYZER = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) -WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability +WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability -Wno-declaration-after-statement -Wno-objc-messaging-id -Wno-direct-ivar-access -Wno-cast-qual -Wno-deprecated-declarations diff --git a/WebDriverAgentLib/Utilities/FBBaseActionsParser.m b/WebDriverAgentLib/Utilities/FBBaseActionsParser.m deleted file mode 100644 index 872dc268e..000000000 --- a/WebDriverAgentLib/Utilities/FBBaseActionsParser.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 "FBBaseActionsSynthesizer.h" - -#import "FBErrorBuilder.h" - -@implementation FBBaseActionsSynthesizer - -- (instancetype)initWithActions:(NSArray *)actions forApplication:(XCUIApplication *)application -{ - self = [super init]; - if (self) { - _actions = actions; - _application = application; - } - return self; -} - -- (nullable XCSynthesizedEventRecord *)synthesizeWithError:(NSError **)error -{ - @throw [[FBErrorBuilder.builder withDescription:@"Override this method in subclasses"] build]; - return nil; -} - -@end diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index dc2018928..75275ccf6 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -9,10 +9,6 @@ #import -#import "AXSettings.h" -#import "UIKeyboardImpl.h" -#import "TIPreferencesController.h" - NS_ASSUME_NONNULL_BEGIN extern NSString *const FBSnapshotMaxDepthKey; diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index 1d7438ae1..e91717b2d 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -9,6 +9,10 @@ #import "FBConfiguration.h" +#import "AXSettings.h" +#import "UIKeyboardImpl.h" +#import "TIPreferencesController.h" + #include #import From f9223b3b4cb9bd25c033f53edb5314abfbd27f62 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 7 Oct 2024 20:24:12 +0000 Subject: [PATCH 123/368] chore(release): 8.9.3 [skip ci] ## [8.9.3](https://github.com/appium/WebDriverAgent/compare/v8.9.2...v8.9.3) (2024-10-07) ### Miscellaneous Chores * remove unused FBBaseActionsParser and cleanup imports in FBConfiguration ([#943](https://github.com/appium/WebDriverAgent/issues/943)) ([a2173d0](https://github.com/appium/WebDriverAgent/commit/a2173d05df8ef831310e805a8e6a8a8d17725201)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fb98c7d4..bab482944 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.9.3](https://github.com/appium/WebDriverAgent/compare/v8.9.2...v8.9.3) (2024-10-07) + +### Miscellaneous Chores + +* remove unused FBBaseActionsParser and cleanup imports in FBConfiguration ([#943](https://github.com/appium/WebDriverAgent/issues/943)) ([a2173d0](https://github.com/appium/WebDriverAgent/commit/a2173d05df8ef831310e805a8e6a8a8d17725201)) + ## [8.9.2](https://github.com/appium/WebDriverAgent/compare/v8.9.1...v8.9.2) (2024-09-13) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index a43dfce01..63b4beea4 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.9.2 + 8.9.3 CFBundleSignature ???? CFBundleVersion - 8.9.2 + 8.9.3 NSPrincipalClass diff --git a/package.json b/package.json index ced94dc6b..b813b8a01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.9.2", + "version": "8.9.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From f0bdce7eb8fdb13d2309d28e936950c77f006b20 Mon Sep 17 00:00:00 2001 From: mwakizaka <21286384+mwakizaka@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:35:13 +0900 Subject: [PATCH 124/368] fix: Consider transient overlay windows when respectSystemAlerts is enabled (#946) --- WebDriverAgentLib/Routing/FBSession.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index 14565ad00..a4460b4a8 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -178,8 +178,13 @@ - (XCUIApplication *)activeApplication if (nil != self.testedApplication) { XCUIApplicationState testedAppState = self.testedApplication.state; if (testedAppState >= XCUIApplicationStateRunningForeground) { + // We look for `SBTransientOverlayWindow` elements for half modals. See https://github.com/appium/WebDriverAgent/pull/946 + NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"%K == %@ OR %K == %@", + @"elementType", @(XCUIElementTypeAlert), + @"identifier", @"SBTransientOverlayWindow"]; if ([FBConfiguration shouldRespectSystemAlerts] - && [XCUIApplication.fb_systemApplication descendantsMatchingType:XCUIElementTypeAlert].count > 0) { + && [[XCUIApplication.fb_systemApplication descendantsMatchingType:XCUIElementTypeAny] + matchingPredicate:searchPredicate].count > 0) { return XCUIApplication.fb_systemApplication; } return (XCUIApplication *)self.testedApplication; From 7bd044d75a1f75a9c2696e1a031ffda822f457b7 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 17 Oct 2024 10:40:25 +0000 Subject: [PATCH 125/368] chore(release): 8.9.4 [skip ci] ## [8.9.4](https://github.com/appium/WebDriverAgent/compare/v8.9.3...v8.9.4) (2024-10-17) ### Bug Fixes * Consider transient overlay windows when respectSystemAlerts is enabled ([#946](https://github.com/appium/WebDriverAgent/issues/946)) ([f0bdce7](https://github.com/appium/WebDriverAgent/commit/f0bdce7eb8fdb13d2309d28e936950c77f006b20)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bab482944..619060ee0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.9.4](https://github.com/appium/WebDriverAgent/compare/v8.9.3...v8.9.4) (2024-10-17) + +### Bug Fixes + +* Consider transient overlay windows when respectSystemAlerts is enabled ([#946](https://github.com/appium/WebDriverAgent/issues/946)) ([f0bdce7](https://github.com/appium/WebDriverAgent/commit/f0bdce7eb8fdb13d2309d28e936950c77f006b20)) + ## [8.9.3](https://github.com/appium/WebDriverAgent/compare/v8.9.2...v8.9.3) (2024-10-07) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 63b4beea4..7749d5e09 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.9.3 + 8.9.4 CFBundleSignature ???? CFBundleVersion - 8.9.3 + 8.9.4 NSPrincipalClass diff --git a/package.json b/package.json index b813b8a01..922e3a73e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.9.3", + "version": "8.9.4", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From afd09a8eeb1fa28ed7e070cbf25605e578b26b25 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 28 Oct 2024 23:15:00 -0700 Subject: [PATCH 126/368] ci: update azure env (#947) * ci: update azure env * update testAccessbilityAudit * add an assertion * skip for now --- .azure-pipelines.yml | 28 +++++++++---------- .../IntegrationTests/FBVideoRecordingTests.m | 2 ++ .../XCUIApplicationHelperTests.m | 20 ++++++++++++- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index a324a9b7d..89887d258 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -1,19 +1,19 @@ # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml variables: - 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) (3rd generation) - MAX_VM_IMAGE: macOS-12 - 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) + MIN_VM_IMAGE: macOS-14 + MIN_XCODE_VERSION: 14.3.1 + MIN_PLATFORM_VERSION: 16.4 + MIN_TV_PLATFORM_VERSION: 16.4 + MIN_TV_DEVICE_NAME: Apple TV 4K (3rd generation) + MIN_IPHONE_DEVICE_NAME: iPhone 14 Plus + MIN_IPAD_DEVICE_NAME: iPad Pro (11-inch) (4th generation) + MAX_VM_IMAGE: macOS-14 + MAX_XCODE_VERSION: 15.4 + MAX_PLATFORM_VERSION: 17.5 + MAX_PLATFORM_VERSION_TV: 17.5 + MAX_IPHONE_DEVICE_NAME: iPhone 15 Plus + MAX_TV_DEVICE_NAME: Apple TV 4K (3rd generation) + MAX_IPAD_DEVICE_NAME: iPad Air 11-inch (M2) DEFAULT_NODE_VERSION: "18.x" trigger: diff --git a/WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m b/WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m index 617480c0c..191af3420 100644 --- a/WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBVideoRecordingTests.m @@ -31,6 +31,8 @@ - (void)setUp - (void)testStartingAndStoppingVideoRecording { + XCTSkip(@"Failed on Azure Pipeline. Local run succeeded."); + // Video recording is only available since iOS 17 if (SYSTEM_VERSION_LESS_THAN(@"17.0")) { return; diff --git a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m index e86f62021..15b906db7 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m @@ -111,7 +111,25 @@ - (void)testAccessbilityAudit [set addObject:@"XCUIAccessibilityAuditTypeAll"]; NSArray *auditIssues2 = [XCUIApplication.fb_activeApplication fb_performAccessibilityAuditWithAuditTypesSet:set.copy error:&error]; - XCTAssertEqualObjects(auditIssues1, auditIssues2); + // 'elementDescription' is not in this list because it could have + // different object id's debug description in XCTest. + NSArray *checkKeys = @[ + @"auditType", + @"compactDescription", + @"detailedDescription", + @"element", + @"elementAttributes" + ]; + + XCTAssertEqual([auditIssues1 count], [auditIssues2 count]); + for (int i = 1; i < [auditIssues1 count]; i++) { + for (NSString *k in checkKeys) { + XCTAssertEqualObjects( + [auditIssues1[i] objectForKey:k], + [auditIssues2[i] objectForKey:k] + ); + } + } XCTAssertNil(error); } From 61bc051180d691d26233c66a5a76ed20b7fa09d2 Mon Sep 17 00:00:00 2001 From: KAdachi <27220367+ppken@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:36:51 +0900 Subject: [PATCH 127/368] feat: add useClearTextShortcut setting (#952) --- WebDriverAgentLib/Categories/XCUIElement+FBTyping.m | 2 +- WebDriverAgentLib/Commands/FBSessionCommands.m | 8 ++++++++ WebDriverAgentLib/Utilities/FBConfiguration.h | 9 +++++++++ WebDriverAgentLib/Utilities/FBConfiguration.m | 12 ++++++++++++ WebDriverAgentLib/Utilities/FBSettings.h | 1 + WebDriverAgentLib/Utilities/FBSettings.m | 1 + lib/types.ts | 1 + 7 files changed, 33 insertions(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m index db516a220..8b59ad031 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m @@ -166,7 +166,7 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot [self fb_prepareForTextInputWithSnapshot:snapshot]; } - if (retry == 0) { + if (retry == 0 && FBConfiguration.useClearTextShortcut) { // 1st attempt is via the IOHIDEvent as the fastest operation // https://github.com/appium/appium/issues/19389 [[XCUIDevice sharedDevice] fb_performIOHIDEventWithPage:0x07 // kHIDPage_KeyboardOrKeypad diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index c11c5eabb..e5d4894f5 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -141,6 +141,10 @@ + (NSArray *)routes [FBConfiguration forceSimulatorSoftwareKeyboardPresence]; } + if (capabilities[FB_SETTING_USE_CLEAR_TEXT_SHORTCUT]) { + [FBConfiguration setUseClearTextShortcut:[capabilities[FB_SETTING_USE_CLEAR_TEXT_SHORTCUT] boolValue]]; + } + NSString *bundleID = capabilities[FB_CAP_BUNDLE_ID]; NSString *initialUrl = capabilities[FB_CAP_INITIAL_URL]; XCUIApplication *app = nil; @@ -351,6 +355,7 @@ + (NSArray *)routes FB_SETTING_DEFAULT_ALERT_ACTION: request.session.defaultAlertAction ?: @"", FB_SETTING_MAX_TYPING_FREQUENCY: @([FBConfiguration maxTypingFrequency]), FB_SETTING_RESPECT_SYSTEM_ALERTS: @([FBConfiguration shouldRespectSystemAlerts]), + FB_SETTING_USE_CLEAR_TEXT_SHORTCUT: @([FBConfiguration useClearTextShortcut]), #if !TARGET_OS_TV FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation], #endif @@ -449,6 +454,9 @@ + (NSArray *)routes if (nil != [settings objectForKey:FB_SETTING_MAX_TYPING_FREQUENCY]) { [FBConfiguration setMaxTypingFrequency:[[settings objectForKey:FB_SETTING_MAX_TYPING_FREQUENCY] unsignedIntegerValue]]; } + if (nil != [settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT]) { + [FBConfiguration setUseClearTextShortcut:[[settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT] boolValue]]; + } #if !TARGET_OS_TV if (nil != [settings objectForKey:FB_SETTING_SCREENSHOT_ORIENTATION]) { diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index 75275ccf6..7c337826c 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -283,6 +283,15 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) { + (void)setDismissAlertButtonSelector:(NSString *)classChainSelector; + (NSString *)dismissAlertButtonSelector; +/** + * Whether to use HIDEvent for text clear. + * By default this is enabled and HIDEvent is used for text clear. + * + * @param enabled Either YES or NO + */ ++ (void)setUseClearTextShortcut:(BOOL)enabled; ++ (BOOL)useClearTextShortcut; + #if !TARGET_OS_TV /** Set the screenshot orientation for iOS diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index e91717b2d..dab8cb4db 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -56,6 +56,7 @@ static NSTimeInterval FBAnimationCoolOffTimeout; static BOOL FBShouldUseCompactResponses; static NSString *FBElementResponseAttributes; +static BOOL FBUseClearTextShortcut; #if !TARGET_OS_TV static UIInterfaceOrientation FBScreenshotOrientation; #endif @@ -438,6 +439,16 @@ + (NSString *)dismissAlertButtonSelector return FBDismissAlertButtonSelector; } ++ (void)setUseClearTextShortcut:(BOOL)enabled +{ + FBUseClearTextShortcut = enabled; +} + ++ (BOOL)useClearTextShortcut +{ + return FBUseClearTextShortcut; +} + #if !TARGET_OS_TV + (BOOL)setScreenshotOrientation:(NSString *)orientation error:(NSError **)error { @@ -503,6 +514,7 @@ + (void)resetSessionSettings FBAnimationCoolOffTimeout = 2.; // 50 should be enough for the majority of the cases. The performance is acceptable for values up to 100. FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @50); + FBUseClearTextShortcut = YES; #if !TARGET_OS_TV FBScreenshotOrientation = UIInterfaceOrientationUnknown; #endif diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index 5f4450110..b1f2f1fca 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -40,6 +40,7 @@ extern NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT; extern NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT; extern NSString* const FB_SETTING_MAX_TYPING_FREQUENCY; extern NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS; +extern NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT; NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index a45afeb90..ada529eed 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -35,3 +35,4 @@ NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT = @"animationCoolOffTimeout"; NSString* const FB_SETTING_MAX_TYPING_FREQUENCY = @"maxTypingFrequency"; NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS = @"respectSystemAlerts"; +NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT = @"useClearTextShortcut"; diff --git a/lib/types.ts b/lib/types.ts index 8b41dfc4e..82c51cb15 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -25,6 +25,7 @@ export interface WDASettings { waitForIdleTimeout?: number; animationCoolOffTimeout?: number; maxTypingFrequency?: number; + useClearTextShortcut?: boolean; } // WebDriverAgentLib/Utilities/FBCapabilities.h From 93f147a82e34042d388596d7522f7b4f896dc771 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 7 Nov 2024 07:41:17 +0000 Subject: [PATCH 128/368] chore(release): 8.10.0 [skip ci] ## [8.10.0](https://github.com/appium/WebDriverAgent/compare/v8.9.4...v8.10.0) (2024-11-07) ### Features * add useClearTextShortcut setting ([#952](https://github.com/appium/WebDriverAgent/issues/952)) ([61bc051](https://github.com/appium/WebDriverAgent/commit/61bc051180d691d26233c66a5a76ed20b7fa09d2)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 619060ee0..fd0e43dc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.10.0](https://github.com/appium/WebDriverAgent/compare/v8.9.4...v8.10.0) (2024-11-07) + +### Features + +* add useClearTextShortcut setting ([#952](https://github.com/appium/WebDriverAgent/issues/952)) ([61bc051](https://github.com/appium/WebDriverAgent/commit/61bc051180d691d26233c66a5a76ed20b7fa09d2)) + ## [8.9.4](https://github.com/appium/WebDriverAgent/compare/v8.9.3...v8.9.4) (2024-10-17) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 7749d5e09..04d3b61c5 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.9.4 + 8.10.0 CFBundleSignature ???? CFBundleVersion - 8.9.4 + 8.10.0 NSPrincipalClass diff --git a/package.json b/package.json index 922e3a73e..d3662bd62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.9.4", + "version": "8.10.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 940df80937381b481a2762fbf86b6249804591bd Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 10 Nov 2024 07:33:16 -0800 Subject: [PATCH 129/368] chore: remove unnecessary lines (#954) --- WebDriverAgentLib/Commands/FBSessionCommands.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index e5d4894f5..1972186d2 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -141,10 +141,6 @@ + (NSArray *)routes [FBConfiguration forceSimulatorSoftwareKeyboardPresence]; } - if (capabilities[FB_SETTING_USE_CLEAR_TEXT_SHORTCUT]) { - [FBConfiguration setUseClearTextShortcut:[capabilities[FB_SETTING_USE_CLEAR_TEXT_SHORTCUT] boolValue]]; - } - NSString *bundleID = capabilities[FB_CAP_BUNDLE_ID]; NSString *initialUrl = capabilities[FB_CAP_INITIAL_URL]; XCUIApplication *app = nil; From 6beb1b5393a4bde0e28051bffe23337846c5da72 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 10 Nov 2024 15:38:37 +0000 Subject: [PATCH 130/368] chore(release): 8.10.1 [skip ci] ## [8.10.1](https://github.com/appium/WebDriverAgent/compare/v8.10.0...v8.10.1) (2024-11-10) ### Miscellaneous Chores * remove unnecessary lines ([#954](https://github.com/appium/WebDriverAgent/issues/954)) ([940df80](https://github.com/appium/WebDriverAgent/commit/940df80937381b481a2762fbf86b6249804591bd)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd0e43dc5..4a2761854 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.10.1](https://github.com/appium/WebDriverAgent/compare/v8.10.0...v8.10.1) (2024-11-10) + +### Miscellaneous Chores + +* remove unnecessary lines ([#954](https://github.com/appium/WebDriverAgent/issues/954)) ([940df80](https://github.com/appium/WebDriverAgent/commit/940df80937381b481a2762fbf86b6249804591bd)) + ## [8.10.0](https://github.com/appium/WebDriverAgent/compare/v8.9.4...v8.10.0) (2024-11-07) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 04d3b61c5..f14279538 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.10.0 + 8.10.1 CFBundleSignature ???? CFBundleVersion - 8.10.0 + 8.10.1 NSPrincipalClass diff --git a/package.json b/package.json index d3662bd62..062531ae1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.10.0", + "version": "8.10.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 6112223b21026fae5545fe1b1433a09c67ff524b Mon Sep 17 00:00:00 2001 From: Sawan Garg Date: Mon, 11 Nov 2024 18:23:24 +0530 Subject: [PATCH 131/368] feat: Add support for excluded_attributes in JSON source hierarchy (#953) --- .../Categories/XCUIApplication+FBHelpers.h | 6 +++ .../Categories/XCUIApplication+FBHelpers.m | 53 +++++++++++++++---- WebDriverAgentLib/Commands/FBDebugCommands.m | 7 ++- .../XCUIApplicationHelperTests.m | 7 +++ 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h index 3ef66423b..54d4bd281 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h @@ -31,6 +31,12 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSDictionary *)fb_tree; +/** + @param excludedAttributes Set of possible attributes to be excluded i.e frame, enabled, visible, accessible, focused. If set to nil or an empty array then no attributes will be excluded from the resulting JSON + @return application elements tree in form of nested dictionaries + */ +- (NSDictionary *)fb_tree:(nullable NSSet *) excludedAttributes; + /** Return application elements accessibility tree in form of nested dictionaries */ diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index c3c99e6f5..6cdae945b 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -152,11 +152,16 @@ - (BOOL)fb_deactivateWithDuration:(NSTimeInterval)duration error:(NSError **)err } - (NSDictionary *)fb_tree +{ + return [self fb_tree:nil]; +} + +- (NSDictionary *)fb_tree:(nullable NSSet *) excludedAttributes { id snapshot = self.fb_isResolvedFromCache.boolValue ? self.lastSnapshot : [self fb_snapshotWithAllAttributesAndMaxDepth:nil]; - return [self.class dictionaryForElement:snapshot recursive:YES]; + return [self.class dictionaryForElement:snapshot recursive:YES excludedAttributes:excludedAttributes]; } - (NSDictionary *)fb_accessibilityTree @@ -167,7 +172,9 @@ - (NSDictionary *)fb_accessibilityTree return [self.class accessibilityInfoForElement:snapshot]; } -+ (NSDictionary *)dictionaryForElement:(id)snapshot recursive:(BOOL)recursive ++ (NSDictionary *)dictionaryForElement:(id)snapshot + recursive:(BOOL)recursive + excludedAttributes:(nullable NSSet *) excludedAttributes { NSMutableDictionary *info = [[NSMutableDictionary alloc] init]; info[@"type"] = [FBElementTypeTransformer shortStringWithElementType:snapshot.elementType]; @@ -177,11 +184,35 @@ + (NSDictionary *)dictionaryForElement:(id)snapshot recursi info[@"value"] = FBValueOrNull(wrappedSnapshot.wdValue); info[@"label"] = FBValueOrNull(wrappedSnapshot.wdLabel); info[@"rect"] = wrappedSnapshot.wdRect; - info[@"frame"] = NSStringFromCGRect(wrappedSnapshot.wdFrame); - info[@"isEnabled"] = [@([wrappedSnapshot isWDEnabled]) stringValue]; - info[@"isVisible"] = [@([wrappedSnapshot isWDVisible]) stringValue]; - info[@"isAccessible"] = [@([wrappedSnapshot isWDAccessible]) stringValue]; - info[@"isFocused"] = [@([wrappedSnapshot isWDFocused]) stringValue]; + + NSDictionary *attributeBlocks = @{ + @"frame": ^{ + return NSStringFromCGRect(wrappedSnapshot.wdFrame); + }, + @"enabled": ^{ + return [@([wrappedSnapshot isWDEnabled]) stringValue]; + }, + @"visible": ^{ + return [@([wrappedSnapshot isWDVisible]) stringValue]; + }, + @"accessible": ^{ + return [@([wrappedSnapshot isWDAccessible]) stringValue]; + }, + @"focused": ^{ + return [@([wrappedSnapshot isWDFocused]) stringValue]; + } + }; + + for (NSString *key in attributeBlocks) { + if (excludedAttributes == nil || ![excludedAttributes containsObject:key]) { + NSString *value = ((NSString * (^)(void))attributeBlocks[key])(); + if ([key isEqualToString:@"frame"]) { + info[key] = value; + } else { + info[[NSString stringWithFormat:@"is%@", [key capitalizedString]]] = value; + } + } + } if (!recursive) { return info.copy; @@ -191,7 +222,9 @@ + (NSDictionary *)dictionaryForElement:(id)snapshot recursi if ([childElements count]) { info[@"children"] = [[NSMutableArray alloc] init]; for (id childSnapshot in childElements) { - [info[@"children"] addObject:[self dictionaryForElement:childSnapshot recursive:YES]]; + [info[@"children"] addObject:[self dictionaryForElement:childSnapshot + recursive:YES + excludedAttributes:excludedAttributes]]; } } return info; @@ -379,7 +412,9 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames id extractedElement = extractIssueProperty(issue, @"element"); id elementSnapshot = [extractedElement fb_takeSnapshot]; - NSDictionary *elementAttributes = elementSnapshot ? [self.class dictionaryForElement:elementSnapshot recursive:NO] : @{}; + NSDictionary *elementAttributes = elementSnapshot + ? [self.class dictionaryForElement:elementSnapshot recursive:NO excludedAttributes:nil] + : @{}; [resultArray addObject:@{ @"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"", diff --git a/WebDriverAgentLib/Commands/FBDebugCommands.m b/WebDriverAgentLib/Commands/FBDebugCommands.m index dc96958d0..c3f9a7816 100644 --- a/WebDriverAgentLib/Commands/FBDebugCommands.m +++ b/WebDriverAgentLib/Commands/FBDebugCommands.m @@ -54,7 +54,12 @@ + (NSArray *)routes withExcludedAttributes:excludedAttributes] withScope:sourceScope]]; } else if ([sourceType caseInsensitiveCompare:SOURCE_FORMAT_JSON] == NSOrderedSame) { - result = application.fb_tree; + NSString *excludedAttributesString = request.parameters[@"excluded_attributes"]; + NSSet *excludedAttributes = (excludedAttributesString == nil) + ? nil + : [NSSet setWithArray:[excludedAttributesString componentsSeparatedByString:@","]]; + + result = [application fb_tree:excludedAttributes]; } else if ([sourceType caseInsensitiveCompare:SOURCE_FORMAT_DESCRIPTION] == NSOrderedSame) { result = application.fb_descriptionRepresentation; } else { diff --git a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m index 15b906db7..794be2192 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m @@ -44,6 +44,13 @@ - (void)testApplicationTree XCTAssertNotNil(self.testedApplication.fb_accessibilityTree); } +- (void)testApplicationTreeAttributesFiltering +{ + NSDictionary *applicationTree = [self.testedApplication fb_tree:[NSSet setWithArray:@[@"visible"]]]; + XCTAssertNotNil(applicationTree); + XCTAssertNil([applicationTree objectForKey:@"isVisible"], @"'isVisible' key should not be present in the application tree"); +} + - (void)testDeactivateApplication { NSError *error; From a05bcf021ebf7b55f3b1c2f6e4242234f118132b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 11 Nov 2024 12:59:16 +0000 Subject: [PATCH 132/368] chore(release): 8.11.0 [skip ci] ## [8.11.0](https://github.com/appium/WebDriverAgent/compare/v8.10.1...v8.11.0) (2024-11-11) ### Features * Add support for excluded_attributes in JSON source hierarchy ([#953](https://github.com/appium/WebDriverAgent/issues/953)) ([6112223](https://github.com/appium/WebDriverAgent/commit/6112223b21026fae5545fe1b1433a09c67ff524b)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a2761854..d1af845b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.11.0](https://github.com/appium/WebDriverAgent/compare/v8.10.1...v8.11.0) (2024-11-11) + +### Features + +* Add support for excluded_attributes in JSON source hierarchy ([#953](https://github.com/appium/WebDriverAgent/issues/953)) ([6112223](https://github.com/appium/WebDriverAgent/commit/6112223b21026fae5545fe1b1433a09c67ff524b)) + ## [8.10.1](https://github.com/appium/WebDriverAgent/compare/v8.10.0...v8.10.1) (2024-11-10) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index f14279538..9fd975595 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.10.1 + 8.11.0 CFBundleSignature ???? CFBundleVersion - 8.10.1 + 8.11.0 NSPrincipalClass diff --git a/package.json b/package.json index 062531ae1..a678782cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.10.1", + "version": "8.11.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 021f34901866f4a7870914c00781b83bd0cbddc4 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 11 Nov 2024 09:25:23 -0800 Subject: [PATCH 133/368] chore: bump appium-ios-device (#955) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a678782cd..4798555e6 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "@appium/base-driver": "^9.0.0", "@appium/strongbox": "^0.x", "@appium/support": "^5.0.3", - "appium-ios-device": "^2.5.0", + "appium-ios-device": "^2.7.25", "appium-ios-simulator": "^6.0.0", "async-lock": "^1.0.0", "asyncbox": "^3.0.0", From 024b7c066b43fff3d5ee462d5ca386e497ca661e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 11 Nov 2024 17:33:31 +0000 Subject: [PATCH 134/368] chore(release): 8.11.1 [skip ci] ## [8.11.1](https://github.com/appium/WebDriverAgent/compare/v8.11.0...v8.11.1) (2024-11-11) ### Miscellaneous Chores * bump appium-ios-device ([#955](https://github.com/appium/WebDriverAgent/issues/955)) ([021f349](https://github.com/appium/WebDriverAgent/commit/021f34901866f4a7870914c00781b83bd0cbddc4)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1af845b2..1a56783d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.11.1](https://github.com/appium/WebDriverAgent/compare/v8.11.0...v8.11.1) (2024-11-11) + +### Miscellaneous Chores + +* bump appium-ios-device ([#955](https://github.com/appium/WebDriverAgent/issues/955)) ([021f349](https://github.com/appium/WebDriverAgent/commit/021f34901866f4a7870914c00781b83bd0cbddc4)) + ## [8.11.0](https://github.com/appium/WebDriverAgent/compare/v8.10.1...v8.11.0) (2024-11-11) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 9fd975595..ead3f644e 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.11.0 + 8.11.1 CFBundleSignature ???? CFBundleVersion - 8.11.0 + 8.11.1 NSPrincipalClass diff --git a/package.json b/package.json index 4798555e6..a06baeeeb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.11.0", + "version": "8.11.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 2e9be570db20ad38270e175ccaffdaa58ffe198e Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 12 Nov 2024 08:29:16 -0800 Subject: [PATCH 135/368] ci: use proper host os (#956) --- .github/workflows/functional-test.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index 4e51234c4..61b23bdd2 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -12,18 +12,21 @@ jobs: fail-fast: false matrix: test_targets: - - XCODE_VERSION: '16.0.0' + - HOST_OS: 'macos-15' + XCODE_VERSION: '16.0.0' IOS_VERSION: '18.0' - IOS_MODEL: iPhone 15 Plus - - XCODE_VERSION: '15.3' + IOS_MODEL: iPhone 16 Plus + - HOST_OS: 'macos-14' + XCODE_VERSION: '15.3' IOS_VERSION: '17.4' IOS_MODEL: iPhone 15 Plus - - XCODE_VERSION: 14.3.1 + - HOST_OS: 'macos-13' + XCODE_VERSION: 14.3.1 IOS_VERSION: '16.4' IOS_MODEL: iPhone 14 Plus # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md - runs-on: macos-14 + runs-on: ${{matrix.test_targets.HOST_OS}} steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 From 5b4af690043216c9c2bf51ba4320f1e93e2ea670 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 23 Nov 2024 10:40:11 -0800 Subject: [PATCH 136/368] ci: run with Xcode 16.1.0 (#950) * ci: run with Xcode 16.1.0 as well * Update functional-test.yml * use maco 13 for xcode 14.3.1 --- .azure-pipelines.yml | 2 +- .github/workflows/functional-test.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 89887d258..eca3f55cf 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -1,6 +1,6 @@ # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml variables: - MIN_VM_IMAGE: macOS-14 + MIN_VM_IMAGE: macOS-13 MIN_XCODE_VERSION: 14.3.1 MIN_PLATFORM_VERSION: 16.4 MIN_TV_PLATFORM_VERSION: 16.4 diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index 61b23bdd2..b8c9855aa 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -13,8 +13,8 @@ jobs: matrix: test_targets: - HOST_OS: 'macos-15' - XCODE_VERSION: '16.0.0' - IOS_VERSION: '18.0' + XCODE_VERSION: '16.1.0' + IOS_VERSION: '18.1' IOS_MODEL: iPhone 16 Plus - HOST_OS: 'macos-14' XCODE_VERSION: '15.3' From 55b49c83581c9e88f70806d98015238de3104f19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:58:18 -0800 Subject: [PATCH 137/368] chore(deps-dev): bump mocha from 10.8.2 to 11.0.1 (#959) Bumps [mocha](https://github.com/mochajs/mocha) from 10.8.2 to 11.0.1. - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/main/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v10.8.2...v11.0.1) --- updated-dependencies: - dependency-name: mocha 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 a06baeeeb..8c9386971 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "chai-as-promised": "^8.0.0", "conventional-changelog-conventionalcommits": "^8.0.0", "node-simctl": "^7.0.1", - "mocha": "^10.0.0", + "mocha": "^11.0.1", "prettier": "^3.0.0", "semantic-release": "^24.0.0", "semver": "^7.3.7", From 593bb0381a70ff1c25fa35092d0e9fe0cb4db066 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 3 Dec 2024 20:01:04 +0000 Subject: [PATCH 138/368] chore(release): 8.11.2 [skip ci] ## [8.11.2](https://github.com/appium/WebDriverAgent/compare/v8.11.1...v8.11.2) (2024-12-03) ### Miscellaneous Chores * **deps-dev:** bump mocha from 10.8.2 to 11.0.1 ([#959](https://github.com/appium/WebDriverAgent/issues/959)) ([55b49c8](https://github.com/appium/WebDriverAgent/commit/55b49c83581c9e88f70806d98015238de3104f19)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a56783d3..4ad29b2da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.11.2](https://github.com/appium/WebDriverAgent/compare/v8.11.1...v8.11.2) (2024-12-03) + +### Miscellaneous Chores + +* **deps-dev:** bump mocha from 10.8.2 to 11.0.1 ([#959](https://github.com/appium/WebDriverAgent/issues/959)) ([55b49c8](https://github.com/appium/WebDriverAgent/commit/55b49c83581c9e88f70806d98015238de3104f19)) + ## [8.11.1](https://github.com/appium/WebDriverAgent/compare/v8.11.0...v8.11.1) (2024-11-11) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index ead3f644e..ebf8f6cf9 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.11.1 + 8.11.2 CFBundleSignature ???? CFBundleVersion - 8.11.1 + 8.11.2 NSPrincipalClass diff --git a/package.json b/package.json index 8c9386971..2c3d71bc0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.11.1", + "version": "8.11.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From dbeb09c89f8c02e00a7bdffe7899650d435f3575 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 13:28:13 +0100 Subject: [PATCH 139/368] chore(deps): bump @appium/support from 5.1.8 to 6.0.0 (#960) Bumps [@appium/support](https://github.com/appium/appium/tree/HEAD/packages/support) from 5.1.8 to 6.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@6.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 2c3d71bc0..32d3111b1 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "dependencies": { "@appium/base-driver": "^9.0.0", "@appium/strongbox": "^0.x", - "@appium/support": "^5.0.3", + "@appium/support": "^6.0.0", "appium-ios-device": "^2.7.25", "appium-ios-simulator": "^6.0.0", "async-lock": "^1.0.0", From deb8ecabc52571e8004bcb2b804b9f7e43fad944 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 6 Dec 2024 12:30:49 +0000 Subject: [PATCH 140/368] chore(release): 8.11.3 [skip ci] ## [8.11.3](https://github.com/appium/WebDriverAgent/compare/v8.11.2...v8.11.3) (2024-12-06) ### Miscellaneous Chores * **deps:** bump @appium/support from 5.1.8 to 6.0.0 ([#960](https://github.com/appium/WebDriverAgent/issues/960)) ([dbeb09c](https://github.com/appium/WebDriverAgent/commit/dbeb09c89f8c02e00a7bdffe7899650d435f3575)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ad29b2da..478d31819 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.11.3](https://github.com/appium/WebDriverAgent/compare/v8.11.2...v8.11.3) (2024-12-06) + +### Miscellaneous Chores + +* **deps:** bump @appium/support from 5.1.8 to 6.0.0 ([#960](https://github.com/appium/WebDriverAgent/issues/960)) ([dbeb09c](https://github.com/appium/WebDriverAgent/commit/dbeb09c89f8c02e00a7bdffe7899650d435f3575)) + ## [8.11.2](https://github.com/appium/WebDriverAgent/compare/v8.11.1...v8.11.2) (2024-12-03) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index ebf8f6cf9..f100c34c0 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.11.2 + 8.11.3 CFBundleSignature ???? CFBundleVersion - 8.11.2 + 8.11.3 NSPrincipalClass diff --git a/package.json b/package.json index 32d3111b1..9df01f49b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.11.2", + "version": "8.11.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 916c8c557a9366608df211f33b5b7fbb0354dad3 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 13 Dec 2024 11:03:11 -0800 Subject: [PATCH 141/368] feat: look for critical notification in respectSystemAlerts (#962) * feat: look for critical notification in respectSystemAlerts * use IN * Update FBSession.m * Use NotificationShortLookView instead as identifier --- WebDriverAgentLib/Routing/FBSession.m | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index a4460b4a8..e8fb95a18 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -178,10 +178,13 @@ - (XCUIApplication *)activeApplication if (nil != self.testedApplication) { XCUIApplicationState testedAppState = self.testedApplication.state; if (testedAppState >= XCUIApplicationStateRunningForeground) { - // We look for `SBTransientOverlayWindow` elements for half modals. See https://github.com/appium/WebDriverAgent/pull/946 - NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"%K == %@ OR %K == %@", + NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"%K == %@ OR %K IN {%@, %@}", @"elementType", @(XCUIElementTypeAlert), - @"identifier", @"SBTransientOverlayWindow"]; + // To look for `SBTransientOverlayWindow` elements. See https://github.com/appium/WebDriverAgent/pull/946 + @"identifier", @"SBTransientOverlayWindow", + // To look for 'criticalAlertSetting' elements https://developer.apple.com/documentation/usernotifications/unnotificationsettings/criticalalertsetting + // See https://github.com/appium/appium/issues/20835 + @"NotificationShortLookView"]; if ([FBConfiguration shouldRespectSystemAlerts] && [[XCUIApplication.fb_systemApplication descendantsMatchingType:XCUIElementTypeAny] matchingPredicate:searchPredicate].count > 0) { From 9734b83f7a228d09566e73c25058432e8e083e50 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 13 Dec 2024 19:08:26 +0000 Subject: [PATCH 142/368] chore(release): 8.12.0 [skip ci] ## [8.12.0](https://github.com/appium/WebDriverAgent/compare/v8.11.3...v8.12.0) (2024-12-13) ### Features * look for critical notification in respectSystemAlerts ([#962](https://github.com/appium/WebDriverAgent/issues/962)) ([916c8c5](https://github.com/appium/WebDriverAgent/commit/916c8c557a9366608df211f33b5b7fbb0354dad3)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 478d31819..963a3763a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.12.0](https://github.com/appium/WebDriverAgent/compare/v8.11.3...v8.12.0) (2024-12-13) + +### Features + +* look for critical notification in respectSystemAlerts ([#962](https://github.com/appium/WebDriverAgent/issues/962)) ([916c8c5](https://github.com/appium/WebDriverAgent/commit/916c8c557a9366608df211f33b5b7fbb0354dad3)) + ## [8.11.3](https://github.com/appium/WebDriverAgent/compare/v8.11.2...v8.11.3) (2024-12-06) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index f100c34c0..0998ccfbb 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.11.3 + 8.12.0 CFBundleSignature ???? CFBundleVersion - 8.11.3 + 8.12.0 NSPrincipalClass diff --git a/package.json b/package.json index 9df01f49b..55dfe122e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.11.3", + "version": "8.12.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 17f49ec5a54e97b0ef0d20a3e39fc96b32575e43 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 3 Jan 2025 17:34:51 +0100 Subject: [PATCH 143/368] chore: Bump eslint (#965) --- .eslintignore | 3 --- .eslintrc.json | 29 --------------------- Scripts/build-webdriveragent.js | 2 +- Scripts/fetch-prebuilt-wda.js | 2 +- eslint.config.mjs | 13 +++++++++ lib/check-dependencies.js | 5 ++-- lib/utils.js | 6 ++--- lib/webdriveragent.js | 4 +-- package.json | 2 +- test/functional/helpers/simulator.js | 4 +-- test/functional/webdriveragent-e2e-specs.js | 6 ++--- 11 files changed, 28 insertions(+), 48 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.json create mode 100644 eslint.config.mjs diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 84930aead..000000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -Resources -coverage -build diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 3d7db0846..000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "extends": ["@appium/eslint-config-appium-ts"], - "overrides": [ - { - "files": "test/**/*.js", - "rules": { - "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/Scripts/build-webdriveragent.js b/Scripts/build-webdriveragent.js index 1958b876d..b37bcbbc9 100644 --- a/Scripts/build-webdriveragent.js +++ b/Scripts/build-webdriveragent.js @@ -34,7 +34,7 @@ async function buildWebDriverAgent (xcodeVersion) { await exec('xcodebuild', ['clean', '-derivedDataPath', DERIVED_DATA_PATH, '-scheme', 'WebDriverAgentRunner'], { cwd: ROOT_DIR }); - } catch (ign) {} + } catch {} // Get Xcode version xcodeVersion = xcodeVersion || await xcode.getVersion(); diff --git a/Scripts/fetch-prebuilt-wda.js b/Scripts/fetch-prebuilt-wda.js index 8bedd9a3d..4bd6840fa 100644 --- a/Scripts/fetch-prebuilt-wda.js +++ b/Scripts/fetch-prebuilt-wda.js @@ -47,7 +47,7 @@ async function fetchPrebuiltWebDriverAgentAssets () { try { const nameOfAgent = _.last(url.split('/')); agentsDownloading.push(downloadAgent(url, path.join(webdriveragentsDir, nameOfAgent))); - } catch (ign) { } + } catch { } } // Wait for them all to finish diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..020f8c2d2 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,13 @@ +import appiumConfig from '@appium/eslint-config-appium-ts'; + +export default [ + ...appiumConfig, + { + ignores: [ + 'Configurations/**', + 'Fastlane/**', + 'PrivateHeaders/**', + 'WebDriverAgent*/**' + ], + }, +]; diff --git a/lib/check-dependencies.js b/lib/check-dependencies.js index 21c68de60..49903671d 100644 --- a/lib/check-dependencies.js +++ b/lib/check-dependencies.js @@ -2,8 +2,8 @@ import { fs } from '@appium/support'; import _ from 'lodash'; import { exec } from 'teen_process'; import path from 'path'; -import XcodeBuild from './xcodebuild'; -import xcode from 'appium-xcode'; +import {XcodeBuild} from './xcodebuild'; +import * as xcode from 'appium-xcode'; import { WDA_SCHEME, SDK_SIMULATOR, WDA_RUNNER_APP } from './constants'; @@ -22,7 +22,6 @@ async function buildWDASim () { await exec('xcodebuild', args); } -// eslint-disable-next-line require-await export async function checkForDependencies () { log.debug('Dependencies are up to date'); return false; diff --git a/lib/utils.js b/lib/utils.js index f8e7007c1..77ca8f53a 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -27,7 +27,7 @@ const getModuleRoot = _.memoize(function getModuleRoot () { JSON.parse(_fs.readFileSync(manifestPath, 'utf8')).name === 'appium-webdriveragent') { return currentDir; } - } catch (ign) {} + } catch {} currentDir = path.dirname(currentDir); isAtFsRoot = currentDir.length <= path.dirname(currentDir).length; } @@ -86,7 +86,7 @@ async function killAppUsingPattern (pgrepPattern) { intervalMs: 100, }); return; - } catch (ign) { + } catch { // try the next signal } } @@ -121,7 +121,7 @@ async function updateProjectFile (agentPath, newBundleId) { try { // Assuming projectFilePath is in the correct state, create .old from projectFilePath await fs.copyFile(projectFilePath, `${projectFilePath}.old`); - await replaceInFile(projectFilePath, new RegExp(_.escapeRegExp(WDA_RUNNER_BUNDLE_ID), 'g'), newBundleId); // eslint-disable-line no-useless-escape + await replaceInFile(projectFilePath, new RegExp(_.escapeRegExp(WDA_RUNNER_BUNDLE_ID), 'g'), newBundleId); log.debug(`Successfully updated '${projectFilePath}' with bundle id '${newBundleId}'`); } catch (err) { log.debug(`Error updating project file: ${err.message}`); diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index f5cda7ee3..e47b9c752 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -10,7 +10,7 @@ import { NoSessionProxy } from './no-session-proxy'; import { getWDAUpgradeTimestamp, resetTestProcesses, getPIDsListeningOnPort, BOOTSTRAP_PATH } from './utils'; -import XcodeBuild from './xcodebuild'; +import {XcodeBuild} from './xcodebuild'; import AsyncLock from 'async-lock'; import { exec } from 'teen_process'; import { bundleWDASim } from './check-dependencies'; @@ -417,7 +417,7 @@ export class WebDriverAgent { let status; try { status = await this.getStatus(this.wdaLaunchTimeout); - } catch (err) { + } catch { throw new Error( `Failed to start the preinstalled WebDriverAgent in ${this.wdaLaunchTimeout} ms. ` + `The WebDriverAgent might not be properly built or the device might be locked. ` + diff --git a/package.json b/package.json index 55dfe122e..b1c5ad616 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ }, "homepage": "https://github.com/appium/WebDriverAgent#readme", "devDependencies": { - "@appium/eslint-config-appium-ts": "^0.x", + "@appium/eslint-config-appium-ts": "^1.0.0", "@appium/test-support": "^3.0.0", "@appium/tsconfig": "^0.x", "@appium/types": "^0.x", diff --git a/test/functional/helpers/simulator.js b/test/functional/helpers/simulator.js index 4dd7359df..f315f2035 100644 --- a/test/functional/helpers/simulator.js +++ b/test/functional/helpers/simulator.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import Simctl from 'node-simctl'; +import { Simctl } from 'node-simctl'; import { retryInterval } from 'asyncbox'; import { killAllSimulators as simKill } from 'appium-ios-simulator'; import { resetTestProcesses } from '../../../lib/utils'; @@ -34,7 +34,7 @@ async function deleteDeviceWithRetry (udid) { const simctl = new Simctl({udid}); try { await retryInterval(10, 1000, simctl.deleteDevice.bind(simctl)); - } catch (ign) {} + } catch {} } diff --git a/test/functional/webdriveragent-e2e-specs.js b/test/functional/webdriveragent-e2e-specs.js index 3cf2862f1..bb1ce67c9 100644 --- a/test/functional/webdriveragent-e2e-specs.js +++ b/test/functional/webdriveragent-e2e-specs.js @@ -1,4 +1,4 @@ -import Simctl from 'node-simctl'; +import { Simctl } from 'node-simctl'; import { getVersion } from 'appium-xcode'; import { getSimulator } from 'appium-ios-simulator'; import { killAllSimulators, shutdownSimulator } from './helpers/simulator'; @@ -89,7 +89,7 @@ describe('WebDriverAgent', function () { await retryInterval(5, 1000, async function () { await shutdownSimulator(device); }); - } catch (ign) {} + } catch {} }); it('should launch agent on a sim', async function () { @@ -106,7 +106,7 @@ describe('WebDriverAgent', function () { const agent = new WebDriverAgent(xcodeVersion, getStartOpts(device)); - agent.xcodebuild.createSubProcess = async function () { // eslint-disable-line require-await + agent.xcodebuild.createSubProcess = async function () { let args = [ '-workspace', `${this.agentPath}dfgs`, From a1b5af60d5257850dac989dff3fdce2ec459efcd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 3 Jan 2025 16:37:36 +0000 Subject: [PATCH 144/368] chore(release): 8.12.1 [skip ci] ## [8.12.1](https://github.com/appium/WebDriverAgent/compare/v8.12.0...v8.12.1) (2025-01-03) ### Miscellaneous Chores * Bump eslint ([#965](https://github.com/appium/WebDriverAgent/issues/965)) ([17f49ec](https://github.com/appium/WebDriverAgent/commit/17f49ec5a54e97b0ef0d20a3e39fc96b32575e43)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 963a3763a..d35fd58bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.12.1](https://github.com/appium/WebDriverAgent/compare/v8.12.0...v8.12.1) (2025-01-03) + +### Miscellaneous Chores + +* Bump eslint ([#965](https://github.com/appium/WebDriverAgent/issues/965)) ([17f49ec](https://github.com/appium/WebDriverAgent/commit/17f49ec5a54e97b0ef0d20a3e39fc96b32575e43)) + ## [8.12.0](https://github.com/appium/WebDriverAgent/compare/v8.11.3...v8.12.0) (2024-12-13) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 0998ccfbb..3f9b91d92 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.12.0 + 8.12.1 CFBundleSignature ???? CFBundleVersion - 8.12.0 + 8.12.1 NSPrincipalClass diff --git a/package.json b/package.json index b1c5ad616..6bddce650 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.12.0", + "version": "8.12.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From f62afc372c123bdd8dd7bb493f653bb128144d24 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 13 Jan 2025 08:34:09 +0100 Subject: [PATCH 145/368] chore: Exclude element visibility and accessibility info from the accessibility audit details (#968) --- .../Categories/XCUIApplication+FBHelpers.m | 64 +++++++++++++++---- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 6cdae945b..2672e3272 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -40,6 +40,13 @@ static NSString* const FBUnknownBundleId = @"unknown"; +static NSString* const FBExclusionAttributeFrame = @"frame"; +static NSString* const FBExclusionAttributeEnabled = @"enabled"; +static NSString* const FBExclusionAttributeVisible = @"visible"; +static NSString* const FBExclusionAttributeAccessible = @"accessible"; +static NSString* const FBExclusionAttributeFocused = @"focused"; + + _Nullable id extractIssueProperty(id issue, NSString *propertyName) { SEL selector = NSSelectorFromString(propertyName); NSMethodSignature *methodSignature = [issue methodSignatureForSelector:selector]; @@ -88,6 +95,17 @@ _Nullable id extractIssueProperty(id issue, NSString *propertyName) { return result; } +NSDictionary *customExclusionAttributesMap(void) { + static dispatch_once_t onceToken; + static NSDictionary *result; + dispatch_once(&onceToken, ^{ + result = @{ + FBExclusionAttributeVisible: FB_XCAXAIsVisibleAttributeName, + FBExclusionAttributeAccessible: FB_XCAXAIsElementAttributeName, + }; + }); + return result; +} @implementation XCUIApplication (FBHelpers) @@ -156,12 +174,26 @@ - (NSDictionary *)fb_tree return [self fb_tree:nil]; } -- (NSDictionary *)fb_tree:(nullable NSSet *) excludedAttributes +- (NSDictionary *)fb_tree:(nullable NSSet *)excludedAttributes { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : [self fb_snapshotWithAllAttributesAndMaxDepth:nil]; - return [self.class dictionaryForElement:snapshot recursive:YES excludedAttributes:excludedAttributes]; + // This set includes XCTest-specific internal attribute names, + // while the `excludedAttributes` arg contains human-readable ones + NSMutableSet* includedAttributeNames = [NSMutableSet setWithArray:FBCustomAttributeNames()]; + [includedAttributeNames addObjectsFromArray:FBStandardAttributeNames()]; + if (nil != excludedAttributes) { + for (NSString *attr in excludedAttributes) { + NSString *mappedName = [customExclusionAttributesMap() objectForKey:attr]; + if (nil != mappedName) { + [includedAttributeNames removeObject:attr]; + } + } + } + id snapshot = nil == excludedAttributes + ? [self fb_snapshotWithAllAttributesAndMaxDepth:nil] + : [self fb_snapshotWithAttributes:[includedAttributeNames allObjects] maxDepth:nil]; + return [self.class dictionaryForElement:snapshot + recursive:YES + excludedAttributes:excludedAttributes]; } - (NSDictionary *)fb_accessibilityTree @@ -174,7 +206,7 @@ - (NSDictionary *)fb_accessibilityTree + (NSDictionary *)dictionaryForElement:(id)snapshot recursive:(BOOL)recursive - excludedAttributes:(nullable NSSet *) excludedAttributes + excludedAttributes:(nullable NSSet *)excludedAttributes { NSMutableDictionary *info = [[NSMutableDictionary alloc] init]; info[@"type"] = [FBElementTypeTransformer shortStringWithElementType:snapshot.elementType]; @@ -186,19 +218,19 @@ + (NSDictionary *)dictionaryForElement:(id)snapshot info[@"rect"] = wrappedSnapshot.wdRect; NSDictionary *attributeBlocks = @{ - @"frame": ^{ + FBExclusionAttributeFrame: ^{ return NSStringFromCGRect(wrappedSnapshot.wdFrame); }, - @"enabled": ^{ + FBExclusionAttributeEnabled: ^{ return [@([wrappedSnapshot isWDEnabled]) stringValue]; }, - @"visible": ^{ + FBExclusionAttributeVisible: ^{ return [@([wrappedSnapshot isWDVisible]) stringValue]; }, - @"accessible": ^{ + FBExclusionAttributeAccessible: ^{ return [@([wrappedSnapshot isWDAccessible]) stringValue]; }, - @"focused": ^{ + FBExclusionAttributeFocused: ^{ return [@([wrappedSnapshot isWDFocused]) stringValue]; } }; @@ -206,7 +238,7 @@ + (NSDictionary *)dictionaryForElement:(id)snapshot for (NSString *key in attributeBlocks) { if (excludedAttributes == nil || ![excludedAttributes containsObject:key]) { NSString *value = ((NSString * (^)(void))attributeBlocks[key])(); - if ([key isEqualToString:@"frame"]) { + if ([key isEqualToString:FBExclusionAttributeFrame]) { info[key] = value; } else { info[[NSString stringWithFormat:@"is%@", [key capitalizedString]]] = value; @@ -396,6 +428,8 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames return nil; } + // These custom attributes could take too long to fetch, thus excluded + NSSet *customAttributesToExclude = [NSSet setWithArray:[customExclusionAttributesMap() allKeys]]; NSMutableArray *resultArray = [NSMutableArray array]; NSMethodSignature *methodSignature = [self methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; @@ -411,9 +445,11 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames id extractedElement = extractIssueProperty(issue, @"element"); - id elementSnapshot = [extractedElement fb_takeSnapshot]; + id elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_takeSnapshot]; NSDictionary *elementAttributes = elementSnapshot - ? [self.class dictionaryForElement:elementSnapshot recursive:NO excludedAttributes:nil] + ? [self.class dictionaryForElement:elementSnapshot + recursive:NO + excludedAttributes:customAttributesToExclude] : @{}; [resultArray addObject:@{ From 194ddf1d75e9bc2fb741088b801fdf4ff87d099b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 13 Jan 2025 07:39:09 +0000 Subject: [PATCH 146/368] chore(release): 8.12.2 [skip ci] ## [8.12.2](https://github.com/appium/WebDriverAgent/compare/v8.12.1...v8.12.2) (2025-01-13) ### Miscellaneous Chores * Exclude element visibility and accessibility info from the accessibility audit details ([#968](https://github.com/appium/WebDriverAgent/issues/968)) ([f62afc3](https://github.com/appium/WebDriverAgent/commit/f62afc372c123bdd8dd7bb493f653bb128144d24)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d35fd58bc..7fe42c710 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.12.2](https://github.com/appium/WebDriverAgent/compare/v8.12.1...v8.12.2) (2025-01-13) + +### Miscellaneous Chores + +* Exclude element visibility and accessibility info from the accessibility audit details ([#968](https://github.com/appium/WebDriverAgent/issues/968)) ([f62afc3](https://github.com/appium/WebDriverAgent/commit/f62afc372c123bdd8dd7bb493f653bb128144d24)) + ## [8.12.1](https://github.com/appium/WebDriverAgent/compare/v8.12.0...v8.12.1) (2025-01-03) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 3f9b91d92..f263b2ad8 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.12.1 + 8.12.2 CFBundleSignature ???? CFBundleVersion - 8.12.1 + 8.12.2 NSPrincipalClass diff --git a/package.json b/package.json index 6bddce650..4134f04db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.12.1", + "version": "8.12.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From eca2ed1e4fd0b5a1d31ac305603b6b06faeb8a7d Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Tue, 14 Jan 2025 14:43:55 -0800 Subject: [PATCH 147/368] ci: lock Ruby version to 3.3 (#971) --- azure-templates/bootstrap_steps.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-templates/bootstrap_steps.yml b/azure-templates/bootstrap_steps.yml index 6c96e9ead..14c127e11 100644 --- a/azure-templates/bootstrap_steps.yml +++ b/azure-templates/bootstrap_steps.yml @@ -3,5 +3,5 @@ steps: - script: mkdir -p ./Resources/WebDriverAgent.bundle - task: UseRubyVersion@0 inputs: - versionSpec: '3' + versionSpec: '3.3' addToPath: true From 08f13060119c710f53b34a98c95683287c0365a0 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 16 Jan 2025 17:44:20 +0100 Subject: [PATCH 148/368] feat: Refactor snapshotting mechanism (#970) BREAKING CHANGE: snapshotTimeout and customSnapshotTimeout settings have been removed as a result of the custom snapshotting logic removal --- .../XCTestManager_ManagerInterface-Protocol.h | 1 + WebDriverAgent.xcodeproj/project.pbxproj | 12 ++ .../FBXCElementSnapshotWrapper+Helpers.h | 13 +- .../FBXCElementSnapshotWrapper+Helpers.m | 38 ++-- .../Categories/XCUIApplication+FBAlert.m | 4 +- .../Categories/XCUIApplication+FBHelpers.m | 24 +-- .../Categories/XCUIElement+FBAccessibility.m | 19 +- .../Categories/XCUIElement+FBCaching.h | 3 - .../Categories/XCUIElement+FBCaching.m | 23 +- .../Categories/XCUIElement+FBFind.m | 2 +- .../Categories/XCUIElement+FBIsVisible.m | 201 +++--------------- .../Categories/XCUIElement+FBPickerWheel.m | 4 +- .../Categories/XCUIElement+FBScrolling.m | 63 +++--- .../Categories/XCUIElement+FBTyping.m | 12 +- .../Categories/XCUIElement+FBUID.m | 4 +- .../Categories/XCUIElement+FBUtilities.h | 39 +--- .../Categories/XCUIElement+FBUtilities.m | 78 +------ .../Categories/XCUIElement+FBVisibleFrame.h | 36 ++++ .../Categories/XCUIElement+FBVisibleFrame.m | 53 +++++ .../XCUIElement+FBWebDriverAttributes.m | 27 +-- WebDriverAgentLib/Commands/FBCustomCommands.m | 3 +- .../Commands/FBElementCommands.m | 72 +++---- .../Commands/FBFindElementCommands.m | 19 +- .../Commands/FBSessionCommands.m | 8 - WebDriverAgentLib/FBAlert.m | 11 +- WebDriverAgentLib/Routing/FBElementCache.h | 14 +- WebDriverAgentLib/Routing/FBElementCache.m | 37 +--- WebDriverAgentLib/Routing/FBResponsePayload.m | 8 +- WebDriverAgentLib/Utilities/FBConfiguration.h | 8 - WebDriverAgentLib/Utilities/FBConfiguration.m | 12 -- WebDriverAgentLib/Utilities/FBSettings.h | 3 - WebDriverAgentLib/Utilities/FBSettings.m | 2 - .../Utilities/FBTVNavigationTracker.m | 4 +- .../Utilities/FBW3CActionsSynthesizer.m | 2 +- .../Utilities/FBXCAXClientProxy.h | 7 +- .../Utilities/FBXCAXClientProxy.m | 18 +- .../Utilities/FBXCodeCompatibility.h | 4 +- .../Utilities/FBXCodeCompatibility.m | 4 +- WebDriverAgentLib/Utilities/FBXPath.m | 5 +- .../Utilities/XCTestPrivateSymbols.h | 3 + .../Utilities/XCTestPrivateSymbols.m | 1 + .../FBElementAttributeTests.m | 3 +- .../IntegrationTests/FBElementSwipingTests.m | 2 +- .../FBW3CTouchActionsIntegrationTests.m | 2 +- .../FBXPathIntegrationTests.m | 4 +- .../XCElementSnapshotHelperTests.m | 31 ++- .../XCElementSnapshotHitPointTests.m | 2 +- .../XCUIElementHelperIntegrationTests.m | 8 +- .../Doubles/XCElementSnapshotDouble.m | 10 + .../UnitTests/Doubles/XCUIElementDouble.h | 3 +- .../UnitTests/Doubles/XCUIElementDouble.m | 2 +- .../UnitTests/FBElementCacheTests.m | 2 - .../Doubles/XCUIElementDouble.h | 1 - 53 files changed, 350 insertions(+), 621 deletions(-) create mode 100644 WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h create mode 100644 WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m diff --git a/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h b/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h index 8ed03ebf7..d68f25c17 100644 --- a/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +++ b/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h @@ -27,6 +27,7 @@ - (void)_XCT_requestElementAtPoint:(CGPoint)arg1 reply:(void (^)(id/*XCAccessibilityElement*/, NSError *))arg2; - (void)_XCT_fetchParameterizedAttributeForElement:(id/*XCAccessibilityElement*/)arg1 attributes:(NSNumber *)arg2 parameter:(id)arg3 reply:(void (^)(id, NSError *))arg4; - (void)_XCT_setAttribute:(NSNumber *)arg1 value:(id)arg2 element:(id/*XCAccessibilityElement*/)arg3 reply:(void (^)(BOOL, NSError *))arg4; +- (void)_XCT_fetchAttributes:(id)attributes forElement:(id)element reply:(void (^)(NSDictionary *, NSError *))reply; - (void)_XCT_fetchAttributesForElement:(id/*XCAccessibilityElement*/)arg1 attributes:(NSArray *)arg2 reply:(void (^)(NSDictionary *, NSError *))arg3; - (void)_XCT_terminateApplicationWithBundleID:(NSString *)arg1 completion:(void (^)(NSError *))arg2; - (void)_XCT_performAccessibilityAction:(int)arg1 onElement:(id/*XCAccessibilityElement*/)arg2 withValue:(id)arg3 reply:(void (^)(NSError *))arg4; diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index db4465848..2fd346017 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -451,6 +451,10 @@ 71A7EAFA1E224648001DA4F2 /* FBClassChainQueryParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A7EAF81E224648001DA4F2 /* FBClassChainQueryParser.m */; }; 71A7EAFC1E229302001DA4F2 /* FBClassChainTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A7EAFB1E229302001DA4F2 /* FBClassChainTests.m */; }; 71ACF5B8242F2FDC00F0AAD4 /* FBSafariAlertTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71ACF5B7242F2FDC00F0AAD4 /* FBSafariAlertTests.m */; }; + 71AE3CF72D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */; }; + 71AE3CF82D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 71AE3CF62D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m */; }; + 71AE3CF92D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */; }; + 71AE3CFA2D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 71AE3CF62D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.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 */; }; 71B155DF23080CA600646AFB /* FBProtocolHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155DD23080CA600646AFB /* FBProtocolHelpers.h */; }; @@ -1050,6 +1054,8 @@ 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 = ""; }; 71ACF5B7242F2FDC00F0AAD4 /* FBSafariAlertTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSafariAlertTests.m; sourceTree = ""; }; + 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBVisibleFrame.h"; sourceTree = ""; }; + 71AE3CF62D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBVisibleFrame.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 = ""; }; 71B155DD23080CA600646AFB /* FBProtocolHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBProtocolHelpers.h; sourceTree = ""; }; @@ -1781,6 +1787,8 @@ 71B49EC61ED1A58100D51AD6 /* XCUIElement+FBUID.m */, EEE3763F1D59F81400ED88DD /* XCUIElement+FBUtilities.h */, EEE376401D59F81400ED88DD /* XCUIElement+FBUtilities.m */, + 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */, + 71AE3CF62D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m */, EEE376471D59FAE900ED88DD /* XCUIElement+FBWebDriverAttributes.h */, EEE376481D59FAE900ED88DD /* XCUIElement+FBWebDriverAttributes.m */, 641EE7042240CDCF00173FCB /* XCUIElement+FBTVFocuse.h */, @@ -2399,6 +2407,7 @@ 641EE6A42240C5CA00173FCB /* FBCommandHandler.h in Headers */, 641EE6A52240C5CA00173FCB /* FBSessionCommands.h in Headers */, 641EE70C2240CE2D00173FCB /* FBTVNavigationTracker.h in Headers */, + 71AE3CF72D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h in Headers */, 641EE6A62240C5CA00173FCB /* FBImageProcessor.h in Headers */, 641EE6A72240C5CA00173FCB /* FBSession-Private.h in Headers */, 641EE6A82240C5CA00173FCB /* NSString+FBXMLSafeString.h in Headers */, @@ -2585,6 +2594,7 @@ 714EAA0D2673FDFE005C5B47 /* FBCapabilities.h in Headers */, EE35AD5C1E3B77D600A02D78 /* XCTNSPredicateExpectation.h in Headers */, EE35AD521E3B77D600A02D78 /* XCTestObservationCenter.h in Headers */, + 71AE3CF92D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h in Headers */, EE35AD5B1E3B77D600A02D78 /* XCTNSNotificationExpectation.h in Headers */, E444DC97249131D40060D7EB /* HTTPServer.h in Headers */, E444DCAE24913C220060D7EB /* HTTPResponseProxy.h in Headers */, @@ -3160,6 +3170,7 @@ 641EE60E2240C5CA00173FCB /* XCUIElement+FBTyping.m in Sources */, 641EE60F2240C5CA00173FCB /* XCUIElement+FBAccessibility.m in Sources */, 641EE6102240C5CA00173FCB /* FBImageUtils.m in Sources */, + 71AE3CF82D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */, 641EE6112240C5CA00173FCB /* FBSession.m in Sources */, 641EE6122240C5CA00173FCB /* FBFindElementCommands.m in Sources */, 71A5C67629A4F39600421C37 /* XCTIssue+FBPatcher.m in Sources */, @@ -3232,6 +3243,7 @@ 713AE576243A53BE0000D657 /* FBW3CActionsHelpers.m in Sources */, 71B155E123080CA600646AFB /* FBProtocolHelpers.m in Sources */, EE158AB11CBD456F00A3E3F0 /* XCUIElement+FBIsVisible.m in Sources */, + 71AE3CFA2D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */, EEBBD48C1D47746D00656A81 /* XCUIElement+FBFind.m in Sources */, EE158ADD1CBD456F00A3E3F0 /* FBResponsePayload.m in Sources */, E444DCB524913C220060D7EB /* RouteRequest.m in Sources */, diff --git a/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.h b/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.h index 4ce84f88b..a4ebdcaea 100644 --- a/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.h +++ b/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.h @@ -58,9 +58,11 @@ NS_ASSUME_NONNULL_BEGIN @param attribute attribute's accessibility identifier. Can be one of `XC_kAXXCAttribute`-prefixed attribute names. - @return value for given accessibility property identifier + @param error Error instance in case of a failure + @return value for given accessibility property identifier or nil in case of failure */ -- (nullable id)fb_attributeValue:(NSString *)attribute; +- (nullable id)fb_attributeValue:(NSString *)attribute + error:(NSError **)error; /** Method used to determine whether given element matches receiver by comparing it's parameters except frame. @@ -87,13 +89,6 @@ NS_ASSUME_NONNULL_BEGIN /**! Human-readable snapshot description */ - (NSString *)fb_description; -/** - Returns the snapshot visibleFrame with a fallback to direct attribute retrieval from FBXCAXClient in case of a snapshot fault (nil visibleFrame) - - @return the snapshot visibleFrame - */ -- (CGRect)fb_visibleFrameWithFallback; - /** Wrapper for Apple's hitpoint, thats resolves few known issues diff --git a/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.m b/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.m index c16a1a848..c3a70f1f9 100644 --- a/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.m +++ b/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.m @@ -10,9 +10,11 @@ #import "FBXCElementSnapshotWrapper+Helpers.h" #import "FBFindElementCommands.h" +#import "FBErrorBuilder.h" #import "FBRunLoopSpinner.h" #import "FBLogger.h" #import "FBXCElementSnapshot.h" +#import "FBXCTestDaemonsProxy.h" #import "FBXCAXClientProxy.h" #import "XCTestDriver.h" #import "XCTestPrivateSymbols.h" @@ -20,6 +22,8 @@ #import "XCUIElement+FBWebDriverAttributes.h" #import "XCUIHitPointResult.h" +#define ATTRIBUTE_FETCH_WARN_TIME_LIMIT 0.05 + inline static BOOL isSnapshotTypeAmongstGivenTypes(id snapshot, NSArray *types); @@ -65,10 +69,17 @@ - (NSString *)fb_description } - (id)fb_attributeValue:(NSString *)attribute + error:(NSError **)error { + NSDate *start = [NSDate date]; NSDictionary *result = [FBXCAXClientProxy.sharedClient attributesForElement:[self accessibilityElement] - attributes:@[attribute]]; - return result[attribute]; + attributes:@[attribute] + error:error]; + NSTimeInterval elapsed = ABS([start timeIntervalSinceNow]); + if (elapsed > ATTRIBUTE_FETCH_WARN_TIME_LIMIT) { + NSLog(@"! Fetching of %@ value for %@ took %@s", attribute, self.fb_description, @(elapsed)); + } + return [result objectForKey:attribute]; } inline static BOOL areValuesEqual(id value1, id value2); @@ -140,29 +151,6 @@ - (BOOL)fb_framelessFuzzyMatchesElement:(id)snapshot return targetCellSnapshot; } -- (CGRect)fb_visibleFrameWithFallback -{ - CGRect thisVisibleFrame = [self visibleFrame]; - if (!CGRectIsEmpty(thisVisibleFrame)) { - return thisVisibleFrame; - } - - NSDictionary *visibleFrameDict = (NSDictionary*)[self fb_attributeValue:@"XC_kAXXCAttributeVisibleFrame"]; - if (visibleFrameDict == nil) { - return thisVisibleFrame; - } - - id x = [visibleFrameDict objectForKey:@"X"]; - id y = [visibleFrameDict objectForKey:@"Y"]; - id height = [visibleFrameDict objectForKey:@"Height"]; - id width = [visibleFrameDict objectForKey:@"Width"]; - if (x != nil && y != nil && height != nil && width != nil) { - return CGRectMake([x doubleValue], [y doubleValue], [width doubleValue], [height doubleValue]); - } - - return thisVisibleFrame; -} - - (NSValue *)fb_hitPoint { NSError *error; diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m b/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m index 38b6586ef..878be80b0 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m @@ -52,7 +52,7 @@ - (nullable XCUIElement *)fb_alertElementFromSafariWithScrollView:(XCUIElement * // and conatins at least one text view __block NSUInteger buttonsCount = 0; __block NSUInteger textViewsCount = 0; - id snapshot = candidate.fb_cachedSnapshot ?: candidate.fb_takeSnapshot; + id snapshot = candidate.fb_cachedSnapshot ?: [candidate fb_takeSnapshot:YES]; [snapshot enumerateDescendantsUsingBlock:^(id descendant) { XCUIElementType curType = descendant.elementType; if (curType == XCUIElementTypeButton) { @@ -73,7 +73,7 @@ - (XCUIElement *)fb_alertElement if (nil == alert) { return nil; } - id alertSnapshot = alert.fb_cachedSnapshot ?: alert.fb_takeSnapshot; + id alertSnapshot = alert.fb_cachedSnapshot ?: [alert fb_takeSnapshot:YES]; if (alertSnapshot.elementType == XCUIElementTypeAlert) { return alert; diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 2672e3272..03d4407f2 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -176,21 +176,7 @@ - (NSDictionary *)fb_tree - (NSDictionary *)fb_tree:(nullable NSSet *)excludedAttributes { - // This set includes XCTest-specific internal attribute names, - // while the `excludedAttributes` arg contains human-readable ones - NSMutableSet* includedAttributeNames = [NSMutableSet setWithArray:FBCustomAttributeNames()]; - [includedAttributeNames addObjectsFromArray:FBStandardAttributeNames()]; - if (nil != excludedAttributes) { - for (NSString *attr in excludedAttributes) { - NSString *mappedName = [customExclusionAttributesMap() objectForKey:attr]; - if (nil != mappedName) { - [includedAttributeNames removeObject:attr]; - } - } - } - id snapshot = nil == excludedAttributes - ? [self fb_snapshotWithAllAttributesAndMaxDepth:nil] - : [self fb_snapshotWithAttributes:[includedAttributeNames allObjects] maxDepth:nil]; + id snapshot = [self fb_takeSnapshot:YES]; return [self.class dictionaryForElement:snapshot recursive:YES excludedAttributes:excludedAttributes]; @@ -198,9 +184,7 @@ - (NSDictionary *)fb_tree:(nullable NSSet *)excludedAttributes - (NSDictionary *)fb_accessibilityTree { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : [self fb_snapshotWithAllAttributesAndMaxDepth:nil]; + id snapshot = [self fb_takeSnapshot:YES]; return [self.class accessibilityInfoForElement:snapshot]; } @@ -445,8 +429,8 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames id extractedElement = extractIssueProperty(issue, @"element"); - id elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_takeSnapshot]; - NSDictionary *elementAttributes = elementSnapshot + id elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_takeSnapshot:NO]; + NSDictionary *elementAttributes = elementSnapshot ? [self.class dictionaryForElement:elementSnapshot recursive:NO excludedAttributes:customAttributesToExclude] diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m b/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m index 327b2171a..944907c15 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m @@ -18,8 +18,7 @@ @implementation XCUIElement (FBAccessibility) - (BOOL)fb_isAccessibilityElement { - id snapshot = [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName] - maxDepth:@1]; + id snapshot = [self fb_takeSnapshot:NO]; return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isAccessibilityElement; } @@ -33,8 +32,20 @@ - (BOOL)fb_isAccessibilityElement if (nil != isAccessibilityElement) { return isAccessibilityElement.boolValue; } - - return [(NSNumber *)[self fb_attributeValue:FB_XCAXAIsElementAttributeName] boolValue]; + + NSError *error; + NSNumber *attributeValue = [self fb_attributeValue:FB_XCAXAIsElementAttributeName + error:&error]; + if (nil != attributeValue) { + NSMutableDictionary *updatedValue = [NSMutableDictionary dictionaryWithDictionary:self.additionalAttributes ?: @{}]; + [updatedValue setObject:attributeValue forKey:FB_XCAXAIsElementAttribute]; + self.snapshot.additionalAttributes = updatedValue.copy; + return [attributeValue boolValue]; + } + + NSLog(@"Cannot determine accessibility of '%@' natively: %@. Defaulting to: %@", + self.fb_description, error.description, @(NO)); + return NO; } @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h b/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h index 109a26371..a36039419 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h @@ -13,9 +13,6 @@ NS_ASSUME_NONNULL_BEGIN @interface XCUIElement (FBCaching) -/*! This property is set to YES if the given element has been resolved from the cache, so it is safe to use the `lastSnapshot` property */ -@property (nullable, nonatomic) NSNumber *fb_isResolvedFromCache; - @property (nonatomic, readonly) NSString *fb_cacheId; @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m b/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m index faa42ea86..ebf4ea6fa 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m @@ -18,20 +18,6 @@ @implementation XCUIElement (FBCaching) -static char XCUIELEMENT_IS_RESOLVED_FROM_CACHE_KEY; - -@dynamic fb_isResolvedFromCache; - -- (void)setFb_isResolvedFromCache:(NSNumber *)isResolvedFromCache -{ - objc_setAssociatedObject(self, &XCUIELEMENT_IS_RESOLVED_FROM_CACHE_KEY, isResolvedFromCache, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -- (NSNumber *)fb_isResolvedFromCache -{ - return (NSNumber *)objc_getAssociatedObject(self, &XCUIELEMENT_IS_RESOLVED_FROM_CACHE_KEY); -} - static char XCUIELEMENT_CACHE_ID_KEY; @dynamic fb_cacheId; @@ -43,14 +29,7 @@ - (NSString *)fb_cacheId return (NSString *)result; } - NSString *uid; - if ([self isKindOfClass:XCUIApplication.class]) { - uid = self.fb_uid; - } else { - id snapshot = self.fb_cachedSnapshot ?: self.fb_takeSnapshot; - uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]; - } - + NSString *uid = self.fb_uid; objc_setAssociatedObject(self, &XCUIELEMENT_CACHE_ID_KEY, uid, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return uid; } diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m index 4d46f4c8f..e799be557 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m @@ -110,7 +110,7 @@ @implementation XCUIElement (FBFind) matchingSnapshots = @[snapshot]; } return [self fb_filterDescendantsWithSnapshots:matchingSnapshots - selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot] + selfUID:self.fb_uid onlyChildren:NO]; } diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m index 87841fc38..80ee1bd9b 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m @@ -9,24 +9,23 @@ #import "XCUIElement+FBIsVisible.h" -#import "FBConfiguration.h" #import "FBElementUtils.h" -#import "FBMathUtils.h" -#import "FBActiveAppDetectionPoint.h" -#import "FBSession.h" -#import "FBXCAccessibilityElement.h" #import "FBXCodeCompatibility.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "XCUIElement+FBUtilities.h" -#import "XCUIElement+FBUID.h" +#import "XCUIElement+FBVisibleFrame.h" #import "XCTestPrivateSymbols.h" +NSNumber* _Nullable fetchSnapshotVisibility(id snapshot) +{ + return nil == snapshot.additionalAttributes ? nil : snapshot.additionalAttributes[FB_XCAXAIsVisibleAttribute]; +} + @implementation XCUIElement (FBIsVisible) - (BOOL)fb_isVisible { - id snapshot = [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName] - maxDepth:@1]; + id snapshot = [self fb_takeSnapshot:NO]; return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isVisible; } @@ -34,187 +33,43 @@ - (BOOL)fb_isVisible @implementation FBXCElementSnapshotWrapper (FBIsVisible) -+ (NSString *)fb_uniqIdWithSnapshot:(id)snapshot -{ - return [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot] ?: [NSString stringWithFormat:@"%p", (void *)snapshot]; -} - -- (nullable NSNumber *)fb_cachedVisibilityValue +- (BOOL)fb_hasVisibleDescendants { - NSMutableDictionary *cache = FBSession.activeSession.elementsVisibilityCache; - if (nil == cache) { - return nil; - } - - NSDictionary *result = cache[@(self.generation)]; - if (nil == result) { - // There is no need to keep the cached data for the previous generations - [cache removeAllObjects]; - cache[@(self.generation)] = [NSMutableDictionary dictionary]; - return nil; - } - return result[[self.class fb_uniqIdWithSnapshot:self.snapshot]]; -} - -- (BOOL)fb_cacheVisibilityWithValue:(BOOL)isVisible - forAncestors:(nullable NSArray> *)ancestors -{ - NSMutableDictionary *cache = FBSession.activeSession.elementsVisibilityCache; - if (nil == cache) { - return isVisible; - } - NSMutableDictionary *destination = cache[@(self.generation)]; - if (nil == destination) { - return isVisible; - } - - NSNumber *visibleObj = [NSNumber numberWithBool:isVisible]; - destination[[self.class fb_uniqIdWithSnapshot:self.snapshot]] = visibleObj; - if (isVisible && nil != ancestors) { - // if an element is visible then all its ancestors must be visible as well - for (id ancestor in ancestors) { - NSString *ancestorId = [self.class fb_uniqIdWithSnapshot:ancestor]; - if (nil == destination[ancestorId]) { - destination[ancestorId] = visibleObj; - } - } - } - return isVisible; -} - -- (CGRect)fb_frameInContainer:(id)container - hierarchyIntersection:(nullable NSValue *)intersectionRectange -{ - CGRect currentRectangle = nil == intersectionRectange ? self.frame : [intersectionRectange CGRectValue]; - id parent = self.parent; - CGRect parentFrame = parent.frame; - CGRect containerFrame = container.frame; - if (CGSizeEqualToSize(parentFrame.size, CGSizeZero) && - CGPointEqualToPoint(parentFrame.origin, CGPointZero)) { - // Special case (or XCTest bug). Shift the origin and return immediately after shift - id nextParent = parent.parent; - BOOL isGrandparent = YES; - while (nextParent && nextParent != container) { - CGRect nextParentFrame = nextParent.frame; - if (isGrandparent && - CGSizeEqualToSize(nextParentFrame.size, CGSizeZero) && - CGPointEqualToPoint(nextParentFrame.origin, CGPointZero)) { - // Double zero-size container inclusion means that element coordinates are absolute - return CGRectIntersection(currentRectangle, containerFrame); - } - isGrandparent = NO; - if (!CGPointEqualToPoint(nextParentFrame.origin, CGPointZero)) { - currentRectangle.origin.x += nextParentFrame.origin.x; - currentRectangle.origin.y += nextParentFrame.origin.y; - return CGRectIntersection(currentRectangle, containerFrame); - } - nextParent = nextParent.parent; - } - return CGRectIntersection(currentRectangle, containerFrame); - } - // Skip parent containers if they are outside of the viewport - CGRect intersectionWithParent = CGRectIntersectsRect(parentFrame, containerFrame) || parent.elementType != XCUIElementTypeOther - ? CGRectIntersection(currentRectangle, parentFrame) - : currentRectangle; - if (CGRectIsEmpty(intersectionWithParent) && - parent != container && - self.elementType == XCUIElementTypeOther) { - // Special case (or XCTest bug). Shift the origin - if (CGSizeEqualToSize(parentFrame.size, containerFrame.size) || - // The size might be inverted in landscape - CGSizeEqualToSize(parentFrame.size, CGSizeMake(containerFrame.size.height, containerFrame.size.width)) || - CGSizeEqualToSize(self.frame.size, CGSizeZero)) { - // Covers ActivityListView and RemoteBridgeView cases - currentRectangle.origin.x += parentFrame.origin.x; - currentRectangle.origin.y += parentFrame.origin.y; - return CGRectIntersection(currentRectangle, containerFrame); - } - } - if (CGRectIsEmpty(intersectionWithParent) || parent == container) { - return intersectionWithParent; - } - return [[FBXCElementSnapshotWrapper ensureWrapped:parent] fb_frameInContainer:container - hierarchyIntersection:[NSValue valueWithCGRect:intersectionWithParent]]; -} - -- (BOOL)fb_hasAnyVisibleLeafs -{ - NSArray> *children = self.children; - if (0 == children.count) { - return self.fb_isVisible; - } - - for (id child in children) { - if ([FBXCElementSnapshotWrapper ensureWrapped:child].fb_hasAnyVisibleLeafs) { + for (id descendant in (self._allDescendants ?: @[])) { + if ([fetchSnapshotVisibility(descendant) boolValue]) { return YES; } } - return NO; } - (BOOL)fb_isVisible { - NSNumber *isVisible = self.additionalAttributes[FB_XCAXAIsVisibleAttribute]; - if (isVisible != nil) { + NSNumber *isVisible = fetchSnapshotVisibility(self); + if (nil != isVisible) { return isVisible.boolValue; } - - NSNumber *cachedValue = [self fb_cachedVisibilityValue]; - if (nil != cachedValue) { - return [cachedValue boolValue]; - } - CGRect selfFrame = self.frame; - if (CGRectIsEmpty(selfFrame)) { - return [self fb_cacheVisibilityWithValue:NO forAncestors:nil]; + // Fetching the attribute value is expensive. + // Shortcircuit here to save time and assume if any of descendants + // is already determined as visible then the container should be visible as well + if ([self fb_hasVisibleDescendants]) { + return YES; } - NSArray> *ancestors = self.fb_ancestors; - if ([FBConfiguration shouldUseTestManagerForVisibilityDetection]) { - BOOL visibleAttrValue = [(NSNumber *)[self fb_attributeValue:FB_XCAXAIsVisibleAttributeName] boolValue]; - return [self fb_cacheVisibilityWithValue:visibleAttrValue forAncestors:ancestors]; + NSError *error; + NSNumber *attributeValue = [self fb_attributeValue:FB_XCAXAIsVisibleAttributeName + error:&error]; + if (nil != attributeValue) { + NSMutableDictionary *updatedValue = [NSMutableDictionary dictionaryWithDictionary:self.additionalAttributes ?: @{}]; + [updatedValue setObject:attributeValue forKey:FB_XCAXAIsVisibleAttribute]; + self.snapshot.additionalAttributes = updatedValue.copy; + return [attributeValue boolValue]; } - id parentWindow = ancestors.count > 1 ? [ancestors objectAtIndex:ancestors.count - 2] : nil; - CGRect visibleRect = selfFrame; - if (nil != parentWindow) { - visibleRect = [self fb_frameInContainer:parentWindow hierarchyIntersection:nil]; - } - if (CGRectIsEmpty(visibleRect)) { - return [self fb_cacheVisibilityWithValue:NO forAncestors:ancestors]; - } - CGPoint midPoint = CGPointMake(visibleRect.origin.x + visibleRect.size.width / 2, - visibleRect.origin.y + visibleRect.size.height / 2); - id hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint]; - if (nil != hitElement) { - if (FBIsAXElementEqualToOther(self.accessibilityElement, hitElement)) { - return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors]; - } - for (id ancestor in ancestors) { - if (FBIsAXElementEqualToOther(hitElement, ancestor.accessibilityElement)) { - return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors]; - } - } - } - if (self.children.count > 0) { - if (nil != hitElement) { - for (id descendant in self._allDescendants) { - if (FBIsAXElementEqualToOther(hitElement, descendant.accessibilityElement)) { - return [self fb_cacheVisibilityWithValue:YES - forAncestors:[FBXCElementSnapshotWrapper ensureWrapped:descendant].fb_ancestors]; - } - } - } - if (self.fb_hasAnyVisibleLeafs) { - return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors]; - } - } else if (nil == hitElement) { - // Sometimes XCTest returns nil for leaf elements hit test even if such elements are hittable - // Assume such elements are visible if their rectInContainer is visible - return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors]; - } - return [self fb_cacheVisibilityWithValue:NO forAncestors:ancestors]; + NSLog(@"Cannot determine visiblity of %@ natively: %@. Defaulting to: %@", + self.fb_description, error.description, @(NO)); + return NO; } @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m index 71ebaf652..881081fa1 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m @@ -23,9 +23,7 @@ @implementation XCUIElement (FBPickerWheel) - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)error { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_takeSnapshot:NO]; 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)]; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m index 52be1a557..4ebd14b32 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m @@ -20,9 +20,11 @@ #import "XCUIApplication.h" #import "XCUICoordinate.h" #import "XCUIElement+FBIsVisible.h" +#import "XCUIElement+FBVisibleFrame.h" #import "XCUIElement.h" #import "XCUIElement+FBUtilities.h" #import "XCUIElement+FBWebDriverAttributes.h" +#import "XCTestPrivateSymbols.h" const CGFloat FBFuzzyPointThreshold = 20.f; //Smallest determined value that is not interpreted as touch const CGFloat FBScrollToVisibleNormalizedDistance = .5f; @@ -47,45 +49,35 @@ @implementation XCUIElement (FBScrolling) - (BOOL)fb_nativeScrollToVisibleWithError:(NSError **)error { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_takeSnapshot:YES]; return nil != [self _hitPointByAttemptingToScrollToVisibleSnapshot:snapshot error:error]; } - (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_takeSnapshot:YES]; [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollUpByNormalizedDistance:distance inApplication:self.application]; } - (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_takeSnapshot:YES]; [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollDownByNormalizedDistance:distance inApplication:self.application]; } - (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_takeSnapshot:YES]; [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollLeftByNormalizedDistance:distance inApplication:self.application]; } - (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_takeSnapshot:YES]; [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollRightByNormalizedDistance:distance inApplication:self.application]; } @@ -95,7 +87,8 @@ - (BOOL)fb_scrollToVisibleWithError:(NSError **)error return [self fb_scrollToVisibleWithNormalizedScrollDistance:FBScrollToVisibleNormalizedDistance error:error]; } -- (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance error:(NSError **)error +- (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance + error:(NSError **)error { return [self fb_scrollToVisibleWithNormalizedScrollDistance:normalizedScrollDistance scrollDirection:FBXCUIElementScrollDirectionUnknown @@ -106,7 +99,8 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll scrollDirection:(FBXCUIElementScrollDirection)scrollDirection error:(NSError **)error { - FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]]; + FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:YES]]; + if (prescrollSnapshot.isWDVisible) { return YES; } @@ -138,12 +132,12 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll FBXCElementSnapshotWrapper *wrappedCellSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:cellSnapshot]; if (wrappedCellSnapshot.wdVisible) { [visibleCellSnapshots addObject:cellSnapshot]; + if (visibleCellSnapshots.count > 1) { + return YES; + } } } - if (visibleCellSnapshots.count > 1) { - return YES; - } return NO; }]; @@ -213,9 +207,9 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll // Cell is now visible, but it might be only partialy visible, scrolling till whole frame is visible. // Sometimes, attempting to grab the parent snapshot of the target cell after scrolling is complete causes a stale element reference exception. // Trying fb_cachedSnapshot first - FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:([self fb_cachedSnapshot] ?: [self fb_takeSnapshot])]; + FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:YES]]; targetCellSnapshot = [targetCellSnapshotWrapped fb_parentCellSnapshot]; - CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].fb_visibleFrameWithFallback; + CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].fb_visibleFrame; CGVector scrollVector = CGVectorMake(visibleFrame.size.width - targetCellSnapshot.frame.size.width, visibleFrame.size.height - targetCellSnapshot.frame.size.height @@ -233,7 +227,7 @@ - (BOOL)fb_isEquivalentElementSnapshotVisible:(id)snapshot return YES; } - id appSnapshot = [self.application fb_takeSnapshot]; + id appSnapshot = [self.application fb_takeSnapshot:YES]; for (id elementSnapshot in appSnapshot._allDescendants.copy) { FBXCElementSnapshotWrapper *wrappedElementSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:elementSnapshot]; // We are comparing pre-scroll snapshot so frames are irrelevant. @@ -255,27 +249,32 @@ - (CGRect)scrollingFrame return self.visibleFrame; } -- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application +- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance + inApplication:(XCUIApplication *)application { [self fb_scrollByNormalizedVector:CGVectorMake(0.0, distance) inApplication:application]; } -- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application +- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance + inApplication:(XCUIApplication *)application { [self fb_scrollByNormalizedVector:CGVectorMake(0.0, -distance) inApplication:application]; } -- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application +- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance + inApplication:(XCUIApplication *)application { [self fb_scrollByNormalizedVector:CGVectorMake(distance, 0.0) inApplication:application]; } -- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application +- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance + inApplication:(XCUIApplication *)application { [self fb_scrollByNormalizedVector:CGVectorMake(-distance, 0.0) inApplication:application]; } -- (BOOL)fb_scrollByNormalizedVector:(CGVector)normalizedScrollVector inApplication:(XCUIApplication *)application +- (BOOL)fb_scrollByNormalizedVector:(CGVector)normalizedScrollVector + inApplication:(XCUIApplication *)application { CGVector scrollVector = CGVectorMake(CGRectGetWidth(self.scrollingFrame) * normalizedScrollVector.dx, CGRectGetHeight(self.scrollingFrame) * normalizedScrollVector.dy @@ -283,7 +282,9 @@ - (BOOL)fb_scrollByNormalizedVector:(CGVector)normalizedScrollVector inApplicati return [self fb_scrollByVector:scrollVector inApplication:application error:nil]; } -- (BOOL)fb_scrollByVector:(CGVector)vector inApplication:(XCUIApplication *)application error:(NSError **)error +- (BOOL)fb_scrollByVector:(CGVector)vector + inApplication:(XCUIApplication *)application + error:(NSError **)error { CGVector scrollBoundingVector = CGVectorMake( CGRectGetWidth(self.scrollingFrame) * FBScrollTouchProportion, @@ -314,7 +315,9 @@ - (CGVector)fb_hitPointOffsetForScrollingVector:(CGVector)scrollingVector return CGVectorMake((CGFloat)floor(x), (CGFloat)floor(y)); } -- (BOOL)fb_scrollAncestorScrollViewByVectorWithinScrollViewFrame:(CGVector)vector inApplication:(XCUIApplication *)application error:(NSError **)error +- (BOOL)fb_scrollAncestorScrollViewByVectorWithinScrollViewFrame:(CGVector)vector + inApplication:(XCUIApplication *)application + error:(NSError **)error { CGVector hitpointOffset = [self fb_hitPointOffsetForScrollingVector:vector]; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m index 8b59ad031..4ea5cc66a 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m @@ -91,7 +91,7 @@ - (void)fb_prepareForTextInputWithSnapshot:(FBXCElementSnapshotWrapper *)snapsho [FBLogger logFmt:@"Trying to tap the \"%@\" element to have it focused", snapshot.fb_description]; [self tap]; // It might take some time to update the UI - [self fb_takeSnapshot]; + [self fb_takeSnapshot:NO]; #endif } @@ -110,9 +110,7 @@ - (BOOL)fb_typeText:(NSString *)text frequency:(NSUInteger)frequency error:(NSError **)error { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_takeSnapshot:NO]; FBXCElementSnapshotWrapper *wrapped = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; [self fb_prepareForTextInputWithSnapshot:wrapped]; if (shouldClear && ![self fb_clearTextWithSnapshot:wrapped shouldPrepareForInput:NO error:error]) { @@ -123,9 +121,7 @@ - (BOOL)fb_typeText:(NSString *)text - (BOOL)fb_clearTextWithError:(NSError **)error { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_takeSnapshot:NO]; return [self fb_clearTextWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot] shouldPrepareForInput:YES error:error]; @@ -182,7 +178,7 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot return NO; } - currentValue = self.fb_takeSnapshot.value; + currentValue = [self fb_takeSnapshot:NO].value; if (nil != placeholderValue && [currentValue isEqualToString:placeholderValue]) { // Short circuit if only the placeholder value left return YES; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUID.m b/WebDriverAgentLib/Categories/XCUIElement+FBUID.m index ecac2cd91..70cfd4970 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUID.m @@ -22,14 +22,14 @@ - (unsigned long long)fb_accessibiltyId { return [FBElementUtils idWithAccessibilityElement:([self isKindOfClass:XCUIApplication.class] ? [(XCUIApplication *)self accessibilityElement] - : [self fb_takeSnapshot].accessibilityElement)]; + : [self fb_takeSnapshot:NO].accessibilityElement)]; } - (NSString *)fb_uid { return [self isKindOfClass:XCUIApplication.class] ? [FBElementUtils uidWithAccessibilityElement:[(XCUIApplication *)self accessibilityElement]] - : [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]].fb_uid; + : [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:NO]].fb_uid; } @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h index 66b9ee2c9..a16e581f4 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h @@ -19,12 +19,13 @@ NS_ASSUME_NONNULL_BEGIN Gets the most recent snapshot of the current element. The element will be automatically resolved if the snapshot is not available yet. Calls to this method mutate the `lastSnapshot` instance property.. - Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`. + @param inDepth Whether to resolve snapshot parents and children. Setting it to NO + would improve the snapshotting performance @return The recent snapshot of the element @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made */ -- (id)fb_takeSnapshot; +- (id)fb_takeSnapshot:(BOOL)inDepth; /** Extracts the cached element snapshot from its query. @@ -36,40 +37,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable id)fb_cachedSnapshot; -/** - Gets the most recent snapshot of the current element and already resolves the accessibility attributes - needed for creating the page source of this element. No additional calls to the accessibility layer - are required. - Calls to this method mutate the `lastSnapshot` instance property. - Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`. - - @param maxDepth The maximum depth of the snapshot. nil value means to use the default depth. - with custom attributes cannot be resolved - - @return The recent snapshot of the element with all attributes resolved or a snapshot with default - attributes resolved if there was a failure while resolving additional attributes - @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made - */ -- (nullable id)fb_snapshotWithAllAttributesAndMaxDepth:(nullable NSNumber *)maxDepth; - -/** - Gets the most recent snapshot of the current element with given attributes resolved. - No additional calls to the accessibility layer are required. - Calls to this method mutate the `lastSnapshot` instance property. - Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`. - - @param attributeNames The list of attribute names to resolve. Must be one of - FB_...Name values exported by XCTestPrivateSymbols.h module. - `nil` value means that only the default attributes must be extracted - @param maxDepth The maximum depth of the snapshot. nil value means to use the default depth. - - @return The recent snapshot of the element with the given attributes resolved or a snapshot with default - attributes resolved if there was a failure while resolving additional attributes - @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made -*/ -- (nullable id)fb_snapshotWithAttributes:(nullable NSArray *)attributeNames - maxDepth:(nullable NSNumber *)maxDepth; - /** Filters elements by matching them to snapshots from the corresponding array diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m index 5f9fd96f4..7b6d52c03 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m @@ -14,6 +14,7 @@ #import "FBConfiguration.h" #import "FBExceptions.h" #import "FBImageUtils.h" +#import "FBElementUtils.h" #import "FBLogger.h" #import "FBMacros.h" #import "FBMathUtils.h" @@ -32,6 +33,7 @@ #import "XCTestPrivateSymbols.h" #import "XCTRunnerDaemonSession.h" #import "XCUIApplicationProcess+FBQuiescence.h" +#import "XCUIApplication.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBWebDriverAttributes.h" #import "XCUIElementQuery.h" @@ -40,22 +42,21 @@ #import "XCUIScreen.h" #import "XCUIElement+FBResolve.h" -#define DEFAULT_AX_TIMEOUT 60. - @implementation XCUIElement (FBUtilities) -- (id)fb_takeSnapshot +- (id)fb_takeSnapshot:(BOOL)inDepth { NSError *error = nil; - self.fb_isResolvedFromCache = @(NO); - self.lastSnapshot = [self.fb_query fb_uniqueSnapshotWithError:&error]; + self.lastSnapshot = inDepth + ? [self.fb_query fb_uniqueSnapshotWithError:&error] + : (id)[self snapshotWithError:&error]; if (nil == self.lastSnapshot) { NSString *hintText = @"Make sure the application UI has the expected state"; - if (nil != error - && [error.localizedDescription containsString:@"Identity Binding"]) { + if (nil != error && [error.localizedDescription containsString:@"Identity Binding"]) { hintText = [NSString stringWithFormat:@"%@. You could also try to switch the binding strategy using the 'boundElementsByIndex' setting for the element lookup", hintText]; } - NSString *reason = [NSString stringWithFormat:@"The previously found element \"%@\" is not present in the current view anymore. %@", self.description, hintText]; + NSString *reason = [NSString stringWithFormat:@"The previously found element \"%@\" is not present in the current view anymore. %@", + self.description, hintText]; if (nil != error) { reason = [NSString stringWithFormat:@"%@. Original error: %@", reason, error.localizedDescription]; } @@ -69,63 +70,6 @@ @implementation XCUIElement (FBUtilities) return [self.query fb_cachedSnapshot]; } -- (nullable id)fb_snapshotWithAllAttributesAndMaxDepth:(NSNumber *)maxDepth -{ - NSMutableArray *allNames = [NSMutableArray arrayWithArray:FBStandardAttributeNames()]; - [allNames addObjectsFromArray:FBCustomAttributeNames()]; - return [self fb_snapshotWithAttributes:allNames.copy - maxDepth:maxDepth]; -} - -- (nullable id)fb_snapshotWithAttributes:(NSArray *)attributeNames - maxDepth:(NSNumber *)maxDepth -{ - NSSet *standardAttributes = [NSSet setWithArray:FBStandardAttributeNames()]; - id snapshot = self.fb_takeSnapshot; - NSTimeInterval axTimeout = FBConfiguration.customSnapshotTimeout; - if (nil == attributeNames - || [[NSSet setWithArray:attributeNames] isSubsetOfSet:standardAttributes] - || axTimeout < DBL_EPSILON) { - // return the "normal" element snapshot if no custom attributes are requested - return snapshot; - } - - id axElement = snapshot.accessibilityElement; - if (nil == axElement) { - return nil; - } - - NSError *setTimeoutError; - BOOL isTimeoutSet = [FBXCAXClientProxy.sharedClient setAXTimeout:axTimeout - error:&setTimeoutError]; - if (!isTimeoutSet) { - [FBLogger logFmt:@"Cannot set snapshoting timeout to %.1fs. Original error: %@", - axTimeout, setTimeoutError.localizedDescription]; - } - - NSError *error; - id snapshotWithAttributes = [FBXCAXClientProxy.sharedClient snapshotForElement:axElement - attributes:attributeNames - maxDepth:maxDepth - error:&error]; - if (nil == snapshotWithAttributes) { - NSString *description = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_description; - [FBLogger logFmt:@"Cannot take a snapshot with attribute(s) %@ of '%@' after %.2f seconds", - attributeNames, description, axTimeout]; - [FBLogger logFmt:@"This timeout could be customized via '%@' setting", FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT]; - [FBLogger logFmt:@"Internal error: %@", error.localizedDescription]; - [FBLogger logFmt:@"Falling back to the default snapshotting mechanism for the element '%@' (some attribute values, like visibility or accessibility might not be precise though)", description]; - snapshotWithAttributes = self.lastSnapshot; - } else { - self.lastSnapshot = snapshotWithAttributes; - } - - if (isTimeoutSet) { - [FBXCAXClientProxy.sharedClient setAXTimeout:DEFAULT_AX_TIMEOUT error:nil]; - } - return snapshotWithAttributes; -} - - (NSArray *)fb_filterDescendantsWithSnapshots:(NSArray> *)snapshots selfUID:(NSString *)selfUID onlyChildren:(BOOL)onlyChildren @@ -143,9 +87,7 @@ @implementation XCUIElement (FBUtilities) NSMutableArray *matchedElements = [NSMutableArray array]; NSString *uid = selfUID; if (nil == uid) { - uid = self.fb_isResolvedFromCache.boolValue - ? [FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot] - : self.fb_uid; + uid = self.fb_uid; } if (nil != uid && [matchedIds containsObject:uid]) { XCUIElement *stableSelf = self.fb_stableInstance; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h b/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h new file mode 100644 index 000000000..8917275d1 --- /dev/null +++ b/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h @@ -0,0 +1,36 @@ +/** + * 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 "FBXCElementSnapshotWrapper.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XCUIElement (FBVisibleFrame) + +/** + Returns the snapshot visibleFrame with a fallback to direct attribute retrieval from FBXCAXClient in case of a snapshot fault (nil visibleFrame) + + @return the snapshot visibleFrame + */ +- (CGRect)fb_visibleFrame; + +@end + +@interface FBXCElementSnapshotWrapper (FBVisibleFrame) + +/** + Returns the snapshot visibleFrame with a fallback to direct attribute retrieval from FBXCAXClient in case of a snapshot fault (nil visibleFrame) + + @return the snapshot visibleFrame + */ +- (CGRect)fb_visibleFrame; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m b/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m new file mode 100644 index 000000000..3117b4acb --- /dev/null +++ b/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m @@ -0,0 +1,53 @@ +/** + * 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+FBVisibleFrame.h" +#import "FBElementUtils.h" +#import "FBXCodeCompatibility.h" +#import "FBXCElementSnapshotWrapper+Helpers.h" +#import "XCUIElement+FBUtilities.h" +#import "XCTestPrivateSymbols.h" + +@implementation XCUIElement (FBVisibleFrame) + +- (CGRect)fb_visibleFrame +{ + id snapshot = [self fb_takeSnapshot:NO]; + return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_visibleFrame; +} + +@end + +@implementation FBXCElementSnapshotWrapper (FBVisibleFrame) + +- (CGRect)fb_visibleFrame +{ + CGRect thisVisibleFrame = [self visibleFrame]; + if (!CGRectIsEmpty(thisVisibleFrame)) { + return thisVisibleFrame; + } + + NSDictionary *visibleFrameDict = [self fb_attributeValue:FB_XCAXAVisibleFrameAttributeName + error:nil]; + if (nil == visibleFrameDict) { + return thisVisibleFrame; + } + + id x = [visibleFrameDict objectForKey:@"X"]; + id y = [visibleFrameDict objectForKey:@"Y"]; + id height = [visibleFrameDict objectForKey:@"Height"]; + id width = [visibleFrameDict objectForKey:@"Width"]; + if (x != nil && y != nil && height != nil && width != nil) { + return CGRectMake([x doubleValue], [y doubleValue], [width doubleValue], [height doubleValue]); + } + + return thisVisibleFrame; +} + +@end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m index b29c5a8b2..f99158c7f 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m @@ -28,24 +28,10 @@ @implementation XCUIElement (WebDriverAttributesForwarding) - (id)fb_snapshotForAttributeName:(NSString *)name { - // These attributes are special, because we can only retrieve them from - // the snapshot if we explicitly ask XCTest to include them into the query while taking it. - // That is why fb_snapshotWithAllAttributes method must be used instead of the default snapshot - // call - if ([name isEqualToString:FBStringify(XCUIElement, isWDVisible)]) { - return [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName] - maxDepth:@1]; - } - if ([name isEqualToString:FBStringify(XCUIElement, isWDAccessible)]) { - return [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName] - maxDepth:@1]; - } - if ([name isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)]) { - return [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName] - maxDepth:nil]; - } - - return self.fb_takeSnapshot; + BOOL inDepth = [name isEqualToString:FBStringify(XCUIElement, isWDAccessible)] + || [name isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)] + || [name isEqualToString:FBStringify(XCUIElement, wdIndex)]; + return [self fb_takeSnapshot:inDepth]; } - (id)fb_valueForWDAttributeName:(NSString *)name @@ -92,6 +78,7 @@ - (NSString *)wdValue value = @([value boolValue]); } else if (elementType == XCUIElementTypeTextView || elementType == XCUIElementTypeTextField || + elementType == XCUIElementTypeSearchField || elementType == XCUIElementTypeSecureTextField) { NSString *placeholderValue = self.placeholderValue; value = FBFirstNonEmptyValue(value, placeholderValue); @@ -183,8 +170,8 @@ - (BOOL)isWDAccessible // In the scenario when table provides Search results controller, table could be marked as accessible element, even though it isn't // As it is highly unlikely that table view should ever be an accessibility element itself, // for now we work around that by skipping Table View in container checks - if ([FBXCElementSnapshotWrapper ensureWrapped:parentSnapshot].fb_isAccessibilityElement - && parentSnapshot.elementType != XCUIElementTypeTable) { + if (parentSnapshot.elementType != XCUIElementTypeTable + && [FBXCElementSnapshotWrapper ensureWrapped:parentSnapshot].fb_isAccessibilityElement) { return NO; } parentSnapshot = parentSnapshot.parent; diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index 2ab039e6b..97ecfbca9 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -567,7 +567,8 @@ + (NSString *)timeZone FBElementCache *elementCache = request.session.elementCache; BOOL hasElement = ![request.parameters[@"uuid"] isEqual:@"0"]; XCUIElement *destination = hasElement - ? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]] + ? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES] : request.session.activeApplication; id keys = request.arguments[@"keys"]; diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 762bad327..79fa30b8d 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -126,38 +126,22 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - BOOL isEnabled = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDEnabled; - return FBResponseWithObject(isEnabled ? @YES : @NO); + return FBResponseWithObject(@(element.isWDEnabled)); } + (id)handleGetRect:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdRect); + return FBResponseWithObject(element.wdRect); } + (id)handleGetAttribute:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; NSString *attributeName = request.parameters[@"name"]; - NSString *wdAttributeName = [FBElementUtils wdAttributeNameForAttributeName:attributeName]; - NSArray *additionalAttributes = nil; - NSNumber *maxDepth = nil; - if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDVisible)]) { - additionalAttributes = @[FB_XCAXAIsVisibleAttributeName]; - maxDepth = @1; - } else if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDEnabled)]) { - additionalAttributes = @[FB_XCAXAIsElementAttributeName]; - maxDepth = @1; - } else if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)]) { - additionalAttributes = @[FB_XCAXAIsElementAttributeName]; - } - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:additionalAttributes - andMaxDepth:maxDepth]; - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot]; - id attributeValue = [wrappedSnapshot fb_valueForWDAttributeName:attributeName]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + id attributeValue = [element fb_valueForWDAttributeName:attributeName]; return FBResponseWithObject(attributeValue ?: [NSNull null]); } @@ -165,7 +149,7 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot]; + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[element fb_takeSnapshot:NO]]; id text = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel); return FBResponseWithObject(text ?: @""); } @@ -173,48 +157,43 @@ + (NSArray *)routes + (id)handleGetDisplayed:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName] - andMaxDepth:@1]; - return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDVisible)); + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + return FBResponseWithObject(@(element.isWDVisible)); } + (id)handleGetAccessible:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName] - andMaxDepth:@1]; - return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessible)); + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + return FBResponseWithObject(@(element.isWDAccessible)); } + (id)handleGetIsAccessibilityContainer:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName] - andMaxDepth:nil]; - return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessibilityContainer)); + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + return FBResponseWithObject(@(element.isWDAccessibilityContainer)); } + (id)handleGetName:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdType); + return FBResponseWithObject(element.wdType); } + (id)handleGetSelected:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdSelected)); + return FBResponseWithObject(@(element.wdSelected)); } + (id)handleSetValue:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES]; id value = request.arguments[@"value"] ?: request.arguments[@"text"]; if (!value) { return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"Neither 'value' nor 'text' parameter is provided" traceback:nil]); @@ -222,7 +201,7 @@ + (NSArray *)routes NSString *textToType = [value isKindOfClass:NSArray.class] ? [value componentsJoinedByString:@""] : value; - XCUIElementType elementType = [(id)element.lastSnapshot elementType]; + XCUIElementType elementType = [element elementType]; #if !TARGET_OS_TV if (elementType == XCUIElementTypePickerWheel) { [element adjustToPickerWheelValue:textToType]; @@ -251,7 +230,7 @@ + (NSArray *)routes + (id)handleClick:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] checkStaleness:YES]; #if TARGET_OS_IOS [element tap]; #elif TARGET_OS_TV @@ -353,7 +332,7 @@ + (NSArray *)routes FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [self targetFromRequest:request]; [element pressForDuration:[request.arguments[@"pressDuration"] doubleValue] - thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"]] + thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"] checkStaleness:YES] withVelocity:[request.arguments[@"velocity"] doubleValue] thenHoldForDuration:[request.arguments[@"holdDuration"] doubleValue]]; return FBResponseWithOK(); @@ -441,10 +420,7 @@ + (NSArray *)routes + (id)handleDrag:(FBRouteRequest *)request { - NSString *elementUdid = (NSString *)request.parameters[@"uuid"]; - XCUIElement *target = nil == elementUdid - ? request.session.activeApplication - : [request.session.elementCache elementForUUID:elementUdid]; + XCUIElement *target = [self targetFromRequest:request]; CGVector startOffset = CGVectorMake([request.arguments[@"fromX"] doubleValue], [request.arguments[@"fromY"] doubleValue]); XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset element:target]; @@ -561,7 +537,8 @@ + (NSArray *)routes + (id)handleElementScreenshot:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES]; NSData *screenshotData = [element.screenshot PNGRepresentation]; if (nil == screenshotData) { NSString *errMsg = [NSString stringWithFormat:@"Cannot take a screenshot of %@", element.description]; @@ -581,8 +558,9 @@ + (NSArray *)routes + (id)handleWheelSelect:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - if ([element.lastSnapshot elementType] != XCUIElementTypePickerWheel) { + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES]; + if ([element elementType] != XCUIElementTypePickerWheel) { 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]]); @@ -688,7 +666,7 @@ + (XCUIElement *)targetFromRequest:(FBRouteRequest *)request NSString *elementUuid = (NSString *)request.parameters[@"uuid"]; return nil == elementUuid ? request.session.activeApplication - : [elementCache elementForUUID:elementUuid]; + : [elementCache elementForUUID:elementUuid checkStaleness:YES]; } #endif diff --git a/WebDriverAgentLib/Commands/FBFindElementCommands.m b/WebDriverAgentLib/Commands/FBFindElementCommands.m index ba30a7170..a92c5082e 100644 --- a/WebDriverAgentLib/Commands/FBFindElementCommands.m +++ b/WebDriverAgentLib/Commands/FBFindElementCommands.m @@ -80,15 +80,14 @@ + (NSArray *)routes + (id)handleFindVisibleCells:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName] - andMaxDepth:nil]; - NSArray> *visibleCellSnapshots = [element.lastSnapshot descendantsByFilteringWithBlock:^BOOL(id snapshot) { - return snapshot.elementType == XCUIElementTypeCell - && [FBXCElementSnapshotWrapper ensureWrapped:snapshot].wdVisible; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + id snapshot = [element fb_takeSnapshot:YES]; + NSArray> *visibleCellSnapshots = [snapshot descendantsByFilteringWithBlock:^BOOL(id shot) { + return shot.elementType == XCUIElementTypeCell + && [FBXCElementSnapshotWrapper ensureWrapped:shot].wdVisible; }]; NSArray *cells = [element fb_filterDescendantsWithSnapshots:visibleCellSnapshots - selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:element.lastSnapshot] + selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot] onlyChildren:NO]; return FBResponseWithCachedElements(cells, request.session.elementCache, FBConfiguration.shouldUseCompactResponses); } @@ -96,7 +95,8 @@ + (NSArray *)routes + (id)handleFindSubElement:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES]; XCUIElement *foundElement = [self.class elementUsing:request.arguments[@"using"] withValue:request.arguments[@"value"] under:element]; @@ -109,7 +109,8 @@ + (NSArray *)routes + (id)handleFindSubElements:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES]; NSArray *foundElements = [self.class elementsUsing:request.arguments[@"using"] withValue:request.arguments[@"value"] under:element diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 1972186d2..8f84d7afe 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -336,7 +336,6 @@ + (NSArray *)routes FB_SETTING_SCREENSHOT_QUALITY: @([FBConfiguration screenshotQuality]), FB_SETTING_KEYBOARD_AUTOCORRECTION: @([FBConfiguration keyboardAutocorrection]), FB_SETTING_KEYBOARD_PREDICTION: @([FBConfiguration keyboardPrediction]), - FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT: @([FBConfiguration customSnapshotTimeout]), FB_SETTING_SNAPSHOT_MAX_DEPTH: @([FBConfiguration snapshotMaxDepth]), FB_SETTING_USE_FIRST_MATCH: @([FBConfiguration useFirstMatch]), FB_SETTING_WAIT_FOR_IDLE_TIMEOUT: @([FBConfiguration waitForIdleTimeout]), @@ -395,13 +394,6 @@ + (NSArray *)routes if (nil != [settings objectForKey:FB_SETTING_RESPECT_SYSTEM_ALERTS]) { [FBConfiguration setShouldRespectSystemAlerts:[[settings objectForKey:FB_SETTING_RESPECT_SYSTEM_ALERTS] boolValue]]; } - // SNAPSHOT_TIMEOUT setting is deprecated. Please use CUSTOM_SNAPSHOT_TIMEOUT instead - if (nil != [settings objectForKey:FB_SETTING_SNAPSHOT_TIMEOUT]) { - [FBConfiguration setCustomSnapshotTimeout:[[settings objectForKey:FB_SETTING_SNAPSHOT_TIMEOUT] doubleValue]]; - } - if (nil != [settings objectForKey:FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT]) { - [FBConfiguration setCustomSnapshotTimeout:[[settings objectForKey:FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT] doubleValue]]; - } if (nil != [settings objectForKey:FB_SETTING_SNAPSHOT_MAX_DEPTH]) { [FBConfiguration setSnapshotMaxDepth:[[settings objectForKey:FB_SETTING_SNAPSHOT_MAX_DEPTH] intValue]]; } diff --git a/WebDriverAgentLib/FBAlert.m b/WebDriverAgentLib/FBAlert.m index b06e26788..aca9781e1 100644 --- a/WebDriverAgentLib/FBAlert.m +++ b/WebDriverAgentLib/FBAlert.m @@ -50,7 +50,7 @@ - (BOOL)isPresent if (nil == self.alertElement) { return NO; } - [self.alertElement fb_takeSnapshot]; + [self.alertElement fb_takeSnapshot:YES]; return YES; } @catch (NSException *) { return NO; @@ -82,7 +82,7 @@ - (NSString *)text } NSMutableArray *resultText = [NSMutableArray array]; - id snapshot = self.alertElement.lastSnapshot; + id snapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_takeSnapshot:YES]; BOOL isSafariAlert = [self.class isSafariWebAlertWithSnapshot:snapshot]; [snapshot enumerateDescendantsUsingBlock:^(id descendant) { XCUIElementType elementType = descendant.elementType; @@ -145,7 +145,8 @@ - (NSArray *)buttonLabels } NSMutableArray *labels = [NSMutableArray array]; - [self.alertElement.lastSnapshot enumerateDescendantsUsingBlock:^(id descendant) { + id alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_takeSnapshot:YES]; + [alertSnapshot enumerateDescendantsUsingBlock:^(id descendant) { if (descendant.elementType != XCUIElementTypeButton) { return; } @@ -163,7 +164,7 @@ - (BOOL)acceptWithError:(NSError **)error return [self notPresentWithError:error]; } - id alertSnapshot = self.alertElement.lastSnapshot; + id alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_takeSnapshot:YES]; XCUIElement *acceptButton = nil; if (FBConfiguration.acceptAlertButtonSelector.length) { NSString *errorReason = nil; @@ -204,7 +205,7 @@ - (BOOL)dismissWithError:(NSError **)error return [self notPresentWithError:error]; } - id alertSnapshot = self.alertElement.lastSnapshot; + id alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_takeSnapshot:YES]; XCUIElement *dismissButton = nil; if (FBConfiguration.dismissAlertButtonSelector.length) { NSString *errorReason = nil; diff --git a/WebDriverAgentLib/Routing/FBElementCache.h b/WebDriverAgentLib/Routing/FBElementCache.h index 13100eeb2..940c2df6f 100644 --- a/WebDriverAgentLib/Routing/FBElementCache.h +++ b/WebDriverAgentLib/Routing/FBElementCache.h @@ -35,26 +35,20 @@ extern const int ELEMENT_CACHE_SIZE; @param uuid uuid of element to fetch @return element - @throws FBStaleElementException if the found element is not present in DOM anymore @throws FBInvalidArgumentException if uuid is nil */ - (XCUIElement *)elementForUUID:(NSString *)uuid; /** - Returns cached element + Returns cached element resolved with default snapshot attributes @param uuid uuid of element to fetch - @param additionalAttributes Add additonal attribute names if the snapshot should contain - them in `addtionalAttributes` section. nil value resolves the snapshot with standard attributes. - @param maxDepth The maximum depth of the snapshot. Only works if additional attributes are provided. - `nil` value means to use the default maximum depth value. + @param checkStaleness Whether to throw FBStaleElementException if the found element is not present in DOM anymore @return element - @throws FBStaleElementException if the found element is not present in DOM anymore + @throws FBStaleElementException if `checkStaleness` is enabled @throws FBInvalidArgumentException if uuid is nil */ -- (XCUIElement *)elementForUUID:(NSString *)uuid - resolveForAdditionalAttributes:(nullable NSArray *)additionalAttributes - andMaxDepth:(nullable NSNumber *)maxDepth; +- (XCUIElement *)elementForUUID:(NSString *)uuid checkStaleness:(BOOL)checkStaleness; /** Checks element existence in the cache diff --git a/WebDriverAgentLib/Routing/FBElementCache.m b/WebDriverAgentLib/Routing/FBElementCache.m index 1f069bec6..3228f752c 100644 --- a/WebDriverAgentLib/Routing/FBElementCache.m +++ b/WebDriverAgentLib/Routing/FBElementCache.m @@ -26,7 +26,6 @@ @interface FBElementCache () @property (nonatomic, strong) LRUCache *elementCache; -@property (nonatomic) BOOL elementsNeedReset; @end @implementation FBElementCache @@ -38,7 +37,6 @@ - (instancetype)init return nil; } _elementCache = [[LRUCache alloc] initWithCapacity:ELEMENT_CACHE_SIZE]; - _elementsNeedReset = NO; return self; } @@ -50,19 +48,16 @@ - (NSString *)storeElement:(XCUIElement *)element } @synchronized (self.elementCache) { [self.elementCache setObject:element forKey:uuid]; - self.elementsNeedReset = YES; } return uuid; } - (XCUIElement *)elementForUUID:(NSString *)uuid { - return [self elementForUUID:uuid resolveForAdditionalAttributes:nil andMaxDepth:nil]; + return [self elementForUUID:uuid checkStaleness:NO]; } -- (XCUIElement *)elementForUUID:(NSString *)uuid - resolveForAdditionalAttributes:(NSArray *)additionalAttributes - andMaxDepth:(NSNumber *)maxDepth +- (XCUIElement *)elementForUUID:(NSString *)uuid checkStaleness:(BOOL)checkStaleness { if (!uuid) { NSString *reason = [NSString stringWithFormat:@"Cannot extract cached element for UUID: %@", uuid]; @@ -71,23 +66,15 @@ - (XCUIElement *)elementForUUID:(NSString *)uuid XCUIElement *element; @synchronized (self.elementCache) { - [self resetElements]; element = [self.elementCache objectForKey:uuid]; } if (nil == element) { NSString *reason = [NSString stringWithFormat:@"The element identified by \"%@\" is either not present or it has expired from the internal cache. Try to find it again", uuid]; @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}]; } - // This will throw FBStaleElementException exception if the element is stale - // or resolve the element and set lastSnapshot property - if (nil == additionalAttributes) { - [element fb_takeSnapshot]; - } else { - NSMutableArray *attributes = [NSMutableArray arrayWithArray:FBStandardAttributeNames()]; - [attributes addObjectsFromArray:additionalAttributes]; - [element fb_snapshotWithAttributes:attributes.copy maxDepth:maxDepth]; + if (checkStaleness) { + [element fb_takeSnapshot:NO]; } - element.fb_isResolvedFromCache = @(YES); return element; } @@ -101,20 +88,4 @@ - (BOOL)hasElementWithUUID:(NSString *)uuid } } -- (void)resetElements -{ - if (!self.elementsNeedReset) { - return; - } - - for (XCUIElement *element in self.elementCache.allObjects) { - element.lastSnapshot = nil; - if (nil != element.query) { - element.query.rootElementSnapshot = nil; - } - element.fb_isResolvedFromCache = @(NO); - } - self.elementsNeedReset = NO; -} - @end diff --git a/WebDriverAgentLib/Routing/FBResponsePayload.m b/WebDriverAgentLib/Routing/FBResponsePayload.m index 08fcd63fe..dcaa77403 100644 --- a/WebDriverAgentLib/Routing/FBResponsePayload.m +++ b/WebDriverAgentLib/Routing/FBResponsePayload.m @@ -91,13 +91,7 @@ inline NSDictionary *FBDictionaryResponseWithElement(XCUIElement *element, BOOL compact) { - id snapshot = nil; - if (nil != element.query.rootElementSnapshot) { - snapshot = element.fb_cachedSnapshot; - } - if (nil == snapshot) { - snapshot = element.lastSnapshot ?: element.fb_takeSnapshot; - } + id snapshot = element.lastSnapshot ?: element.fb_cachedSnapshot ?: [element fb_takeSnapshot:YES]; NSDictionary *compactResult = FBToElementDict((NSString *)[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]); if (compact) { return compactResult; diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index 7c337826c..ad9687b19 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -177,14 +177,6 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) { + (void)setKeyboardPrediction:(BOOL)isEnabled; + (FBConfigurationKeyboardPreference)keyboardPrediction; -/** - * The maximum time to wait until accessibility snapshot is taken - * - * @param timeout The number of float seconds to wait (15 seconds by default) - */ -+ (void)setCustomSnapshotTimeout:(NSTimeInterval)timeout; -+ (NSTimeInterval)customSnapshotTimeout; - /** Sets maximum depth for traversing elements tree from parents to children while requesting XCElementSnapshot. Used to set maxDepth value in a dictionary provided by XCAXClient_iOS's method defaultParams. diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index dab8cb4db..1065b892e 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -46,7 +46,6 @@ static BOOL FBShouldTerminateApp; static NSNumber* FBMaxTypingFrequency; static NSUInteger FBScreenshotQuality; -static NSTimeInterval FBCustomSnapshotTimeout; static BOOL FBShouldUseFirstMatch; static BOOL FBShouldBoundElementsByIndex; static BOOL FBIncludeNonModalElements; @@ -359,16 +358,6 @@ + (void)setKeyboardPrediction:(BOOL)isEnabled [self configureKeyboardsPreference:isEnabled forPreferenceKey:FBKeyboardPredictionKey]; } -+ (void)setCustomSnapshotTimeout:(NSTimeInterval)timeout -{ - FBCustomSnapshotTimeout = timeout; -} - -+ (NSTimeInterval)customSnapshotTimeout -{ - return FBCustomSnapshotTimeout; -} - + (void)setSnapshotMaxDepth:(int)maxDepth { FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @(maxDepth)); @@ -502,7 +491,6 @@ + (void)resetSessionSettings FBElementResponseAttributes = @"type,label"; FBMaxTypingFrequency = @([self defaultTypingFrequency]); FBScreenshotQuality = 3; - FBCustomSnapshotTimeout = 15.; FBShouldUseFirstMatch = NO; FBShouldBoundElementsByIndex = NO; // This is diabled by default because enabling it prevents the accessbility snapshot to be taken diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index b1f2f1fca..1a551c63f 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -22,9 +22,6 @@ extern NSString* const FB_SETTING_MJPEG_SCALING_FACTOR; extern NSString* const FB_SETTING_SCREENSHOT_QUALITY; extern NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION; extern NSString* const FB_SETTING_KEYBOARD_PREDICTION; -// This setting is deprecated. Please use CUSTOM_SNAPSHOT_TIMEOUT instead -extern NSString* const FB_SETTING_SNAPSHOT_TIMEOUT; -extern NSString* const FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT; extern NSString* const FB_SETTING_SNAPSHOT_MAX_DEPTH; extern NSString* const FB_SETTING_USE_FIRST_MATCH; extern NSString* const FB_SETTING_BOUND_ELEMENTS_BY_INDEX; diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index ada529eed..f5a61a8a8 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -18,8 +18,6 @@ NSString* const FB_SETTING_SCREENSHOT_QUALITY = @"screenshotQuality"; NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION = @"keyboardAutocorrection"; NSString* const FB_SETTING_KEYBOARD_PREDICTION = @"keyboardPrediction"; -NSString* const FB_SETTING_SNAPSHOT_TIMEOUT = @"snapshotTimeout"; -NSString* const FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT = @"customSnapshotTimeout"; NSString* const FB_SETTING_SNAPSHOT_MAX_DEPTH = @"snapshotMaxDepth"; NSString* const FB_SETTING_USE_FIRST_MATCH = @"useFirstMatch"; NSString* const FB_SETTING_BOUND_ELEMENTS_BY_INDEX = @"boundElementsByIndex"; diff --git a/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m b/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m index 11becfa72..4c42b1419 100644 --- a/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +++ b/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m @@ -57,9 +57,7 @@ - (instancetype)initWithTargetElement:(XCUIElement *)targetElement self = [super init]; if (self) { _targetElement = targetElement; - CGRect frame = targetElement.fb_isResolvedFromCache.boolValue - ? [FBXCElementSnapshotWrapper ensureWrapped:targetElement.lastSnapshot].wdFrame - : targetElement.wdFrame; + CGRect frame = targetElement.wdFrame; _targetCenter = FBRectGetCenter(frame); _navigationItems = [NSMutableDictionary dictionary]; } diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m index c488ca4ac..bd2dd3952 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m @@ -661,7 +661,7 @@ @implementation FBW3CActionsSynthesizer if ([origin isKindOfClass:XCUIElement.class]) { instance = origin; } else if ([origin isKindOfClass:NSString.class]) { - instance = [self.elementCache elementForUUID:(NSString *)origin]; + instance = [self.elementCache elementForUUID:(NSString *)origin checkStaleness:YES]; } else { [result addObject:actionItem]; continue; diff --git a/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h b/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h index cf6f497a9..45a8bcb34 100644 --- a/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +++ b/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h @@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable id)snapshotForElement:(id)element attributes:(nullable NSArray *)attributes - maxDepth:(nullable NSNumber *)maxDepth + inDepth:(BOOL)inDepth error:(NSError **)error; - (NSArray> *)activeApplications; @@ -39,8 +39,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)notifyWhenNoAnimationsAreActiveForApplication:(XCUIApplication *)application reply:(void (^)(void))reply; -- (NSDictionary *)attributesForElement:(id)element - attributes:(NSArray *)attributes; +- (nullable NSDictionary *)attributesForElement:(id)element + attributes:(NSArray *)attributes + error:(NSError**)error; - (XCUIApplication *)monitoredApplicationWithProcessIdentifier:(int)pid; diff --git a/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m b/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m index 907bb25b1..4c7c9cf27 100644 --- a/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +++ b/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m @@ -37,12 +37,12 @@ - (BOOL)setAXTimeout:(NSTimeInterval)timeout error:(NSError **)error - (id)snapshotForElement:(id)element attributes:(NSArray *)attributes - maxDepth:(nullable NSNumber *)maxDepth + inDepth:(BOOL)inDepth error:(NSError **)error { NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithDictionary:self.defaultParameters]; - if (nil != maxDepth) { - parameters[FBSnapshotMaxDepthKey] = maxDepth; + if (!inDepth) { + parameters[FBSnapshotMaxDepthKey] = @1; } id result = [FBAXClient requestSnapshotForElement:element @@ -76,15 +76,11 @@ - (void)notifyWhenNoAnimationsAreActiveForApplication:(XCUIApplication *)applica - (NSDictionary *)attributesForElement:(id)element attributes:(NSArray *)attributes + error:(NSError**)error; { - NSError *error = nil; - NSDictionary* result = [FBAXClient attributesForElement:element - attributes:attributes - error:&error]; - if (error) { - [FBLogger logFmt:@"Cannot retrieve element attribute(s) %@. Original error: %@", attributes, error.description]; - } - return result; + return [FBAXClient attributesForElement:element + attributes:attributes + error:error]; } - (XCUIApplication *)monitoredApplicationWithProcessIdentifier:(int)pid diff --git a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h index 0a7dd9a0c..f00f2e0b1 100644 --- a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +++ b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h @@ -10,6 +10,8 @@ #import #import "XCPointerEvent.h" +@class FBXCElementSnapshot; + /** The version of testmanagerd process which is running on the device. @@ -46,7 +48,7 @@ NS_ASSUME_NONNULL_BEGIN @param error The error instance if there was a failure while retrieveing the snapshot @returns The cached unqiue snapshot or nil if the element is stale */ -- (nullable XCElementSnapshot *)fb_uniqueSnapshotWithError:(NSError **)error; +- (nullable id)fb_uniqueSnapshotWithError:(NSError **)error; @end diff --git a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m index b13a79e55..b78dff6d2 100644 --- a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +++ b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m @@ -20,9 +20,9 @@ @implementation XCUIElementQuery (FBCompatibility) -- (XCElementSnapshot *)fb_uniqueSnapshotWithError:(NSError **)error +- (id)fb_uniqueSnapshotWithError:(NSError **)error { - return [self uniqueMatchingSnapshotWithError:error]; + return (id)[self uniqueMatchingSnapshotWithError:error]; } - (XCUIElement *)fb_firstMatch diff --git a/WebDriverAgentLib/Utilities/FBXPath.m b/WebDriverAgentLib/Utilities/FBXPath.m index eae3ee438..8a3cc2d60 100644 --- a/WebDriverAgentLib/Utilities/FBXPath.m +++ b/WebDriverAgentLib/Utilities/FBXPath.m @@ -368,15 +368,12 @@ + (int)writeXmlWithRootElement:(id)root NSArray> *children; if ([root isKindOfClass:XCUIElement.class]) { XCUIElement *element = (XCUIElement *)root; - NSMutableArray *snapshotAttributes = [NSMutableArray arrayWithArray:FBStandardAttributeNames()]; if (nil == includedAttributes || [includedAttributes containsObject:FBVisibleAttribute.class]) { - [snapshotAttributes addObject:FB_XCAXAIsVisibleAttributeName]; // If the app is not idle state while we retrieve the visiblity state // then the snapshot retrieval operation might freeze and time out [element.application fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; } - currentSnapshot = [element fb_snapshotWithAttributes:snapshotAttributes.copy - maxDepth:nil]; + currentSnapshot = [element fb_takeSnapshot:YES]; children = currentSnapshot.children; } else { currentSnapshot = (id)root; diff --git a/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h b/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h index 87199ff35..da99cfd58 100644 --- a/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h +++ b/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h @@ -19,6 +19,9 @@ extern NSString *FB_XCAXAIsVisibleAttributeName; extern NSNumber *FB_XCAXAIsElementAttribute; extern NSString *FB_XCAXAIsElementAttributeName; +/*! Accessibility identifier for visible frame attribute */ +extern NSString *FB_XCAXAVisibleFrameAttributeName; + /*! Getter for XCTest logger */ extern id (*XCDebugLogger)(void); diff --git a/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m b/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m index 861a78660..502a6f8b7 100644 --- a/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +++ b/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m @@ -18,6 +18,7 @@ NSString *FB_XCAXAIsVisibleAttributeName = @"XC_kAXXCAttributeIsVisible"; NSNumber *FB_XCAXAIsElementAttribute; NSString *FB_XCAXAIsElementAttributeName = @"XC_kAXXCAttributeIsElement"; +NSString *FB_XCAXAVisibleFrameAttributeName = @"XC_kAXXCAttributeVisibleFrame"; void (*XCSetDebugLogger)(id ); id (*XCDebugLogger)(void); diff --git a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m index 2d6f30c5b..7c094b600 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m @@ -71,6 +71,7 @@ - (void)testButtonAttributes XCTAssertEqualObjects(element.wdLabel, @"Button"); XCTAssertNil(element.wdValue); XCTAssertFalse(element.wdSelected); + XCTAssertTrue(element.fb_isVisible); [element tap]; XCTAssertTrue(element.wdValue.boolValue); XCTAssertTrue(element.wdSelected); @@ -133,7 +134,7 @@ - (void)testSliderAttributes XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeSlider"); XCTAssertNil(element.wdName); XCTAssertNil(element.wdLabel); - XCTAssertEqualObjects(element.wdValue, @"50%"); + XCTAssertTrue([element.wdValue containsString:@"50"]); } - (void)testActivityIndicatorAttributes diff --git a/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m b/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m index 0a9d2f5c4..ec5c853d0 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m @@ -72,7 +72,7 @@ - (void)testSwipeDownWithVelocity } [self.scrollView fb_swipeWithDirection:@"up" velocity:@2500]; FBAssertInvisibleCell(@"0"); - [self.scrollView fb_swipeWithDirection:@"down" velocity:@2500]; + [self.scrollView fb_swipeWithDirection:@"down" velocity:@3000]; FBAssertVisibleCell(@"0"); } diff --git a/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m index ccb996aa3..f7a3c7e02 100644 --- a/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m @@ -424,7 +424,7 @@ - (void)verifyPickerWheelPositionChangeWithGesture:(NSArray)destinationSnapshot { XCUIElement *matchingElement = self.testedView.buttons.allElementsBoundByIndex.firstObject; - FBAssertWaitTillBecomesTrue(nil != matchingElement.fb_takeSnapshot); + FBAssertWaitTillBecomesTrue(nil != [matchingElement fb_takeSnapshot:YES]); - id snapshot = matchingElement.fb_takeSnapshot; + id snapshot = matchingElement.lastSnapshot; // Over iOS13, snapshot returns a child. // The purpose of here is return a single element to replace children with an empty array for testing. snapshot.children = @[]; diff --git a/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m b/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m index 418c7869d..55d8852a8 100644 --- a/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m @@ -44,7 +44,8 @@ - (void)testDescendantsMatchingType @"Deadlock app", @"Touch", ]]; - NSArray> *matchingSnapshots = [[FBXCElementSnapshotWrapper ensureWrapped:self.testedView.fb_takeSnapshot] + NSArray> *matchingSnapshots = [[FBXCElementSnapshotWrapper ensureWrapped: + [self.testedView fb_takeSnapshot:YES]] fb_descendantsMatchingType:XCUIElementTypeButton]; XCTAssertEqual(matchingSnapshots.count, expectedLabels.count); NSArray *labels = [matchingSnapshots valueForKeyPath:@"@distinctUnionOfObjects.label"]; @@ -59,7 +60,8 @@ - (void)testParentMatchingType { XCUIElement *button = self.testedApplication.buttons[@"Alerts"]; FBAssertWaitTillBecomesTrue(button.exists); - id windowSnapshot = [[FBXCElementSnapshotWrapper ensureWrapped:button.fb_takeSnapshot] + id windowSnapshot = [[FBXCElementSnapshotWrapper ensureWrapped: + [self.testedView fb_takeSnapshot:YES]] fb_parentMatchingType:XCUIElementTypeWindow]; XCTAssertNotNil(windowSnapshot); XCTAssertEqual(windowSnapshot.elementType, XCUIElementTypeWindow); @@ -86,7 +88,8 @@ - (void)testParentMatchingOneOfTypes { XCUIElement *todayPickerWheel = self.testedApplication.pickerWheels[@"Today"]; FBAssertWaitTillBecomesTrue(todayPickerWheel.exists); - id datePicker = [[FBXCElementSnapshotWrapper ensureWrapped:todayPickerWheel.fb_takeSnapshot] + id datePicker = [[FBXCElementSnapshotWrapper ensureWrapped: + [todayPickerWheel fb_takeSnapshot:YES]] fb_parentMatchingOneOfTypes:@[@(XCUIElementTypeDatePicker), @(XCUIElementTypeWindow)]]; XCTAssertNotNil(datePicker); XCTAssertEqual(datePicker.elementType, XCUIElementTypeDatePicker); @@ -96,7 +99,8 @@ - (void)testParentMatchingOneOfTypesWithXCUIElementTypeAny { XCUIElement *todayPickerWheel = self.testedApplication.pickerWheels[@"Today"]; FBAssertWaitTillBecomesTrue(todayPickerWheel.exists); - id otherSnapshot =[[FBXCElementSnapshotWrapper ensureWrapped:todayPickerWheel.fb_takeSnapshot] + id otherSnapshot =[[FBXCElementSnapshotWrapper ensureWrapped: + [todayPickerWheel fb_takeSnapshot:YES]] fb_parentMatchingOneOfTypes:@[@(XCUIElementTypeAny)]]; XCTAssertNotNil(otherSnapshot); } @@ -105,7 +109,8 @@ - (void)testParentMatchingOneOfTypesWithAbsentParents { XCUIElement *todayPickerWheel = self.testedApplication.pickerWheels[@"Today"]; FBAssertWaitTillBecomesTrue(todayPickerWheel.exists); - id otherSnapshot = [[FBXCElementSnapshotWrapper ensureWrapped:todayPickerWheel.fb_takeSnapshot] + id otherSnapshot = [[FBXCElementSnapshotWrapper ensureWrapped: + [todayPickerWheel fb_takeSnapshot:YES]] fb_parentMatchingOneOfTypes:@[@(XCUIElementTypeTab), @(XCUIElementTypeLink)]]; XCTAssertNil(otherSnapshot); } @@ -136,8 +141,9 @@ - (void)testParentMatchingOneOfTypesWithFilter @(XCUIElementTypeCollectionView), @(XCUIElementTypeTable), ]; - id scrollView = [[FBXCElementSnapshotWrapper ensureWrapped:threeStaticText.fb_takeSnapshot] - fb_parentMatchingOneOfTypes:acceptedParents + id scrollView = [[FBXCElementSnapshotWrapper ensureWrapped: + [threeStaticText fb_takeSnapshot:YES]] + fb_parentMatchingOneOfTypes:acceptedParents filter:^BOOL(id snapshot) { return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] isWDVisible]; }]; @@ -153,7 +159,8 @@ - (void)testParentMatchingOneOfTypesWithFilterRetruningNo @(XCUIElementTypeCollectionView), @(XCUIElementTypeTable), ]; - id scrollView = [[FBXCElementSnapshotWrapper ensureWrapped:threeStaticText.fb_takeSnapshot] + id scrollView = [[FBXCElementSnapshotWrapper ensureWrapped: + [threeStaticText fb_takeSnapshot:YES]] fb_parentMatchingOneOfTypes:acceptedParents filter:^BOOL(id snapshot) { return NO; @@ -165,7 +172,9 @@ - (void)testDescendantsCellSnapshots { XCUIElement *scrollView = self.testedApplication.scrollViews[@"scrollView"]; FBAssertWaitTillBecomesTrue(self.testedApplication.staticTexts[@"3"].fb_isVisible); - NSArray *cells = [[FBXCElementSnapshotWrapper ensureWrapped:scrollView.fb_takeSnapshot] fb_descendantsCellSnapshots]; + NSArray *cells = [[FBXCElementSnapshotWrapper ensureWrapped: + [scrollView fb_takeSnapshot:YES]] + fb_descendantsCellSnapshots]; XCTAssertGreaterThanOrEqual(cells.count, 10); id element = cells.firstObject; XCTAssertEqualObjects(element.label, @"0"); @@ -192,7 +201,9 @@ - (void)testParentCellSnapshot { FBAssertWaitTillBecomesTrue(self.testedApplication.staticTexts[@"3"].fb_isVisible); XCUIElement *threeStaticText = self.testedApplication.staticTexts[@"3"]; - id xcuiElementCell = [[FBXCElementSnapshotWrapper ensureWrapped:threeStaticText.fb_takeSnapshot] fb_parentCellSnapshot]; + id xcuiElementCell = [[FBXCElementSnapshotWrapper ensureWrapped: + [threeStaticText fb_takeSnapshot:YES]] + fb_parentCellSnapshot]; XCTAssertEqual(xcuiElementCell.elementType, 75); } diff --git a/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m b/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m index 0acfe0f9c..b5635d6dc 100644 --- a/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m @@ -23,7 +23,7 @@ - (void)testAccessibilityActivationPoint [self launchApplication]; [self goToAttributesPage]; XCUIElement *dstBtn = self.testedApplication.buttons[@"not_accessible"]; - CGPoint hitPoint = [FBXCElementSnapshotWrapper ensureWrapped:dstBtn.fb_takeSnapshot].fb_hitPoint.CGPointValue; + CGPoint hitPoint = [FBXCElementSnapshotWrapper ensureWrapped:[dstBtn fb_takeSnapshot:NO]].fb_hitPoint.CGPointValue; XCTAssertTrue(hitPoint.x > 0 && hitPoint.y > 0); } diff --git a/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m index 496bd353d..17396d106 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m @@ -41,9 +41,11 @@ - (void)testDescendantsFiltering [allElements addObjectsFromArray:windows]; NSMutableArray> *buttonSnapshots = [NSMutableArray array]; - [buttonSnapshots addObject:[buttons.firstObject fb_takeSnapshot]]; - - NSArray *result = [self.testedApplication fb_filterDescendantsWithSnapshots:buttonSnapshots selfUID:nil onlyChildren:NO]; + [buttonSnapshots addObject:[buttons.firstObject fb_takeSnapshot:YES]]; + + NSArray *result = [self.testedApplication fb_filterDescendantsWithSnapshots:buttonSnapshots + selfUID:nil + onlyChildren:NO]; XCTAssertEqual(1, result.count); XCTAssertEqual([result.firstObject elementType], XCUIElementTypeButton); } diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m b/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m index d52c2904c..fc0814c1e 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +++ b/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m @@ -98,4 +98,14 @@ - (NSArray *)children return @[]; } +- (NSArray *)_allDescendants +{ + return @[]; +} + +- (CGRect)visibleFrame +{ + return CGRectZero; +} + @end diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h index d40945545..5720ef8ab 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h @@ -19,7 +19,6 @@ @property (nonatomic, readwrite, nullable) id lastSnapshot; @property (nonatomic, assign) BOOL fb_isObstructedByAlert; @property (nonatomic, readonly, nonnull) NSString *fb_cacheId; -@property (nonatomic, nullable) NSNumber *fb_isResolvedFromCache; @property (nonatomic, readwrite, copy, nonnull) NSDictionary *wdRect; @property (nonatomic, readwrite, assign) CGRect wdFrame; @property (nonatomic, readwrite, copy, nonnull) NSString *wdUID; @@ -39,7 +38,7 @@ @property (nonatomic, readwrite, getter=isWDAccessibilityContainer) BOOL wdAccessibilityContainer; - (void)resolve; -- (id _Nonnull)fb_takeSnapshot; +- (id _Nonnull)fb_takeSnapshot:(BOOL)inDepth; - (nullable id)query; // Checks diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m index e9792f132..9e65324b3 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m @@ -68,7 +68,7 @@ - (void)fb_nativeResolve self.didResolve = YES; } -- (id)fb_takeSnapshot +- (id _Nonnull)fb_takeSnapshot:(BOOL)inDepth; { return [self lastSnapshot]; } diff --git a/WebDriverAgentTests/UnitTests/FBElementCacheTests.m b/WebDriverAgentTests/UnitTests/FBElementCacheTests.m index e81a77300..79eed7ad0 100644 --- a/WebDriverAgentTests/UnitTests/FBElementCacheTests.m +++ b/WebDriverAgentTests/UnitTests/FBElementCacheTests.m @@ -43,10 +43,8 @@ - (void)testFetchingElement XCUIElement *element = (XCUIElement *)XCUIElementDouble.new; NSString *uuid = [self.cache storeElement:element]; XCTAssertNotNil(uuid, @"Stored index should be higher than 0"); - XCTAssertFalse(element.fb_isResolvedFromCache.boolValue); XCUIElement *cachedElement = [self.cache elementForUUID:uuid]; XCTAssertEqual(element, cachedElement); - XCTAssertTrue(element.fb_isResolvedFromCache.boolValue); } - (void)testFetchingBadIndex diff --git a/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h b/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h index cb43c334d..a57aec620 100644 --- a/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h +++ b/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h @@ -18,7 +18,6 @@ @property (nonatomic, readwrite, assign) CGRect frame; @property (nonatomic, readwrite, nullable) id lastSnapshot; @property (nonatomic, assign) BOOL fb_isObstructedByAlert; -@property (nonatomic, nullable) NSNumber *fb_isResolvedFromCache; @property (nonatomic, readwrite, copy, nonnull) NSDictionary *wdRect; @property (nonatomic, readwrite, assign) CGRect wdFrame; @property (nonatomic, readwrite, copy, nonnull) NSString *wdUID; From 43a9c654916295f33631487b094645597f887eb4 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 16 Jan 2025 16:47:45 +0000 Subject: [PATCH 149/368] chore(release): 9.0.0 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [9.0.0](https://github.com/appium/WebDriverAgent/compare/v8.12.2...v9.0.0) (2025-01-16) ### ⚠ BREAKING CHANGES * snapshotTimeout and customSnapshotTimeout settings have been removed as a result of the custom snapshotting logic removal ### Features * Refactor snapshotting mechanism ([#970](https://github.com/appium/WebDriverAgent/issues/970)) ([08f1306](https://github.com/appium/WebDriverAgent/commit/08f13060119c710f53b34a98c95683287c0365a0)) --- CHANGELOG.md | 10 ++++++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fe42c710..bef7aba1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [9.0.0](https://github.com/appium/WebDriverAgent/compare/v8.12.2...v9.0.0) (2025-01-16) + +### ⚠ BREAKING CHANGES + +* snapshotTimeout and customSnapshotTimeout settings have been removed as a result of the custom snapshotting logic removal + +### Features + +* Refactor snapshotting mechanism ([#970](https://github.com/appium/WebDriverAgent/issues/970)) ([08f1306](https://github.com/appium/WebDriverAgent/commit/08f13060119c710f53b34a98c95683287c0365a0)) + ## [8.12.2](https://github.com/appium/WebDriverAgent/compare/v8.12.1...v8.12.2) (2025-01-13) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index f263b2ad8..f7eb6cbcf 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.12.2 + 9.0.0 CFBundleSignature ???? CFBundleVersion - 8.12.2 + 9.0.0 NSPrincipalClass diff --git a/package.json b/package.json index 4134f04db..22852e428 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "8.12.2", + "version": "9.0.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From d8ce5c8ffe5366605fd419c484dd95409a784519 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 16 Jan 2025 10:44:33 -0800 Subject: [PATCH 150/368] ci: use master for actions/upload-artifact (#972) --- .github/workflows/wda-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/wda-package.yml b/.github/workflows/wda-package.yml index 8a7d7a526..642e9949e 100644 --- a/.github/workflows/wda-package.yml +++ b/.github/workflows/wda-package.yml @@ -57,11 +57,11 @@ jobs: ZIP_PKG_NAME: "${{ env.ZIP_PKG_NAME_TVOS }}" - name: Upload the built generic app package for iOS - uses: actions/upload-artifact@v3.1.0 + uses: actions/upload-artifact@master with: path: "${{ env.ZIP_PKG_NAME_IOS }}" - name: Upload the built generic app package for tvOS - uses: actions/upload-artifact@v3.1.0 + uses: actions/upload-artifact@master with: path: "${{ env.ZIP_PKG_NAME_TVOS }}" @@ -90,6 +90,6 @@ jobs: 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 + uses: actions/upload-artifact@master with: path: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" From c13a22767dd4b4001fd380ad3c76e22aa3e3194d Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 16 Jan 2025 13:23:55 -0800 Subject: [PATCH 151/368] ci: set proper name for each artifact (#974) * ci: add merge artifact * Update wda-package.yml * Update wda-package.yml --- .github/workflows/wda-package.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/wda-package.yml b/.github/workflows/wda-package.yml index 642e9949e..b89bec31f 100644 --- a/.github/workflows/wda-package.yml +++ b/.github/workflows/wda-package.yml @@ -29,7 +29,9 @@ jobs: runs-on: ${{ needs.host_machine.outputs.host }} env: + PKG_NAME_IOS: "WebDriverAgentRunner-Runner" ZIP_PKG_NAME_IOS: "WebDriverAgentRunner-Runner.zip" + PKG_NAME_TVOS: "WebDriverAgentRunner_tvOS-Runner" ZIP_PKG_NAME_TVOS: "WebDriverAgentRunner_tvOS-Runner.zip" steps: @@ -59,10 +61,12 @@ jobs: - name: Upload the built generic app package for iOS uses: actions/upload-artifact@master with: + name: "${{ env.PKG_NAME_IOS }}" path: "${{ env.ZIP_PKG_NAME_IOS }}" - name: Upload the built generic app package for tvOS uses: actions/upload-artifact@master with: + name: "${{ env.PKG_NAME_TVOS }}" path: "${{ env.ZIP_PKG_NAME_TVOS }}" for_simulator_devices: @@ -92,4 +96,5 @@ jobs: - name: Upload the built generic app package for WebDriverAgentRunner${{ matrix.target }} with ${{ matrix.arch }} uses: actions/upload-artifact@master with: + name: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}" path: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" From f2c752db4707b3864efb62b95b64abb487d28e4b Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 17 Jan 2025 09:06:01 +0100 Subject: [PATCH 152/368] chore: Optimize stable instance retrieval (#973) --- .../Categories/XCUIElement+FBFind.m | 1 - .../Categories/XCUIElement+FBPickerWheel.m | 3 ++- .../Categories/XCUIElement+FBResolve.h | 3 ++- .../Categories/XCUIElement+FBResolve.m | 22 +++++++---------- .../Categories/XCUIElement+FBUtilities.h | 3 --- .../Categories/XCUIElement+FBUtilities.m | 11 ++++----- .../Commands/FBElementCommands.m | 5 +++- .../Commands/FBFindElementCommands.m | 1 - WebDriverAgentLib/Routing/FBResponsePayload.m | 24 ++++++++++++++----- .../FBXPathIntegrationTests.m | 4 +--- .../IntegrationTests/XCUIElementFBFindTests.m | 6 ++++- .../XCUIElementHelperIntegrationTests.m | 1 - 12 files changed, 45 insertions(+), 39 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m index e799be557..aa58afb51 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m @@ -110,7 +110,6 @@ @implementation XCUIElement (FBFind) matchingSnapshots = @[snapshot]; } return [self fb_filterDescendantsWithSnapshots:matchingSnapshots - selfUID:self.fb_uid onlyChildren:NO]; } diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m index 881081fa1..975ab2afa 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m @@ -12,6 +12,7 @@ #import "FBRunLoopSpinner.h" #import "FBXCElementSnapshot.h" #import "FBXCodeCompatibility.h" +#import "XCUIElement+FBUID.h" #import "XCUICoordinate.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBResolve.h" @@ -33,7 +34,7 @@ - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)erro // Fetching stable instance of an element allows it to be bounded to the // 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; + XCUIElement *stableInstance = [self fb_stableInstanceWithUid:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]]; [endCoord tap]; return [[[[FBRunLoopSpinner new] timeout:VALUE_CHANGE_TIMEOUT] diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h index 80b218b06..f430e0b49 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h @@ -27,10 +27,11 @@ NS_ASSUME_NONNULL_BEGIN Although, if the cached element instance is the one returned by this API call then the same element is going to be matched and no staleness exception will be thrown. + @param uid Element UUID @return Either the same element instance if `fb_isResolvedNatively` was set to NO (usually the cache for elements matched by xpath locators) or the stable instance of the self element based on the query by element's UUID. */ -- (XCUIElement *)fb_stableInstance; +- (XCUIElement *)fb_stableInstanceWithUid:(NSString *)uid; @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m index f52c72bf6..66511bf7f 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m @@ -32,23 +32,19 @@ - (NSNumber *)fb_isResolvedNatively return nil == result ? @YES : result; } -- (XCUIElement *)fb_stableInstance +- (XCUIElement *)fb_stableInstanceWithUid:(NSString *)uid { - if (![self.fb_isResolvedNatively boolValue]) { + if (nil == uid || ![self.fb_isResolvedNatively boolValue] || [self isKindOfClass:XCUIApplication.class]) { return self; } - - XCUIElementQuery *query = [self isKindOfClass:XCUIApplication.class] - ? self.application.fb_query - : [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny]; - NSString *uid = nil == self.fb_cachedSnapshot - ? self.fb_uid - : [FBXCElementSnapshotWrapper wdUIDWithSnapshot:(id)self.fb_cachedSnapshot]; - if (nil == uid) { - return self; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K = %@", FBStringify(FBXCElementSnapshotWrapper, fb_uid), uid]; + XCUIElementQuery *query = [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny]; + XCUIElement *result = [query matchingPredicate:predicate].allElementsBoundByIndex.firstObject; + if (nil != result) { + result.fb_isResolvedNatively = @NO; + return result; } - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K = %@",FBStringify(FBXCElementSnapshotWrapper, fb_uid), uid]; - return [query matchingPredicate:predicate].allElementsBoundByIndex.firstObject ?: self; + return self; } @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h index a16e581f4..83a369da1 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h @@ -41,14 +41,11 @@ NS_ASSUME_NONNULL_BEGIN Filters elements by matching them to snapshots from the corresponding array @param snapshots Array of snapshots to be matched with - @param selfUID Optionally the unique identifier of the current element. - Providing it as an argument improves the performance of the method. @param onlyChildren Whether to only look for direct element children @return Array of filtered elements, which have matches in snapshots array */ - (NSArray *)fb_filterDescendantsWithSnapshots:(NSArray> *)snapshots - selfUID:(nullable NSString *)selfUID onlyChildren:(BOOL)onlyChildren; /** diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m index 7b6d52c03..9234ba8e3 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m @@ -71,7 +71,6 @@ @implementation XCUIElement (FBUtilities) } - (NSArray *)fb_filterDescendantsWithSnapshots:(NSArray> *)snapshots - selfUID:(NSString *)selfUID onlyChildren:(BOOL)onlyChildren { if (0 == snapshots.count) { @@ -85,13 +84,11 @@ @implementation XCUIElement (FBUtilities) } } NSMutableArray *matchedElements = [NSMutableArray array]; - NSString *uid = selfUID; - if (nil == uid) { - uid = self.fb_uid; - } + NSString *uid = nil == self.lastSnapshot + ? self.fb_uid + : [FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot]; if (nil != uid && [matchedIds containsObject:uid]) { - XCUIElement *stableSelf = self.fb_stableInstance; - stableSelf.fb_isResolvedNatively = @NO; + XCUIElement *stableSelf = [self fb_stableInstanceWithUid:uid]; if (1 == snapshots.count) { return @[stableSelf]; } diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 79fa30b8d..a03fbea41 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -35,6 +35,7 @@ #import "XCUIElement+FBWebDriverAttributes.h" #import "XCUIElement+FBTVFocuse.h" #import "XCUIElement+FBResolve.h" +#import "XCUIElement+FBUID.h" #import "FBElementTypeTransformer.h" #import "XCUIElement.h" #import "XCUIElementQuery.h" @@ -264,7 +265,9 @@ + (NSArray *)routes if (focusedElement != nil) { FBElementCache *elementCache = request.session.elementCache; BOOL useNativeCachingStrategy = request.session.useNativeCachingStrategy; - NSString *focusedUUID = [elementCache storeElement:(useNativeCachingStrategy ? focusedElement : focusedElement.fb_stableInstance)]; + NSString *focusedUUID = [elementCache storeElement:(useNativeCachingStrategy + ? focusedElement + : [focusedElement fb_stableInstanceWithUid:focusedElement.fb_uid])]; if (focusedUUID && [focusedUUID isEqualToString:(id)request.parameters[@"uuid"]]) { isFocused = YES; } diff --git a/WebDriverAgentLib/Commands/FBFindElementCommands.m b/WebDriverAgentLib/Commands/FBFindElementCommands.m index a92c5082e..0128d8ff7 100644 --- a/WebDriverAgentLib/Commands/FBFindElementCommands.m +++ b/WebDriverAgentLib/Commands/FBFindElementCommands.m @@ -87,7 +87,6 @@ + (NSArray *)routes && [FBXCElementSnapshotWrapper ensureWrapped:shot].wdVisible; }]; NSArray *cells = [element fb_filterDescendantsWithSnapshots:visibleCellSnapshots - selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot] onlyChildren:NO]; return FBResponseWithCachedElements(cells, request.session.elementCache, FBConfiguration.shouldUseCompactResponses); } diff --git a/WebDriverAgentLib/Routing/FBResponsePayload.m b/WebDriverAgentLib/Routing/FBResponsePayload.m index dcaa77403..d6a73472b 100644 --- a/WebDriverAgentLib/Routing/FBResponsePayload.m +++ b/WebDriverAgentLib/Routing/FBResponsePayload.m @@ -34,23 +34,35 @@ return FBResponseWithStatus([FBCommandStatus okWithValue:object]); } -id FBResponseWithCachedElement(XCUIElement *element, FBElementCache *elementCache, BOOL compact) +XCUIElement *maybeStable(XCUIElement *element) { BOOL useNativeCachingStrategy = nil == FBSession.activeSession ? YES : FBSession.activeSession.useNativeCachingStrategy; - [elementCache storeElement:(useNativeCachingStrategy ? element : element.fb_stableInstance)]; + if (useNativeCachingStrategy) { + return element; + } + + XCUIElement *result = element; + id snapshot = element.lastSnapshot ?: [element fb_cachedSnapshot] ?: [element fb_takeSnapshot:NO]; + NSString *uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]; + if (nil != uid) { + result = [element fb_stableInstanceWithUid:uid]; + } + return result; +} + +id FBResponseWithCachedElement(XCUIElement *element, FBElementCache *elementCache, BOOL compact) +{ + [elementCache storeElement:maybeStable(element)]; return FBResponseWithStatus([FBCommandStatus okWithValue:FBDictionaryResponseWithElement(element, compact)]); } id FBResponseWithCachedElements(NSArray *elements, FBElementCache *elementCache, BOOL compact) { NSMutableArray *elementsResponse = [NSMutableArray array]; - BOOL useNativeCachingStrategy = nil == FBSession.activeSession - ? YES - : FBSession.activeSession.useNativeCachingStrategy; for (XCUIElement *element in elements) { - [elementCache storeElement:(useNativeCachingStrategy ? element : element.fb_stableInstance)]; + [elementCache storeElement:maybeStable(element)]; [elementsResponse addObject:FBDictionaryResponseWithElement(element, compact)]; } return FBResponseWithStatus([FBCommandStatus okWithValue:elementsResponse]); diff --git a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m index a3b81c459..461a2ae94 100644 --- a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m @@ -43,9 +43,7 @@ - (void)setUp - (id)destinationSnapshot { XCUIElement *matchingElement = self.testedView.buttons.allElementsBoundByIndex.firstObject; - FBAssertWaitTillBecomesTrue(nil != [matchingElement fb_takeSnapshot:YES]); - - id snapshot = matchingElement.lastSnapshot; + id snapshot = [matchingElement fb_takeSnapshot:YES]; // Over iOS13, snapshot returns a child. // The purpose of here is return a single element to replace children with an empty array for testing. snapshot.children = @[]; diff --git a/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m b/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m index 713aee760..fb2b47e6d 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m @@ -15,6 +15,7 @@ #import "FBTestMacros.h" #import "XCUIElement.h" #import "XCUIElement+FBFind.h" +#import "XCUIElement+FBUID.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "XCUIElement+FBIsVisible.h" #import "XCUIElement+FBClassChain.h" @@ -93,7 +94,10 @@ - (void)testStableInstance NSArray *matchingSnapshots = [self.testedView fb_descendantsMatchingIdentifier:@"Alerts" shouldReturnAfterFirstMatch:YES]; XCTAssertEqual(matchingSnapshots.count, 1); - for (XCUIElement *el in @[matchingSnapshots.lastObject, matchingSnapshots.lastObject.fb_stableInstance]) { + for (XCUIElement *el in @[ + matchingSnapshots.lastObject, + [matchingSnapshots.lastObject fb_stableInstanceWithUid:[matchingSnapshots.lastObject fb_uid]] + ]) { XCTAssertEqual(el.elementType, XCUIElementTypeButton); XCTAssertEqualObjects(el.label, @"Alerts"); } diff --git a/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m index 17396d106..f04f9e158 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m @@ -44,7 +44,6 @@ - (void)testDescendantsFiltering [buttonSnapshots addObject:[buttons.firstObject fb_takeSnapshot:YES]]; NSArray *result = [self.testedApplication fb_filterDescendantsWithSnapshots:buttonSnapshots - selfUID:nil onlyChildren:NO]; XCTAssertEqual(1, result.count); XCTAssertEqual([result.firstObject elementType], XCUIElementTypeButton); From c296efabe83bf9b2fcd1650c06b363344c5535e0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 17 Jan 2025 08:08:50 +0000 Subject: [PATCH 153/368] chore(release): 9.0.1 [skip ci] ## [9.0.1](https://github.com/appium/WebDriverAgent/compare/v9.0.0...v9.0.1) (2025-01-17) ### Miscellaneous Chores * Optimize stable instance retrieval ([#973](https://github.com/appium/WebDriverAgent/issues/973)) ([f2c752d](https://github.com/appium/WebDriverAgent/commit/f2c752db4707b3864efb62b95b64abb487d28e4b)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bef7aba1f..66fb81d12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.0.1](https://github.com/appium/WebDriverAgent/compare/v9.0.0...v9.0.1) (2025-01-17) + +### Miscellaneous Chores + +* Optimize stable instance retrieval ([#973](https://github.com/appium/WebDriverAgent/issues/973)) ([f2c752d](https://github.com/appium/WebDriverAgent/commit/f2c752db4707b3864efb62b95b64abb487d28e4b)) + ## [9.0.0](https://github.com/appium/WebDriverAgent/compare/v8.12.2...v9.0.0) (2025-01-16) ### ⚠ BREAKING CHANGES diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index f7eb6cbcf..2d7429431 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.0.0 + 9.0.1 CFBundleSignature ???? CFBundleVersion - 9.0.0 + 9.0.1 NSPrincipalClass diff --git a/package.json b/package.json index 22852e428..185998d38 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.0.0", + "version": "9.0.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From ea3863a67d5cfa8bc2e48a1dc2c59052acd47937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgars=20Egl=C4=ABtis?= <37242620+eglitise@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:05:17 +0200 Subject: [PATCH 154/368] fix: update docs link in xcodebuild error message (#978) --- lib/xcodebuild.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/xcodebuild.js b/lib/xcodebuild.js index 54add615e..041d24ebe 100644 --- a/lib/xcodebuild.js +++ b/lib/xcodebuild.js @@ -36,6 +36,8 @@ const IGNORED_ERRORS_PATTERN = new RegExp( const RUNNER_SCHEME_TV = 'WebDriverAgentRunner_tvOS'; const LIB_SCHEME_TV = 'WebDriverAgentLib_tvOS'; +const REAL_DEVICES_CONFIG_DOCS_LINK = 'https://appium.github.io/appium-xcuitest-driver/latest/preparation/real-device-config/'; + const xcodeLog = logger.getLogger('Xcode'); @@ -378,8 +380,7 @@ export class XcodeBuild { ` 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.`; + ` for real iOS devices at ${REAL_DEVICES_CONFIG_DOCS_LINK}.`; } return reject(new Error(errorMessage)); } From a49a4858e351b109f92f97d226c5872fe9d2d543 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 3 Feb 2025 13:08:29 +0000 Subject: [PATCH 155/368] chore(release): 9.0.2 [skip ci] ## [9.0.2](https://github.com/appium/WebDriverAgent/compare/v9.0.1...v9.0.2) (2025-02-03) ### Bug Fixes * update docs link in xcodebuild error message ([#978](https://github.com/appium/WebDriverAgent/issues/978)) ([ea3863a](https://github.com/appium/WebDriverAgent/commit/ea3863a67d5cfa8bc2e48a1dc2c59052acd47937)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66fb81d12..5af870074 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.0.2](https://github.com/appium/WebDriverAgent/compare/v9.0.1...v9.0.2) (2025-02-03) + +### Bug Fixes + +* update docs link in xcodebuild error message ([#978](https://github.com/appium/WebDriverAgent/issues/978)) ([ea3863a](https://github.com/appium/WebDriverAgent/commit/ea3863a67d5cfa8bc2e48a1dc2c59052acd47937)) + ## [9.0.1](https://github.com/appium/WebDriverAgent/compare/v9.0.0...v9.0.1) (2025-01-17) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 2d7429431..e8593d550 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.0.1 + 9.0.2 CFBundleSignature ???? CFBundleVersion - 9.0.1 + 9.0.2 NSPrincipalClass diff --git a/package.json b/package.json index 185998d38..9fcbb31d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.0.1", + "version": "9.0.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 34b303c4e226d6a75a45a14eee7ca5e253e67737 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 5 Feb 2025 12:39:38 -0800 Subject: [PATCH 156/368] fix: add nullable signature (#979) --- WebDriverAgentLib/Categories/XCUIElement+FBResolve.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h index f430e0b49..e59ddd89f 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h @@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN @return Either the same element instance if `fb_isResolvedNatively` was set to NO (usually the cache for elements matched by xpath locators) or the stable instance of the self element based on the query by element's UUID. */ -- (XCUIElement *)fb_stableInstanceWithUid:(NSString *)uid; +- (XCUIElement *)fb_stableInstanceWithUid:(NSString *__nullable)uid; @end From 1a0402b76d85ab43cda736fcbce723382ece8079 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 5 Feb 2025 20:42:58 +0000 Subject: [PATCH 157/368] chore(release): 9.0.3 [skip ci] ## [9.0.3](https://github.com/appium/WebDriverAgent/compare/v9.0.2...v9.0.3) (2025-02-05) ### Bug Fixes * add nullable signature ([#979](https://github.com/appium/WebDriverAgent/issues/979)) ([34b303c](https://github.com/appium/WebDriverAgent/commit/34b303c4e226d6a75a45a14eee7ca5e253e67737)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5af870074..cc77dfa3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.0.3](https://github.com/appium/WebDriverAgent/compare/v9.0.2...v9.0.3) (2025-02-05) + +### Bug Fixes + +* add nullable signature ([#979](https://github.com/appium/WebDriverAgent/issues/979)) ([34b303c](https://github.com/appium/WebDriverAgent/commit/34b303c4e226d6a75a45a14eee7ca5e253e67737)) + ## [9.0.2](https://github.com/appium/WebDriverAgent/compare/v9.0.1...v9.0.2) (2025-02-03) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index e8593d550..85644c02f 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.0.2 + 9.0.3 CFBundleSignature ???? CFBundleVersion - 9.0.2 + 9.0.3 NSPrincipalClass diff --git a/package.json b/package.json index 9fcbb31d2..cf3a4f8ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.0.2", + "version": "9.0.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 19efbdd69ff9edff20c0c318bd39c29963d4d51d Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 21 Feb 2025 08:35:42 +0100 Subject: [PATCH 158/368] fix: Accept reqBasePath proxy option (#982) --- lib/webdriveragent.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index e47b9c752..a2a9dbb0d 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -585,6 +585,9 @@ export class WebDriverAgent { timeout: this.wdaConnectionTimeout, keepAlive: true, }; + if (this.args.reqBasePath) { + proxyOpts.reqBasePath = this.args.reqBasePath; + } this.jwproxy = new JWProxy(proxyOpts); this.jwproxy.sessionId = sessionId; From d99087404008f586483427bf29d7607dee58ebfc Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 21 Feb 2025 07:38:25 +0000 Subject: [PATCH 159/368] chore(release): 9.0.4 [skip ci] ## [9.0.4](https://github.com/appium/WebDriverAgent/compare/v9.0.3...v9.0.4) (2025-02-21) ### Bug Fixes * Accept reqBasePath proxy option ([#982](https://github.com/appium/WebDriverAgent/issues/982)) ([19efbdd](https://github.com/appium/WebDriverAgent/commit/19efbdd69ff9edff20c0c318bd39c29963d4d51d)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc77dfa3d..33ad8c0a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.0.4](https://github.com/appium/WebDriverAgent/compare/v9.0.3...v9.0.4) (2025-02-21) + +### Bug Fixes + +* Accept reqBasePath proxy option ([#982](https://github.com/appium/WebDriverAgent/issues/982)) ([19efbdd](https://github.com/appium/WebDriverAgent/commit/19efbdd69ff9edff20c0c318bd39c29963d4d51d)) + ## [9.0.3](https://github.com/appium/WebDriverAgent/compare/v9.0.2...v9.0.3) (2025-02-05) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 85644c02f..e218b456c 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.0.3 + 9.0.4 CFBundleSignature ???? CFBundleVersion - 9.0.3 + 9.0.4 NSPrincipalClass diff --git a/package.json b/package.json index cf3a4f8ae..1d7711f37 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.0.3", + "version": "9.0.4", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From f92f1cde0fe914086103a110844bbe3bc0e3c4a6 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Thu, 27 Feb 2025 00:47:18 +0530 Subject: [PATCH 160/368] fix: add autorelease pool to drain temporary objects (#983) --- .../Categories/XCUIApplication+FBHelpers.m | 60 ++++++++++-------- .../Categories/XCUIElement+FBFind.m | 4 +- .../Categories/XCUIElement+FBIsVisible.m | 10 ++- .../Categories/XCUIElement+FBResolve.m | 12 ++-- .../Categories/XCUIElement+FBScrolling.m | 32 +++++----- .../Categories/XCUIElement+FBUtilities.m | 40 ++++++------ WebDriverAgentLib/Routing/FBResponsePayload.m | 61 ++++++++++--------- WebDriverAgentLib/Utilities/FBXPath.m | 32 +++++----- .../Utilities/NSPredicate+FBFormat.m | 6 +- 9 files changed, 145 insertions(+), 112 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index 03d4407f2..ac3d07ce9 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -238,9 +238,11 @@ + (NSDictionary *)dictionaryForElement:(id)snapshot if ([childElements count]) { info[@"children"] = [[NSMutableArray alloc] init]; for (id childSnapshot in childElements) { - [info[@"children"] addObject:[self dictionaryForElement:childSnapshot - recursive:YES - excludedAttributes:excludedAttributes]]; + @autoreleasepool { + [info[@"children"] addObject:[self dictionaryForElement:childSnapshot + recursive:YES + excludedAttributes:excludedAttributes]]; + } } } return info; @@ -262,9 +264,11 @@ + (NSDictionary *)accessibilityInfoForElement:(id)snapshot } else { NSMutableArray *children = [[NSMutableArray alloc] init]; for (id childSnapshot in snapshot.children) { - NSDictionary *childInfo = [self accessibilityInfoForElement:childSnapshot]; - if ([childInfo count]) { - [children addObject: childInfo]; + @autoreleasepool { + NSDictionary *childInfo = [self accessibilityInfoForElement:childSnapshot]; + if ([childInfo count]) { + [children addObject: childInfo]; + } } } if ([children count]) { @@ -420,31 +424,33 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames [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]; - } - - id extractedElement = extractIssueProperty(issue, @"element"); - - id elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_takeSnapshot:NO]; - NSDictionary *elementAttributes = elementSnapshot + @autoreleasepool { + NSString *auditType = @""; + NSDictionary *valuesToNamesMap = auditTypeValuesToNames(); + NSNumber *auditTypeValue = [issue valueForKey:@"auditType"]; + if (nil != auditTypeValue) { + auditType = valuesToNamesMap[auditTypeValue] ?: [auditTypeValue stringValue]; + } + + id extractedElement = extractIssueProperty(issue, @"element"); + + id elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_takeSnapshot:NO]; + NSDictionary *elementAttributes = elementSnapshot ? [self.class dictionaryForElement:elementSnapshot recursive:NO excludedAttributes:customAttributesToExclude] : @{}; - - [resultArray addObject:@{ - @"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"", - @"compactDescription": extractIssueProperty(issue, @"compactDescription") ?: @"", - @"auditType": auditType, - @"element": [extractedElement description] ?: @"", - @"elementDescription": [extractedElement debugDescription] ?: @"", - @"elementAttributes": elementAttributes ?: @{}, - }]; - return YES; + + [resultArray addObject:@{ + @"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"", + @"compactDescription": extractIssueProperty(issue, @"compactDescription") ?: @"", + @"auditType": auditType, + @"element": [extractedElement description] ?: @"", + @"elementDescription": [extractedElement debugDescription] ?: @"", + @"elementAttributes": elementAttributes ?: @{}, + }]; + return YES; + } }; [invocation setArgument:&issueHandler atIndex:3]; [invocation setArgument:&error atIndex:4]; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m index aa58afb51..d33fce1ea 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m @@ -121,7 +121,9 @@ @implementation XCUIElement (FBFind) { NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id snapshot, NSDictionary * _Nullable bindings) { - return [[FBXCElementSnapshotWrapper wdNameWithSnapshot:snapshot] isEqualToString:accessibilityId]; + @autoreleasepool { + return [[FBXCElementSnapshotWrapper wdNameWithSnapshot:snapshot] isEqualToString:accessibilityId]; + } }]; return [self fb_descendantsMatchingPredicate:predicate shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch]; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m index 80ee1bd9b..aa1f7c28d 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m @@ -25,8 +25,10 @@ @implementation XCUIElement (FBIsVisible) - (BOOL)fb_isVisible { - id snapshot = [self fb_takeSnapshot:NO]; - return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isVisible; + @autoreleasepool { + id snapshot = [self fb_takeSnapshot:NO]; + return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isVisible; + } } @end @@ -64,7 +66,9 @@ - (BOOL)fb_isVisible NSMutableDictionary *updatedValue = [NSMutableDictionary dictionaryWithDictionary:self.additionalAttributes ?: @{}]; [updatedValue setObject:attributeValue forKey:FB_XCAXAIsVisibleAttribute]; self.snapshot.additionalAttributes = updatedValue.copy; - return [attributeValue boolValue]; + @autoreleasepool { + return [attributeValue boolValue]; + } } NSLog(@"Cannot determine visiblity of %@ natively: %@. Defaulting to: %@", diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m index 66511bf7f..43882b077 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m @@ -38,11 +38,13 @@ - (XCUIElement *)fb_stableInstanceWithUid:(NSString *)uid return self; } NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K = %@", FBStringify(FBXCElementSnapshotWrapper, fb_uid), uid]; - XCUIElementQuery *query = [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny]; - XCUIElement *result = [query matchingPredicate:predicate].allElementsBoundByIndex.firstObject; - if (nil != result) { - result.fb_isResolvedNatively = @NO; - return result; + @autoreleasepool { + XCUIElementQuery *query = [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny]; + XCUIElement *result = [query matchingPredicate:predicate].allElementsBoundByIndex.firstObject; + if (nil != result) { + result.fb_isResolvedNatively = @NO; + return result; + } } return self; } diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m index 4ebd14b32..23177131a 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m @@ -178,23 +178,25 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll FBXCElementSnapshotWrapper *scrollViewWrapped = [FBXCElementSnapshotWrapper ensureWrapped:scrollView]; // Scrolling till cell is visible and get current value of frames while (![self fb_isEquivalentElementSnapshotVisible:prescrollSnapshot] && scrollCount < maxScrollCount) { - if (targetCellIndex < visibleCellIndex) { - scrollDirection == FBXCUIElementScrollDirectionVertical ? - [scrollViewWrapped fb_scrollUpByNormalizedDistance:normalizedScrollDistance - inApplication:self.application] : - [scrollViewWrapped fb_scrollLeftByNormalizedDistance:normalizedScrollDistance - inApplication:self.application]; - } - else { - scrollDirection == FBXCUIElementScrollDirectionVertical ? - [scrollViewWrapped fb_scrollDownByNormalizedDistance:normalizedScrollDistance + @autoreleasepool { + if (targetCellIndex < visibleCellIndex) { + scrollDirection == FBXCUIElementScrollDirectionVertical ? + [scrollViewWrapped fb_scrollUpByNormalizedDistance:normalizedScrollDistance inApplication:self.application] : - [scrollViewWrapped fb_scrollRightByNormalizedDistance:normalizedScrollDistance - inApplication:self.application]; + [scrollViewWrapped fb_scrollLeftByNormalizedDistance:normalizedScrollDistance + inApplication:self.application]; + } + else { + scrollDirection == FBXCUIElementScrollDirectionVertical ? + [scrollViewWrapped fb_scrollDownByNormalizedDistance:normalizedScrollDistance + inApplication:self.application] : + [scrollViewWrapped fb_scrollRightByNormalizedDistance:normalizedScrollDistance + inApplication:self.application]; + } + scrollCount++; + // Wait for scroll animation + [self fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; } - scrollCount++; - // Wait for scroll animation - [self fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; } if (scrollCount >= maxScrollCount) { diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m index 9234ba8e3..26e274c18 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m @@ -46,22 +46,26 @@ @implementation XCUIElement (FBUtilities) - (id)fb_takeSnapshot:(BOOL)inDepth { - NSError *error = nil; - self.lastSnapshot = inDepth - ? [self.fb_query fb_uniqueSnapshotWithError:&error] - : (id)[self snapshotWithError:&error]; - if (nil == self.lastSnapshot) { - NSString *hintText = @"Make sure the application UI has the expected state"; - if (nil != error && [error.localizedDescription containsString:@"Identity Binding"]) { - hintText = [NSString stringWithFormat:@"%@. You could also try to switch the binding strategy using the 'boundElementsByIndex' setting for the element lookup", hintText]; + __block id snapshot = nil; + @autoreleasepool { + NSError *error = nil; + snapshot = inDepth + ? [self.fb_query fb_uniqueSnapshotWithError:&error] + : (id)[self snapshotWithError:&error]; + if (nil == snapshot) { + NSString *hintText = @"Make sure the application UI has the expected state"; + if (nil != error && [error.localizedDescription containsString:@"Identity Binding"]) { + hintText = [NSString stringWithFormat:@"%@. You could also try to switch the binding strategy using the 'boundElementsByIndex' setting for the element lookup", hintText]; + } + NSString *reason = [NSString stringWithFormat:@"The previously found element \"%@\" is not present in the current view anymore. %@", + self.description, hintText]; + if (nil != error) { + reason = [NSString stringWithFormat:@"%@. Original error: %@", reason, error.localizedDescription]; + } + @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}]; } - NSString *reason = [NSString stringWithFormat:@"The previously found element \"%@\" is not present in the current view anymore. %@", - self.description, hintText]; - if (nil != error) { - reason = [NSString stringWithFormat:@"%@. Original error: %@", reason, error.localizedDescription]; - } - @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}]; } + self.lastSnapshot = snapshot; return self.lastSnapshot; } @@ -78,9 +82,11 @@ @implementation XCUIElement (FBUtilities) } NSMutableArray *matchedIds = [NSMutableArray new]; for (id snapshot in snapshots) { - NSString *uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]; - if (nil != uid) { - [matchedIds addObject:uid]; + @autoreleasepool { + NSString *uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]; + if (nil != uid) { + [matchedIds addObject:uid]; + } } } NSMutableArray *matchedElements = [NSMutableArray array]; diff --git a/WebDriverAgentLib/Routing/FBResponsePayload.m b/WebDriverAgentLib/Routing/FBResponsePayload.m index d6a73472b..f17517633 100644 --- a/WebDriverAgentLib/Routing/FBResponsePayload.m +++ b/WebDriverAgentLib/Routing/FBResponsePayload.m @@ -103,35 +103,40 @@ inline NSDictionary *FBDictionaryResponseWithElement(XCUIElement *element, BOOL compact) { - id snapshot = element.lastSnapshot ?: element.fb_cachedSnapshot ?: [element fb_takeSnapshot:YES]; - NSDictionary *compactResult = FBToElementDict((NSString *)[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]); - if (compact) { - return compactResult; - } + __block NSDictionary *elementResponse = nil; + @autoreleasepool { + id snapshot = element.lastSnapshot ?: element.fb_cachedSnapshot ?: [element fb_takeSnapshot:YES]; + NSDictionary *compactResult = FBToElementDict((NSString *)[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]); + if (compact) { + elementResponse = compactResult; + return elementResponse; + } - NSMutableDictionary *result = compactResult.mutableCopy; - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; - NSArray *fields = [FBConfiguration.elementResponseAttributes componentsSeparatedByString:@","]; - for (NSString *field in fields) { - // 'name' here is the w3c-approved identifier for what we mean by 'type' - if ([field isEqualToString:@"name"] || [field isEqualToString:@"type"]) { - result[field] = wrappedSnapshot.wdType; - } else if ([field isEqualToString:@"text"]) { - result[field] = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel) ?: [NSNull null]; - } else if ([field isEqualToString:@"rect"]) { - result[field] = wrappedSnapshot.wdRect; - } else if ([field isEqualToString:@"enabled"]) { - result[field] = @(wrappedSnapshot.wdEnabled); - } else if ([field isEqualToString:@"displayed"]) { - result[field] = @(wrappedSnapshot.wdVisible); - } else if ([field isEqualToString:@"selected"]) { - result[field] = @(wrappedSnapshot.wdSelected); - } else if ([field isEqualToString:@"label"]) { - result[field] = wrappedSnapshot.wdLabel ?: [NSNull null]; - } else if ([field hasPrefix:arbitraryAttrPrefix]) { - NSString *attributeName = [field substringFromIndex:[arbitraryAttrPrefix length]]; - result[field] = [wrappedSnapshot fb_valueForWDAttributeName:attributeName] ?: [NSNull null]; + NSMutableDictionary *result = compactResult.mutableCopy; + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; + NSArray *fields = [FBConfiguration.elementResponseAttributes componentsSeparatedByString:@","]; + for (NSString *field in fields) { + // 'name' here is the w3c-approved identifier for what we mean by 'type' + if ([field isEqualToString:@"name"] || [field isEqualToString:@"type"]) { + result[field] = wrappedSnapshot.wdType; + } else if ([field isEqualToString:@"text"]) { + result[field] = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel) ?: [NSNull null]; + } else if ([field isEqualToString:@"rect"]) { + result[field] = wrappedSnapshot.wdRect; + } else if ([field isEqualToString:@"enabled"]) { + result[field] = @(wrappedSnapshot.wdEnabled); + } else if ([field isEqualToString:@"displayed"]) { + result[field] = @(wrappedSnapshot.wdVisible); + } else if ([field isEqualToString:@"selected"]) { + result[field] = @(wrappedSnapshot.wdSelected); + } else if ([field isEqualToString:@"label"]) { + result[field] = wrappedSnapshot.wdLabel ?: [NSNull null]; + } else if ([field hasPrefix:arbitraryAttrPrefix]) { + NSString *attributeName = [field substringFromIndex:[arbitraryAttrPrefix length]]; + result[field] = [wrappedSnapshot fb_valueForWDAttributeName:attributeName] ?: [NSNull null]; + } } + elementResponse = result.copy; } - return result.copy; + return elementResponse; } diff --git a/WebDriverAgentLib/Utilities/FBXPath.m b/WebDriverAgentLib/Utilities/FBXPath.m index 8a3cc2d60..6276cfae6 100644 --- a/WebDriverAgentLib/Utilities/FBXPath.m +++ b/WebDriverAgentLib/Utilities/FBXPath.m @@ -364,7 +364,7 @@ + (int)writeXmlWithRootElement:(id)root { NSAssert((indexPath == nil && elementStore == nil) || (indexPath != nil && elementStore != nil), @"Either both or none of indexPath and elementStore arguments should be equal to nil", nil); - id currentSnapshot; + __block id currentSnapshot; NSArray> *children; if ([root isKindOfClass:XCUIElement.class]) { XCUIElement *element = (XCUIElement *)root; @@ -373,7 +373,9 @@ + (int)writeXmlWithRootElement:(id)root // then the snapshot retrieval operation might freeze and time out [element.application fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; } - currentSnapshot = [element fb_takeSnapshot:YES]; + @autoreleasepool { + currentSnapshot = [element fb_takeSnapshot:YES]; + } children = currentSnapshot.children; } else { currentSnapshot = (id)root; @@ -400,18 +402,20 @@ + (int)writeXmlWithRootElement:(id)root } for (NSUInteger i = 0; i < [children count]; i++) { - id childSnapshot = [children objectAtIndex:i]; - NSString *newIndexPath = (indexPath != nil) ? [indexPath stringByAppendingFormat:@",%lu", (unsigned long)i] : nil; - if (elementStore != nil && newIndexPath != nil) { - [elementStore setObject:childSnapshot forKey:(id)newIndexPath]; - } - rc = [self writeXmlWithRootElement:[FBXCElementSnapshotWrapper ensureWrapped:childSnapshot] - indexPath:newIndexPath - elementStore:elementStore - includedAttributes:includedAttributes - writer:writer]; - if (rc < 0) { - return rc; + @autoreleasepool { + id childSnapshot = [children objectAtIndex:i]; + NSString *newIndexPath = (indexPath != nil) ? [indexPath stringByAppendingFormat:@",%lu", (unsigned long)i] : nil; + if (elementStore != nil && newIndexPath != nil) { + [elementStore setObject:childSnapshot forKey:(id)newIndexPath]; + } + rc = [self writeXmlWithRootElement:[FBXCElementSnapshotWrapper ensureWrapped:childSnapshot] + indexPath:newIndexPath + elementStore:elementStore + includedAttributes:includedAttributes + writer:writer]; + if (rc < 0) { + return rc; + } } } diff --git a/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m b/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m index 8a033e707..2b20fcaa5 100644 --- a/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m +++ b/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m @@ -59,8 +59,10 @@ + (instancetype)fb_snapshotBlockPredicateWithPredicate:(NSPredicate *)input NSPredicate *wdPredicate = [self.class fb_formatSearchPredicate:input]; return [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary * _Nullable bindings) { - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:evaluatedObject]; - return [wdPredicate evaluateWithObject:wrappedSnapshot]; + @autoreleasepool { + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:evaluatedObject]; + return [wdPredicate evaluateWithObject:wrappedSnapshot]; + } }]; } From 4f0dfee950626d5a105ad73a914a3146ddb0f8ca Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 26 Feb 2025 19:20:03 +0000 Subject: [PATCH 161/368] chore(release): 9.0.5 [skip ci] ## [9.0.5](https://github.com/appium/WebDriverAgent/compare/v9.0.4...v9.0.5) (2025-02-26) ### Bug Fixes * add autorelease pool to drain temporary objects ([#983](https://github.com/appium/WebDriverAgent/issues/983)) ([f92f1cd](https://github.com/appium/WebDriverAgent/commit/f92f1cde0fe914086103a110844bbe3bc0e3c4a6)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33ad8c0a5..632761867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.0.5](https://github.com/appium/WebDriverAgent/compare/v9.0.4...v9.0.5) (2025-02-26) + +### Bug Fixes + +* add autorelease pool to drain temporary objects ([#983](https://github.com/appium/WebDriverAgent/issues/983)) ([f92f1cd](https://github.com/appium/WebDriverAgent/commit/f92f1cde0fe914086103a110844bbe3bc0e3c4a6)) + ## [9.0.4](https://github.com/appium/WebDriverAgent/compare/v9.0.3...v9.0.4) (2025-02-21) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index e218b456c..746b99d25 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.0.4 + 9.0.5 CFBundleSignature ???? CFBundleVersion - 9.0.4 + 9.0.5 NSPrincipalClass diff --git a/package.json b/package.json index 1d7711f37..34c9e9db5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.0.4", + "version": "9.0.5", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 46dc417da9f4a843838b414c0b154d6f478dbc0b Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Fri, 28 Feb 2025 20:32:28 +0530 Subject: [PATCH 162/368] fix: optimize LRU cache (#985) --- WebDriverAgentLib/Routing/FBElementCache.m | 12 +++++++- .../Utilities/LRUCache/LRUCache.h | 7 +++++ .../Utilities/LRUCache/LRUCache.m | 8 +++++ .../UnitTests/FBLRUCacheTests.m | 29 +++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Routing/FBElementCache.m b/WebDriverAgentLib/Routing/FBElementCache.m index 3228f752c..b87ec8cf5 100644 --- a/WebDriverAgentLib/Routing/FBElementCache.m +++ b/WebDriverAgentLib/Routing/FBElementCache.m @@ -73,7 +73,17 @@ - (XCUIElement *)elementForUUID:(NSString *)uuid checkStaleness:(BOOL)checkStale @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}]; } if (checkStaleness) { - [element fb_takeSnapshot:NO]; + @try { + [element fb_takeSnapshot:NO]; + } @catch (NSException *exception) { + // if the snapshot method threw FBStaleElementException (implying the element is stale) we need to explicitly remove it from the cache, PR: https://github.com/appium/WebDriverAgent/pull/985 + if ([exception.name isEqualToString:FBStaleElementException]) { + @synchronized (self.elementCache) { + [self.elementCache removeObjectForKey:uuid]; + } + } + @throw exception; + } } return element; } diff --git a/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h b/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h index 70614235f..dbfb4cfbc 100644 --- a/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h +++ b/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h @@ -54,6 +54,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSArray *)allObjects; +/** + Removes the object associated with the specified key from the cache. + + @param key The key identifying the object to remove. + */ +- (void)removeObjectForKey:(id)key; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m b/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m index 4f3a9ad0d..731d74404 100644 --- a/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m +++ b/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m @@ -135,4 +135,12 @@ - (void)alignSize } } +- (void)removeObjectForKey:(id)key +{ + LRUCacheNode *node = self.store[key]; + if (node != nil) { + [self removeNode:node]; + } +} + @end diff --git a/WebDriverAgentTests/UnitTests/FBLRUCacheTests.m b/WebDriverAgentTests/UnitTests/FBLRUCacheTests.m index 6d8438734..6f788a253 100644 --- a/WebDriverAgentTests/UnitTests/FBLRUCacheTests.m +++ b/WebDriverAgentTests/UnitTests/FBLRUCacheTests.m @@ -96,4 +96,33 @@ - (void)testInsertionLoop XCTAssertEqualObjects(@[@(count)], cache.allObjects); } +- (void)testRemoveExistingObjectForKey { + LRUCache *cache = [[LRUCache alloc] initWithCapacity:3]; + [cache setObject:@"foo" forKey:@"bar"]; + [cache setObject:@"foo2" forKey:@"bar2"]; + [cache setObject:@"foo3" forKey:@"bar3"]; + [self assertArray:@[@"foo3", @"foo2", @"foo"] equalsTo:cache.allObjects]; + [cache removeObjectForKey:@"bar2"]; + XCTAssertNil([cache objectForKey:@"bar2"]); + [self assertArray:@[@"foo3", @"foo"] equalsTo:cache.allObjects]; +} + +- (void)testRemoveNonExistingObjectForKey { + LRUCache *cache = [[LRUCache alloc] initWithCapacity:2]; + [cache setObject:@"foo" forKey:@"bar"]; + [cache removeObjectForKey:@"nonExisting"]; + XCTAssertNotNil([cache objectForKey:@"bar"]); + [self assertArray:@[@"foo"] equalsTo:cache.allObjects]; +} + +- (void)testRemoveAndInsertFlow { + LRUCache *cache = [[LRUCache alloc] initWithCapacity:2]; + [cache setObject:@"foo" forKey:@"bar"]; + [cache setObject:@"foo2" forKey:@"bar2"]; + [cache removeObjectForKey:@"bar"]; + XCTAssertNil([cache objectForKey:@"bar"]); + [cache setObject:@"foo3" forKey:@"bar3"]; + [self assertArray:@[@"foo3", @"foo2"] equalsTo:cache.allObjects]; +} + @end From d7cff1a389586f3f492cfd789175e21d838f21da Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 28 Feb 2025 15:06:27 +0000 Subject: [PATCH 163/368] chore(release): 9.0.6 [skip ci] ## [9.0.6](https://github.com/appium/WebDriverAgent/compare/v9.0.5...v9.0.6) (2025-02-28) ### Bug Fixes * optimize LRU cache ([#985](https://github.com/appium/WebDriverAgent/issues/985)) ([46dc417](https://github.com/appium/WebDriverAgent/commit/46dc417da9f4a843838b414c0b154d6f478dbc0b)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 632761867..169152856 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.0.6](https://github.com/appium/WebDriverAgent/compare/v9.0.5...v9.0.6) (2025-02-28) + +### Bug Fixes + +* optimize LRU cache ([#985](https://github.com/appium/WebDriverAgent/issues/985)) ([46dc417](https://github.com/appium/WebDriverAgent/commit/46dc417da9f4a843838b414c0b154d6f478dbc0b)) + ## [9.0.5](https://github.com/appium/WebDriverAgent/compare/v9.0.4...v9.0.5) (2025-02-26) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 746b99d25..39be9a6fe 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.0.5 + 9.0.6 CFBundleSignature ???? CFBundleVersion - 9.0.5 + 9.0.6 NSPrincipalClass diff --git a/package.json b/package.json index 34c9e9db5..95f0b1b33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.0.5", + "version": "9.0.6", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 8c3a1cb30655ed8d1a77d25bbeca71ee48c2ec3e Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sun, 9 Mar 2025 00:37:45 -0800 Subject: [PATCH 164/368] feat: add placeholderValue (#987) * initial implementation * add tests * update tests * update test --- .../XCUIElement+FBWebDriverAttributes.m | 9 +++++++++ WebDriverAgentLib/Routing/FBElement.h | 3 +++ WebDriverAgentLib/Utilities/FBXPath.m | 20 +++++++++++++++++++ .../FBElementAttributeTests.m | 1 + .../FBXPathIntegrationTests.m | 6 +++--- .../Doubles/XCElementSnapshotDouble.m | 2 +- .../UnitTests/Doubles/XCUIElementDouble.h | 1 + .../UnitTests/Doubles/XCUIElementDouble.m | 1 + WebDriverAgentTests/UnitTests/FBXPathTests.m | 12 +++++------ 9 files changed, 45 insertions(+), 10 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m index f99158c7f..4efe2dde6 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m @@ -115,6 +115,15 @@ - (NSString *)wdLabel return FBTransferEmptyStringToNil(label); } +- (NSString *)wdPlaceholderValue +{ + NSString *placehlderValue = self.placeholderValue; + if (nil != placehlderValue) { + return placehlderValue; + } + return FBTransferEmptyStringToNil(placehlderValue); +} + - (NSString *)wdType { return [FBElementTypeTransformer stringWithElementType:self.elementType]; diff --git a/WebDriverAgentLib/Routing/FBElement.h b/WebDriverAgentLib/Routing/FBElement.h index 7cc8f269c..0b3b8b098 100644 --- a/WebDriverAgentLib/Routing/FBElement.h +++ b/WebDriverAgentLib/Routing/FBElement.h @@ -62,6 +62,9 @@ NS_ASSUME_NONNULL_BEGIN /*! Element's index relatively to its parent. Starts from zero */ @property (nonatomic, readonly) NSUInteger wdIndex; +/*! Element's placeholder value */ +@property (nonatomic, readonly, copy, nullable) NSString *wdPlaceholderValue; + /** Returns value of given property specified in WebDriver Spec Check the FBElement protocol to get list of supported attributes. diff --git a/WebDriverAgentLib/Utilities/FBXPath.m b/WebDriverAgentLib/Utilities/FBXPath.m index 6276cfae6..d36291fdd 100644 --- a/WebDriverAgentLib/Utilities/FBXPath.m +++ b/WebDriverAgentLib/Utilities/FBXPath.m @@ -100,6 +100,10 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forValue:(NSString *)value; @end +@interface FBPlaceholderValueAttribute : FBElementAttribute + +@end + #if TARGET_OS_TV @interface FBFocusedAttribute : FBElementAttribute @@ -491,6 +495,7 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forElement:(id)eleme FBHeightAttribute.class, FBIndexAttribute.class, FBHittableAttribute.class, + FBPlaceholderValueAttribute.class, ]; } @@ -713,3 +718,18 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forValue:(NSString *)value return rc; } @end + + +@implementation FBPlaceholderValueAttribute + ++ (NSString *)name +{ + return @"placeholderValue"; +} + ++ (NSString *)valueForElement:(id)element +{ + return element.wdPlaceholderValue; +} + +@end diff --git a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m index 7c094b600..15cf628ab 100644 --- a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m @@ -154,6 +154,7 @@ - (void)testSwitchAttributes XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeSwitch"); XCTAssertNil(element.wdName); XCTAssertNil(element.wdLabel); + XCTAssertNil(element.wdPlaceholderValue); XCTAssertEqualObjects(element.wdValue, @"1"); XCTAssertFalse(element.wdSelected); XCTAssertTrue(element.wdHittable); diff --git a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m index 461a2ae94..adbadeb32 100644 --- a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m @@ -57,7 +57,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, 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]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\"/>\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, wrappedSnapshot.wdPlaceholderValue]; XCTAssertEqualObjects(xmlStr, expectedXml); } @@ -70,7 +70,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, 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]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@>\n <%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\"/>\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, wrappedSnapshot.wdPlaceholderValue, scope]; XCTAssertEqualObjects(xmlStr, expectedXml); } @@ -83,7 +83,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, FBBoolToString(wrappedSnapshot.wdAccessible), [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=\"%@\" placeholderValue=\"%@\"/>\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], wrappedSnapshot.wdPlaceholderValue]; XCTAssertEqualObjects(xmlStr, expectedXml); } diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m b/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m index fc0814c1e..e9e1a2a76 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +++ b/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m @@ -60,7 +60,7 @@ - (XCUIUserInterfaceSizeClass)verticalSizeClass - (NSString *)placeholderValue { - return @""; + return @"testPlaceholderValue"; } - (BOOL)isSelected diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h index 5720ef8ab..b2269874f 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h @@ -33,6 +33,7 @@ @property (nonatomic, readwrite, getter=isWDAccessible) BOOL wdAccessible; @property (nonatomic, readwrite, getter = isWDFocused) BOOL wdFocused; @property (nonatomic, readwrite, getter = isWDHittable) BOOL wdHittable; +@property (nonatomic, copy, readwrite, nullable) NSString *wdPlaceholderValue; @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 9e65324b3..5f731d7ba 100644 --- a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m @@ -23,6 +23,7 @@ - (id)init self.wdName = @"testName"; self.wdLabel = @"testLabel"; self.wdValue = @"magicValue"; + self.wdPlaceholderValue = @"testPlaceholderValue"; self.wdVisible = YES; self.wdAccessible = YES; self.wdEnabled = YES; diff --git a/WebDriverAgentTests/UnitTests/FBXPathTests.m b/WebDriverAgentTests/UnitTests/FBXPathTests.m index ce9171107..ad0d1988f 100644 --- a/WebDriverAgentTests/UnitTests/FBXPathTests.m +++ b/WebDriverAgentTests/UnitTests/FBXPathTests.m @@ -63,8 +63,8 @@ - (void)testDefaultXPathPresentation NSString *resultXml = [self xmlStringWithElement:element 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, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n", + 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, element.wdPlaceholderValue]; XCTAssertTrue([resultXml isEqualToString: expectedXml]); } @@ -75,8 +75,8 @@ - (void)testtXPathPresentationWithSomeAttributesExcluded NSString *resultXml = [self xmlStringWithElement:element 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, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"]]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ name=\"%@\" label=\"%@\" enabled=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n", + element.wdType, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdPlaceholderValue]; XCTAssertEqualObjects(resultXml, expectedXml); } @@ -89,8 +89,8 @@ - (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\" 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)]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" hittable=\"%@\" placeholderValue=\"%@\" 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), element.wdPlaceholderValue]; XCTAssertEqualObjects(expectedXml, resultXml); } From f2de1a6e4baed7cce9a28a08d9b0998383c19e65 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 9 Mar 2025 08:40:23 +0000 Subject: [PATCH 165/368] chore(release): 9.1.0 [skip ci] ## [9.1.0](https://github.com/appium/WebDriverAgent/compare/v9.0.6...v9.1.0) (2025-03-09) ### Features * add placeholderValue ([#987](https://github.com/appium/WebDriverAgent/issues/987)) ([8c3a1cb](https://github.com/appium/WebDriverAgent/commit/8c3a1cb30655ed8d1a77d25bbeca71ee48c2ec3e)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 169152856..727a8d507 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.1.0](https://github.com/appium/WebDriverAgent/compare/v9.0.6...v9.1.0) (2025-03-09) + +### Features + +* add placeholderValue ([#987](https://github.com/appium/WebDriverAgent/issues/987)) ([8c3a1cb](https://github.com/appium/WebDriverAgent/commit/8c3a1cb30655ed8d1a77d25bbeca71ee48c2ec3e)) + ## [9.0.6](https://github.com/appium/WebDriverAgent/compare/v9.0.5...v9.0.6) (2025-02-28) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 39be9a6fe..3bc3b1dc7 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.0.6 + 9.1.0 CFBundleSignature ???? CFBundleVersion - 9.0.6 + 9.1.0 NSPrincipalClass diff --git a/package.json b/package.json index 95f0b1b33..ab880bb02 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.0.6", + "version": "9.1.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 9c9d8af9c98ba7b2843a42f54354b78e126d2d27 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 13 Mar 2025 22:01:25 +0100 Subject: [PATCH 166/368] feat: Add 'limitXpathContextScope' setting (#988) --- .github/workflows/functional-test.yml | 14 +-- .../Commands/FBSessionCommands.m | 4 + WebDriverAgentLib/Utilities/FBConfiguration.h | 8 ++ WebDriverAgentLib/Utilities/FBConfiguration.m | 12 ++ WebDriverAgentLib/Utilities/FBSettings.h | 1 + WebDriverAgentLib/Utilities/FBSettings.m | 1 + WebDriverAgentLib/Utilities/FBXPath-Private.h | 7 +- WebDriverAgentLib/Utilities/FBXPath.m | 119 ++++++++++++++---- .../FBXPathIntegrationTests.m | 23 ++++ WebDriverAgentTests/UnitTests/FBXPathTests.m | 16 +-- lib/webdriveragent.js | 4 +- test/unit/webdriveragent-specs.js | 8 +- 12 files changed, 165 insertions(+), 52 deletions(-) diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index b8c9855aa..524f337dc 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -13,17 +13,13 @@ jobs: matrix: test_targets: - HOST_OS: 'macos-15' - XCODE_VERSION: '16.1.0' - IOS_VERSION: '18.1' + XCODE_VERSION: '16.2' + IOS_VERSION: '18.2' IOS_MODEL: iPhone 16 Plus - - HOST_OS: 'macos-14' - XCODE_VERSION: '15.3' - IOS_VERSION: '17.4' + - HOST_OS: 'macos-15' + XCODE_VERSION: '15.4' + IOS_VERSION: '17.5' IOS_MODEL: iPhone 15 Plus - - HOST_OS: 'macos-13' - XCODE_VERSION: 14.3.1 - IOS_VERSION: '16.4' - IOS_MODEL: iPhone 14 Plus # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md runs-on: ${{matrix.test_targets.HOST_OS}} diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 8f84d7afe..67b6b81e9 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -351,6 +351,7 @@ + (NSArray *)routes FB_SETTING_MAX_TYPING_FREQUENCY: @([FBConfiguration maxTypingFrequency]), FB_SETTING_RESPECT_SYSTEM_ALERTS: @([FBConfiguration shouldRespectSystemAlerts]), FB_SETTING_USE_CLEAR_TEXT_SHORTCUT: @([FBConfiguration useClearTextShortcut]), + FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE: @([FBConfiguration limitXpathContextScope]), #if !TARGET_OS_TV FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation], #endif @@ -445,6 +446,9 @@ + (NSArray *)routes if (nil != [settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT]) { [FBConfiguration setUseClearTextShortcut:[[settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT] boolValue]]; } + if (nil != [settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE]) { + [FBConfiguration setLimitXpathContextScope:[[settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE] boolValue]]; + } #if !TARGET_OS_TV if (nil != [settings objectForKey:FB_SETTING_SCREENSHOT_ORIENTATION]) { diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index ad9687b19..cb0a67dcf 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -103,6 +103,14 @@ extern NSString *const FBSnapshotMaxDepthKey; + (NSUInteger)mjpegServerFramerate; + (void)setMjpegServerFramerate:(NSUInteger)framerate; +/** + Whether to limit the XPath scope to descendant items only while performing a lookup + in an element context. Enabled by default. Being disabled, allows to use XPath locators + like ".." in order to match parent items of the current context root. + */ ++ (BOOL)limitXpathContextScope; ++ (void)setLimitXpathContextScope:(BOOL)enabled; + /** 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). diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index 1065b892e..f3cf8e42f 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -56,6 +56,7 @@ static BOOL FBShouldUseCompactResponses; static NSString *FBElementResponseAttributes; static BOOL FBUseClearTextShortcut; +static BOOL FBLimitXpathContextScope = YES; #if !TARGET_OS_TV static UIInterfaceOrientation FBScreenshotOrientation; #endif @@ -438,6 +439,16 @@ + (BOOL)useClearTextShortcut return FBUseClearTextShortcut; } ++ (BOOL)limitXpathContextScope +{ + return FBLimitXpathContextScope; +} + ++ (void)setLimitXpathContextScope:(BOOL)enabled +{ + FBLimitXpathContextScope = enabled; +} + #if !TARGET_OS_TV + (BOOL)setScreenshotOrientation:(NSString *)orientation error:(NSError **)error { @@ -503,6 +514,7 @@ + (void)resetSessionSettings // 50 should be enough for the majority of the cases. The performance is acceptable for values up to 100. FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @50); FBUseClearTextShortcut = YES; + FBLimitXpathContextScope = YES; #if !TARGET_OS_TV FBScreenshotOrientation = UIInterfaceOrientationUnknown; #endif diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index 1a551c63f..7f6d57970 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -38,6 +38,7 @@ extern NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT; extern NSString* const FB_SETTING_MAX_TYPING_FREQUENCY; extern NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS; extern NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT; +extern NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE; NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index f5a61a8a8..c19889db3 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -34,3 +34,4 @@ NSString* const FB_SETTING_MAX_TYPING_FREQUENCY = @"maxTypingFrequency"; NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS = @"respectSystemAlerts"; NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT = @"useClearTextShortcut"; +NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE = @"limitXpathContextScope"; diff --git a/WebDriverAgentLib/Utilities/FBXPath-Private.h b/WebDriverAgentLib/Utilities/FBXPath-Private.h index 31bb403bf..7346b2c3f 100644 --- a/WebDriverAgentLib/Utilities/FBXPath-Private.h +++ b/WebDriverAgentLib/Utilities/FBXPath-Private.h @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN If `query` argument is assigned then `excludedAttributes` argument is effectively ignored. @return zero if the method has completed successfully */ -+ (int)xmlRepresentationWithRootElement:(id)root ++ (int)xmlRepresentationWithRootElement:(id)root writer:(xmlTextWriterPtr)writer elementStore:(nullable NSMutableDictionary *)elementStore query:(nullable NSString*)query @@ -45,9 +45,12 @@ NS_ASSUME_NONNULL_BEGIN @param xpathQuery actual query. Should be valid XPath 1.0-compatible expression @param document libxml2-compatible document pointer + @param contextNode Optonal context node instance @return pointer to a libxml2-compatible structure with set of matched nodes or NULL in case of failure */ -+ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery document:(xmlDocPtr)doc; ++ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery + document:(xmlDocPtr)doc + contextNode:(nullable xmlNodePtr)contextNode; @end diff --git a/WebDriverAgentLib/Utilities/FBXPath.m b/WebDriverAgentLib/Utilities/FBXPath.m index d36291fdd..18793041f 100644 --- a/WebDriverAgentLib/Utilities/FBXPath.m +++ b/WebDriverAgentLib/Utilities/FBXPath.m @@ -11,6 +11,7 @@ #import "FBConfiguration.h" #import "FBExceptions.h" +#import "FBElementUtils.h" #import "FBLogger.h" #import "FBMacros.h" #import "FBXMLGenerationOptions.h" @@ -145,7 +146,7 @@ + (nullable NSString *)xmlStringWithRootElement:(id)root } if (rc >= 0) { - rc = [self xmlRepresentationWithRootElement:root + rc = [self xmlRepresentationWithRootElement:[self snapshotWithRoot:root] writer:writer elementStore:nil query:nil @@ -193,10 +194,29 @@ + (nullable NSString *)xmlStringWithRootElement:(id)root } NSMutableDictionary *elementStore = [NSMutableDictionary dictionary]; int rc = xmlTextWriterStartDocument(writer, NULL, _UTF8Encoding, NULL); + id lookupScopeSnapshot = nil; + id contextRootSnapshot = nil; if (rc < 0) { [FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterStartDocument. Error code: %d", rc]; } else { - rc = [self xmlRepresentationWithRootElement:root + if (FBConfiguration.limitXpathContextScope) { + lookupScopeSnapshot = [self snapshotWithRoot:root]; + } else { + if ([root isKindOfClass:XCUIElement.class]) { + lookupScopeSnapshot = [self snapshotWithRoot:[(XCUIElement *)root application]]; + contextRootSnapshot = [root isKindOfClass:XCUIApplication.class] + ? nil + : [(XCUIElement *)root fb_takeSnapshot:YES]; + } else { + lookupScopeSnapshot = (id)root; + contextRootSnapshot = nil == lookupScopeSnapshot.parent ? nil : (id)root; + while (nil != lookupScopeSnapshot.parent) { + lookupScopeSnapshot = lookupScopeSnapshot.parent; + } + } + } + + rc = [self xmlRepresentationWithRootElement:lookupScopeSnapshot writer:writer elementStore:elementStore query:xpathQuery @@ -214,7 +234,22 @@ + (nullable NSString *)xmlStringWithRootElement:(id)root return [self throwException:FBXPathQueryEvaluationException forQuery:xpathQuery]; } - xmlXPathObjectPtr queryResult = [self evaluate:xpathQuery document:doc]; + xmlXPathObjectPtr contextNodeQueryResult = [self matchNodeInDocument:doc + elementStore:elementStore.copy + forSnapshot:contextRootSnapshot]; + xmlNodePtr contextNode = NULL; + if (NULL != contextNodeQueryResult) { + xmlNodeSetPtr nodeSet = contextNodeQueryResult->nodesetval; + if (!xmlXPathNodeSetIsEmpty(nodeSet)) { + contextNode = nodeSet->nodeTab[0]; + } + } + xmlXPathObjectPtr queryResult = [self evaluate:xpathQuery + document:doc + contextNode:contextNode]; + if (NULL != contextNodeQueryResult) { + xmlXPathFreeObject(contextNodeQueryResult); + } if (NULL == queryResult) { xmlFreeTextWriter(writer); xmlFreeDoc(doc); @@ -256,6 +291,36 @@ + (NSArray *)collectMatchingSnapshots:(xmlNodeSetPtr)nodeSet return matchingSnapshots.copy; } ++ (nullable xmlXPathObjectPtr)matchNodeInDocument:(xmlDocPtr)doc + elementStore:(NSDictionary> *)elementStore + forSnapshot:(nullable id)snapshot +{ + if (nil == snapshot) { + return NULL; + } + + NSString *contextRootUid = [FBElementUtils uidWithAccessibilityElement:[(id)snapshot accessibilityElement]]; + if (nil == contextRootUid) { + return NULL; + } + + for (NSString *key in elementStore) { + id value = [elementStore objectForKey:key]; + NSString *snapshotUid = [FBElementUtils uidWithAccessibilityElement:[value accessibilityElement]]; + if (nil == snapshotUid || ![snapshotUid isEqualToString:contextRootUid]) { + continue; + } + NSString *indexQuery = [NSString stringWithFormat:@"//*[@%@=\"%@\"]", kXMLIndexPathKey, key]; + xmlXPathObjectPtr queryResult = [self evaluate:indexQuery + document:doc + contextNode:NULL]; + if (NULL != queryResult) { + return queryResult; + } + } + return NULL; +} + + (NSSet *)elementAttributesWithXPathQuery:(NSString *)query { if ([query rangeOfString:@"[^\\w@]@\\*[^\\w]" options:NSRegularExpressionSearch].location != NSNotFound) { @@ -271,7 +336,7 @@ + (NSArray *)collectMatchingSnapshots:(xmlNodeSetPtr)nodeSet return result.copy; } -+ (int)xmlRepresentationWithRootElement:(id)root ++ (int)xmlRepresentationWithRootElement:(id)root writer:(xmlTextWriterPtr)writer elementStore:(nullable NSMutableDictionary *)elementStore query:(nullable NSString*)query @@ -312,14 +377,16 @@ + (int)xmlRepresentationWithRootElement:(id)root return 0; } -+ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery document:(xmlDocPtr)doc ++ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery + document:(xmlDocPtr)doc + contextNode:(nullable xmlNodePtr)contextNode { xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc); if (NULL == xpathCtx) { [FBLogger logFmt:@"Failed to invoke libxml2>xmlXPathNewContext for XPath query \"%@\"", xpathQuery]; return NULL; } - xpathCtx->node = doc->children; + xpathCtx->node = NULL == contextNode ? doc->children : contextNode; xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((const xmlChar *)[xpathQuery UTF8String], xpathCtx); if (NULL == xpathObj) { @@ -360,7 +427,7 @@ + (int)recordElementAttributes:(xmlTextWriterPtr)writer return 0; } -+ (int)writeXmlWithRootElement:(id)root ++ (int)writeXmlWithRootElement:(id)root indexPath:(nullable NSString *)indexPath elementStore:(nullable NSMutableDictionary *)elementStore includedAttributes:(nullable NSSet *)includedAttributes @@ -368,29 +435,13 @@ + (int)writeXmlWithRootElement:(id)root { NSAssert((indexPath == nil && elementStore == nil) || (indexPath != nil && elementStore != nil), @"Either both or none of indexPath and elementStore arguments should be equal to nil", nil); - __block id currentSnapshot; - NSArray> *children; - if ([root isKindOfClass:XCUIElement.class]) { - XCUIElement *element = (XCUIElement *)root; - if (nil == includedAttributes || [includedAttributes containsObject:FBVisibleAttribute.class]) { - // If the app is not idle state while we retrieve the visiblity state - // then the snapshot retrieval operation might freeze and time out - [element.application fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; - } - @autoreleasepool { - currentSnapshot = [element fb_takeSnapshot:YES]; - } - children = currentSnapshot.children; - } else { - currentSnapshot = (id)root; - children = currentSnapshot.children; - } + NSArray> *children = root.children; if (elementStore != nil && indexPath != nil && [indexPath isEqualToString:topNodeIndexPath]) { - [elementStore setObject:currentSnapshot forKey:topNodeIndexPath]; + [elementStore setObject:root forKey:topNodeIndexPath]; } - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:currentSnapshot]; + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:root]; int rc = xmlTextWriterStartElement(writer, (xmlChar *)[wrappedSnapshot.wdType UTF8String]); if (rc < 0) { [FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterStartElement for the tag value '%@'. Error code: %d", wrappedSnapshot.wdType, rc]; @@ -398,7 +449,7 @@ + (int)writeXmlWithRootElement:(id)root } rc = [self recordElementAttributes:writer - forElement:currentSnapshot + forElement:root indexPath:indexPath includedAttributes:includedAttributes]; if (rc < 0) { @@ -431,6 +482,20 @@ + (int)writeXmlWithRootElement:(id)root return 0; } ++ (id)snapshotWithRoot:(id)root +{ + if (![root isKindOfClass:XCUIElement.class]) { + return (id)root; + } + + // If the app is not idle state while we retrieve the visiblity state + // then the snapshot retrieval operation might freeze and time out + [[(XCUIElement *)root application] fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; + @autoreleasepool { + return [(XCUIElement *)root fb_takeSnapshot:YES]; + } +} + @end diff --git a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m index adbadeb32..77b3c2bcf 100644 --- a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m @@ -96,6 +96,29 @@ - (void)testFindMatchesInElement } } +- (void)testFindMatchesWithoutContextScopeLimit +{ + XCUIElement *button = self.testedApplication.buttons.firstMatch; + BOOL previousValue = FBConfiguration.limitXpathContextScope; + FBConfiguration.limitXpathContextScope = NO; + @try { + NSArray *parentSnapshots = [FBXPath matchesWithRootElement:button forQuery:@".."]; + XCTAssertEqual(parentSnapshots.count, 1); + XCTAssertEqualObjects( + [FBXCElementSnapshotWrapper ensureWrapped:[parentSnapshots objectAtIndex:0]].wdLabel, + @"MainView" + ); + NSArray *currentSnapshots = [FBXPath matchesWithRootElement:button forQuery:@"."]; + XCTAssertEqual(currentSnapshots.count, 1); + XCTAssertEqualObjects( + [FBXCElementSnapshotWrapper ensureWrapped:[currentSnapshots objectAtIndex:0]].wdType, + @"XCUIElementTypeButton" + ); + } @finally { + FBConfiguration.limitXpathContextScope = previousValue; + } +} + - (void)testFindMatchesInElementWithDotNotation { NSArray> *matchingSnapshots = [FBXPath matchesWithRootElement:self.testedApplication forQuery:@".//XCUIElementTypeButton"]; diff --git a/WebDriverAgentTests/UnitTests/FBXPathTests.m b/WebDriverAgentTests/UnitTests/FBXPathTests.m index ad0d1988f..3d549e0b2 100644 --- a/WebDriverAgentTests/UnitTests/FBXPathTests.m +++ b/WebDriverAgentTests/UnitTests/FBXPathTests.m @@ -21,7 +21,7 @@ @interface FBXPathTests : XCTestCase @implementation FBXPathTests -- (NSString *)xmlStringWithElement:(id)element +- (NSString *)xmlStringWithElement:(id)snapshot xpathQuery:(nullable NSString *)query excludingAttributes:(nullable NSArray *)excludedAttributes { @@ -33,7 +33,7 @@ - (NSString *)xmlStringWithElement:(id)element xmlChar *xmlbuff = NULL; int rc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL); if (rc >= 0) { - rc = [FBXPath xmlRepresentationWithRootElement:element + rc = [FBXPath xmlRepresentationWithRootElement:snapshot writer:writer elementStore:elementStore query:query @@ -60,7 +60,7 @@ - (void)testDefaultXPathPresentation { XCElementSnapshotDouble *snapshot = [XCElementSnapshotDouble new]; id element = (id)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot]; - NSString *resultXml = [self xmlStringWithElement:element + NSString *resultXml = [self xmlStringWithElement:(id)element xpathQuery:nil excludingAttributes:nil]; NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n", @@ -72,7 +72,7 @@ - (void)testtXPathPresentationWithSomeAttributesExcluded { XCElementSnapshotDouble *snapshot = [XCElementSnapshotDouble new]; id element = (id)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot]; - NSString *resultXml = [self xmlStringWithElement:element + NSString *resultXml = [self xmlStringWithElement:(id)element xpathQuery:nil excludingAttributes:@[@"type", @"visible", @"value", @"index"]]; NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ name=\"%@\" label=\"%@\" enabled=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n", @@ -86,7 +86,7 @@ - (void)testXPathPresentationBasedOnQueryMatchingAllAttributes snapshot.value = @"йоло<>&\""; snapshot.label = @"a\nb"; id element = (id)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot]; - NSString *resultXml = [self xmlStringWithElement:element + NSString *resultXml = [self xmlStringWithElement:(id)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\" hittable=\"%@\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n", @@ -98,7 +98,7 @@ - (void)testXPathPresentationBasedOnQueryMatchingSomeAttributes { XCElementSnapshotDouble *snapshot = [XCElementSnapshotDouble new]; id element = (id)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot]; - NSString *resultXml = [self xmlStringWithElement:element + NSString *resultXml = [self xmlStringWithElement:(id)element xpathQuery:[NSString stringWithFormat:@"//%@[@%@ and contains(@%@, 'blabla')]", element.wdType, @"value", @"name"] excludingAttributes:nil]; NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ value=\"%@\" name=\"%@\" private_indexPath=\"top\"/>\n", @@ -117,7 +117,7 @@ - (void)testSnapshotXPathResultsMatching NSString *query = [NSString stringWithFormat:@"//%@", root.wdType]; int rc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL); if (rc >= 0) { - rc = [FBXPath xmlRepresentationWithRootElement:root + rc = [FBXPath xmlRepresentationWithRootElement:(id)root writer:writer elementStore:elementStore query:query @@ -132,7 +132,7 @@ - (void)testSnapshotXPathResultsMatching XCTFail(@"Unable to create the source XML document"); } - xmlXPathObjectPtr queryResult = [FBXPath evaluate:query document:doc]; + xmlXPathObjectPtr queryResult = [FBXPath evaluate:query document:doc contextNode:NULL]; if (NULL == queryResult) { xmlFreeTextWriter(writer); xmlFreeDoc(doc); diff --git a/lib/webdriveragent.js b/lib/webdriveragent.js index a2a9dbb0d..73b056bd5 100644 --- a/lib/webdriveragent.js +++ b/lib/webdriveragent.js @@ -579,8 +579,8 @@ export class WebDriverAgent { setupProxies (sessionId) { const proxyOpts = { log: this.log, - server: this.url.hostname, - port: this.url.port, + server: this.url.hostname ?? undefined, + port: parseInt(this.url.port ?? '', 10) || undefined, base: this.basePath, timeout: this.wdaConnectionTimeout, keepAlive: true, diff --git a/test/unit/webdriveragent-specs.js b/test/unit/webdriveragent-specs.js index 1b844e08a..487f71d91 100644 --- a/test/unit/webdriveragent-specs.js +++ b/test/unit/webdriveragent-specs.js @@ -71,10 +71,10 @@ describe('launch', function () { await agent.launch('sessionId').should.eventually.eql({build: 'data'}); agent.url.href.should.eql(override); agent.jwproxy.server.should.eql('mockurl'); - agent.jwproxy.port.should.eql('8100'); + agent.jwproxy.port.should.eql(8100); agent.jwproxy.base.should.eql(''); agent.noSessionProxy.server.should.eql('mockurl'); - agent.noSessionProxy.port.should.eql('8100'); + agent.noSessionProxy.port.should.eql(8100); agent.noSessionProxy.base.should.eql(''); wdaStub.reset(); }); @@ -97,10 +97,10 @@ describe('use wda proxy url', function () { agent.url.hostname.should.eql('127.0.0.1'); agent.url.path.should.eql('/aabbccdd'); agent.jwproxy.server.should.eql('127.0.0.1'); - agent.jwproxy.port.should.eql('8100'); + agent.jwproxy.port.should.eql(8100); agent.jwproxy.base.should.eql('/aabbccdd'); agent.noSessionProxy.server.should.eql('127.0.0.1'); - agent.noSessionProxy.port.should.eql('8100'); + agent.noSessionProxy.port.should.eql(8100); agent.noSessionProxy.base.should.eql('/aabbccdd'); }); }); From fd7291306ebdda67af3df042a5a2b50478b377fe Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 13 Mar 2025 21:09:06 +0000 Subject: [PATCH 167/368] chore(release): 9.2.0 [skip ci] ## [9.2.0](https://github.com/appium/WebDriverAgent/compare/v9.1.0...v9.2.0) (2025-03-13) ### Features * Add 'limitXpathContextScope' setting ([#988](https://github.com/appium/WebDriverAgent/issues/988)) ([9c9d8af](https://github.com/appium/WebDriverAgent/commit/9c9d8af9c98ba7b2843a42f54354b78e126d2d27)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 727a8d507..3f0728088 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.2.0](https://github.com/appium/WebDriverAgent/compare/v9.1.0...v9.2.0) (2025-03-13) + +### Features + +* Add 'limitXpathContextScope' setting ([#988](https://github.com/appium/WebDriverAgent/issues/988)) ([9c9d8af](https://github.com/appium/WebDriverAgent/commit/9c9d8af9c98ba7b2843a42f54354b78e126d2d27)) + ## [9.1.0](https://github.com/appium/WebDriverAgent/compare/v9.0.6...v9.1.0) (2025-03-09) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 3bc3b1dc7..af208b64c 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.1.0 + 9.2.0 CFBundleSignature ???? CFBundleVersion - 9.1.0 + 9.2.0 NSPrincipalClass diff --git a/package.json b/package.json index ab880bb02..22a37b149 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.1.0", + "version": "9.2.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 34f95107997bdec63219a2fd917de899de3e198c Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Fri, 21 Mar 2025 07:44:15 +0100 Subject: [PATCH 168/368] feat: Add /window/rect W3C endpoint (#991) --- .../Commands/FBElementCommands.m | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index a03fbea41..adcfa6ed6 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -53,6 +53,7 @@ + (NSArray *)routes return @[ [[FBRoute GET:@"/window/size"] respondWithTarget:self action:@selector(handleGetWindowSize:)], + [[FBRoute GET:@"/window/rect"] respondWithTarget:self action:@selector(handleGetWindowRect:)], [[FBRoute GET:@"/window/size"].withoutSession respondWithTarget:self action:@selector(handleGetWindowSize:)], [[FBRoute GET:@"/element/:uuid/enabled"] respondWithTarget:self action:@selector(handleGetEnabled:)], [[FBRoute GET:@"/element/:uuid/rect"] respondWithTarget:self action:@selector(handleGetRect:)], @@ -525,13 +526,32 @@ + (NSArray *)routes { XCUIApplication *app = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; + CGRect frame = app.wdFrame; #if TARGET_OS_TV - CGSize screenSize = app.frame.size; + CGSize screenSize = frame.size; #else + CGSize screenSize = FBAdjustDimensionsForApplication(frame.size, app.interfaceOrientation); +#endif + return FBResponseWithObject(@{ + @"width": @(screenSize.width), + @"height": @(screenSize.height), + }); +} + + ++ (id)handleGetWindowRect:(FBRouteRequest *)request +{ + XCUIApplication *app = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; + CGRect frame = app.wdFrame; +#if TARGET_OS_TV + CGSize screenSize = frame.size; +#else CGSize screenSize = FBAdjustDimensionsForApplication(frame.size, app.interfaceOrientation); #endif return FBResponseWithObject(@{ + @"x": @(frame.origin.x), + @"y": @(frame.origin.y), @"width": @(screenSize.width), @"height": @(screenSize.height), }); From d84ca5c6b2eb156dbada56e928ab78483bbfdb4f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 21 Mar 2025 06:48:27 +0000 Subject: [PATCH 169/368] chore(release): 9.3.0 [skip ci] ## [9.3.0](https://github.com/appium/WebDriverAgent/compare/v9.2.0...v9.3.0) (2025-03-21) ### Features * Add /window/rect W3C endpoint ([#991](https://github.com/appium/WebDriverAgent/issues/991)) ([34f9510](https://github.com/appium/WebDriverAgent/commit/34f95107997bdec63219a2fd917de899de3e198c)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f0728088..5a0f9f843 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.3.0](https://github.com/appium/WebDriverAgent/compare/v9.2.0...v9.3.0) (2025-03-21) + +### Features + +* Add /window/rect W3C endpoint ([#991](https://github.com/appium/WebDriverAgent/issues/991)) ([34f9510](https://github.com/appium/WebDriverAgent/commit/34f95107997bdec63219a2fd917de899de3e198c)) + ## [9.2.0](https://github.com/appium/WebDriverAgent/compare/v9.1.0...v9.2.0) (2025-03-13) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index af208b64c..2b7c6a296 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.2.0 + 9.3.0 CFBundleSignature ???? CFBundleVersion - 9.2.0 + 9.3.0 NSPrincipalClass diff --git a/package.json b/package.json index 22a37b149..c6379c210 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.2.0", + "version": "9.3.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From f55462f4fa63314dfea48670d17ee54dc5fe2d96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Mar 2025 15:43:43 +0100 Subject: [PATCH 170/368] chore(deps-dev): bump sinon from 19.0.5 to 20.0.0 (#994) Bumps [sinon](https://github.com/sinonjs/sinon) from 19.0.5 to 20.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/v19.0.5...v20.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 c6379c210..262f29661 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "prettier": "^3.0.0", "semantic-release": "^24.0.0", "semver": "^7.3.7", - "sinon": "^19.0.1", + "sinon": "^20.0.0", "ts-node": "^10.9.1", "typescript": "^5.4.2" }, From c016c7c17229803d80c7fe40b79078abb39c11be Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 25 Mar 2025 14:48:58 +0000 Subject: [PATCH 171/368] chore(release): 9.3.1 [skip ci] ## [9.3.1](https://github.com/appium/WebDriverAgent/compare/v9.3.0...v9.3.1) (2025-03-25) ### Miscellaneous Chores * **deps-dev:** bump sinon from 19.0.5 to 20.0.0 ([#994](https://github.com/appium/WebDriverAgent/issues/994)) ([f55462f](https://github.com/appium/WebDriverAgent/commit/f55462f4fa63314dfea48670d17ee54dc5fe2d96)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a0f9f843..fb9871eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.3.1](https://github.com/appium/WebDriverAgent/compare/v9.3.0...v9.3.1) (2025-03-25) + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 19.0.5 to 20.0.0 ([#994](https://github.com/appium/WebDriverAgent/issues/994)) ([f55462f](https://github.com/appium/WebDriverAgent/commit/f55462f4fa63314dfea48670d17ee54dc5fe2d96)) + ## [9.3.0](https://github.com/appium/WebDriverAgent/compare/v9.2.0...v9.3.0) (2025-03-21) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 2b7c6a296..b87c79309 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.3.0 + 9.3.1 CFBundleSignature ???? CFBundleVersion - 9.3.0 + 9.3.1 NSPrincipalClass diff --git a/package.json b/package.json index 262f29661..8930ec7dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.3.0", + "version": "9.3.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 9789e393b55bc682a9a8ef5a65fba5e4dbf752ce Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 26 Mar 2025 22:31:35 +0100 Subject: [PATCH 172/368] fix: Adjust limitXPathContextScope setting name (#995) --- WebDriverAgentLib/Utilities/FBSettings.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index c19889db3..d91e343ed 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -34,4 +34,4 @@ NSString* const FB_SETTING_MAX_TYPING_FREQUENCY = @"maxTypingFrequency"; NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS = @"respectSystemAlerts"; NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT = @"useClearTextShortcut"; -NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE = @"limitXpathContextScope"; +NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE = @"limitXPathContextScope"; From bd07a10a26515f2c4051954eff93c08543166d26 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 26 Mar 2025 21:38:12 +0000 Subject: [PATCH 173/368] chore(release): 9.3.2 [skip ci] ## [9.3.2](https://github.com/appium/WebDriverAgent/compare/v9.3.1...v9.3.2) (2025-03-26) ### Bug Fixes * Adjust limitXPathContextScope setting name ([#995](https://github.com/appium/WebDriverAgent/issues/995)) ([9789e39](https://github.com/appium/WebDriverAgent/commit/9789e393b55bc682a9a8ef5a65fba5e4dbf752ce)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb9871eb1..992cec5f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.3.2](https://github.com/appium/WebDriverAgent/compare/v9.3.1...v9.3.2) (2025-03-26) + +### Bug Fixes + +* Adjust limitXPathContextScope setting name ([#995](https://github.com/appium/WebDriverAgent/issues/995)) ([9789e39](https://github.com/appium/WebDriverAgent/commit/9789e393b55bc682a9a8ef5a65fba5e4dbf752ce)) + ## [9.3.1](https://github.com/appium/WebDriverAgent/compare/v9.3.0...v9.3.1) (2025-03-25) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index b87c79309..c22fd58da 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.3.1 + 9.3.2 CFBundleSignature ???? CFBundleVersion - 9.3.1 + 9.3.2 NSPrincipalClass diff --git a/package.json b/package.json index 8930ec7dd..1bdaf194b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.3.1", + "version": "9.3.2", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 03ca7cd27b7cd92a45b344eb661db973c5dde809 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 27 Mar 2025 12:14:00 +0100 Subject: [PATCH 174/368] fix: Properly set snapshot lookup scope if limitXpathContextScope is disabled (#996) --- WebDriverAgentLib/Categories/XCUIElement+FBFind.m | 6 ++++-- .../IntegrationTests/FBXPathIntegrationTests.m | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m index d33fce1ea..138119da2 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m @@ -12,6 +12,7 @@ #import "FBMacros.h" #import "FBElementTypeTransformer.h" +#import "FBConfiguration.h" #import "NSPredicate+FBFormat.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "FBXCodeCompatibility.h" @@ -109,8 +110,9 @@ @implementation XCUIElement (FBFind) id snapshot = matchingSnapshots.firstObject; matchingSnapshots = @[snapshot]; } - return [self fb_filterDescendantsWithSnapshots:matchingSnapshots - onlyChildren:NO]; + XCUIElement *scopeRoot = FBConfiguration.limitXpathContextScope ? self : self.application; + return [scopeRoot fb_filterDescendantsWithSnapshots:matchingSnapshots + onlyChildren:NO]; } diff --git a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m index 77b3c2bcf..adaca291a 100644 --- a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +++ b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m @@ -108,12 +108,24 @@ - (void)testFindMatchesWithoutContextScopeLimit [FBXCElementSnapshotWrapper ensureWrapped:[parentSnapshots objectAtIndex:0]].wdLabel, @"MainView" ); + NSArray *elements = [button.application fb_filterDescendantsWithSnapshots:parentSnapshots onlyChildren:NO]; + XCTAssertEqual(elements.count, 1); + XCTAssertEqualObjects( + [[elements objectAtIndex:0] wdLabel], + @"MainView" + ); NSArray *currentSnapshots = [FBXPath matchesWithRootElement:button forQuery:@"."]; XCTAssertEqual(currentSnapshots.count, 1); XCTAssertEqualObjects( [FBXCElementSnapshotWrapper ensureWrapped:[currentSnapshots objectAtIndex:0]].wdType, @"XCUIElementTypeButton" ); + NSArray *currentElements = [button.application fb_filterDescendantsWithSnapshots:currentSnapshots onlyChildren:NO]; + XCTAssertEqual(currentElements.count, 1); + XCTAssertEqualObjects( + [[currentElements objectAtIndex:0] wdType], + @"XCUIElementTypeButton" + ); } @finally { FBConfiguration.limitXpathContextScope = previousValue; } From 5f91803d41634713bda8be43955c35c6c31645cb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 27 Mar 2025 11:19:12 +0000 Subject: [PATCH 175/368] chore(release): 9.3.3 [skip ci] ## [9.3.3](https://github.com/appium/WebDriverAgent/compare/v9.3.2...v9.3.3) (2025-03-27) ### Bug Fixes * Properly set snapshot lookup scope if limitXpathContextScope is disabled ([#996](https://github.com/appium/WebDriverAgent/issues/996)) ([03ca7cd](https://github.com/appium/WebDriverAgent/commit/03ca7cd27b7cd92a45b344eb661db973c5dde809)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 992cec5f9..a6c43dec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.3.3](https://github.com/appium/WebDriverAgent/compare/v9.3.2...v9.3.3) (2025-03-27) + +### Bug Fixes + +* Properly set snapshot lookup scope if limitXpathContextScope is disabled ([#996](https://github.com/appium/WebDriverAgent/issues/996)) ([03ca7cd](https://github.com/appium/WebDriverAgent/commit/03ca7cd27b7cd92a45b344eb661db973c5dde809)) + ## [9.3.2](https://github.com/appium/WebDriverAgent/compare/v9.3.1...v9.3.2) (2025-03-26) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index c22fd58da..ee71d3bf5 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.3.2 + 9.3.3 CFBundleSignature ???? CFBundleVersion - 9.3.2 + 9.3.3 NSPrincipalClass diff --git a/package.json b/package.json index 1bdaf194b..e0d86fe30 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.3.2", + "version": "9.3.3", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 60f5aeffdda85faffd60aba416dc9d92987f19ac Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Wed, 2 Apr 2025 07:42:15 +0200 Subject: [PATCH 176/368] feat: Always apply the native snapshotting strategy for XCUIApplication instances (#998) --- .../Categories/XCUIElement+FBUtilities.m | 2 +- .../XCUIApplicationHelperTests.m | 23 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m index 26e274c18..529e17b54 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m @@ -49,7 +49,7 @@ @implementation XCUIElement (FBUtilities) __block id snapshot = nil; @autoreleasepool { NSError *error = nil; - snapshot = inDepth + snapshot = inDepth && ![self isKindOfClass:XCUIApplication.class] ? [self.fb_query fb_uniqueSnapshotWithError:&error] : (id)[self snapshotWithError:&error]; if (nil == snapshot) { diff --git a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m index 794be2192..b6ed3e07b 100644 --- a/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +++ b/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m @@ -20,6 +20,23 @@ #import "XCUIElement+FBIsVisible.h" #import "FBXCodeCompatibility.h" +void calculateMaxTreeDepth(NSDictionary *tree, NSNumber *currentDepth, NSNumber** maxDepth) { + if (nil == maxDepth) { + return; + } + + NSArray *children = tree[@"children"]; + if (nil == children || 0 == children.count) { + return; + } + for (NSDictionary *child in children) { + if (currentDepth.integerValue > [*maxDepth integerValue]) { + *maxDepth = currentDepth; + } + calculateMaxTreeDepth(child, @(currentDepth.integerValue + 1), maxDepth); + } +} + @interface XCUIApplicationHelperTests : FBIntegrationTestCase @end @@ -40,7 +57,11 @@ - (void)testQueringSpringboard - (void)testApplicationTree { - XCTAssertNotNil(self.testedApplication.fb_tree); + NSDictionary *tree = self.testedApplication.fb_tree; + XCTAssertNotNil(tree); + NSNumber *maxDepth; + calculateMaxTreeDepth(tree, @0, &maxDepth); + XCTAssertGreaterThan(maxDepth.integerValue, 3); XCTAssertNotNil(self.testedApplication.fb_accessibilityTree); } From fbe1e3745ca19a2282c8f17868feabd4b2a8284c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 2 Apr 2025 05:47:14 +0000 Subject: [PATCH 177/368] chore(release): 9.4.0 [skip ci] ## [9.4.0](https://github.com/appium/WebDriverAgent/compare/v9.3.3...v9.4.0) (2025-04-02) ### Features * Always apply the native snapshotting strategy for XCUIApplication instances ([#998](https://github.com/appium/WebDriverAgent/issues/998)) ([60f5aef](https://github.com/appium/WebDriverAgent/commit/60f5aeffdda85faffd60aba416dc9d92987f19ac)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6c43dec8..77ee27af5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.4.0](https://github.com/appium/WebDriverAgent/compare/v9.3.3...v9.4.0) (2025-04-02) + +### Features + +* Always apply the native snapshotting strategy for XCUIApplication instances ([#998](https://github.com/appium/WebDriverAgent/issues/998)) ([60f5aef](https://github.com/appium/WebDriverAgent/commit/60f5aeffdda85faffd60aba416dc9d92987f19ac)) + ## [9.3.3](https://github.com/appium/WebDriverAgent/compare/v9.3.2...v9.3.3) (2025-03-27) ### Bug Fixes diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index ee71d3bf5..be415d865 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.3.3 + 9.4.0 CFBundleSignature ???? CFBundleVersion - 9.3.3 + 9.4.0 NSPrincipalClass diff --git a/package.json b/package.json index e0d86fe30..2f902be24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.3.3", + "version": "9.4.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 445741d03313019016d4232f49e656d50f673f16 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 5 Apr 2025 18:00:31 +0900 Subject: [PATCH 178/368] chore: bump appium-ios-simulator --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2f902be24..9ae481c96 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "@appium/strongbox": "^0.x", "@appium/support": "^6.0.0", "appium-ios-device": "^2.7.25", - "appium-ios-simulator": "^6.0.0", + "appium-ios-simulator": "^6.2.2", "async-lock": "^1.0.0", "asyncbox": "^3.0.0", "axios": "^1.4.0", From 37af2edc17b7765867aef66cbfdb2bd2eb39d79c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 5 Apr 2025 09:04:42 +0000 Subject: [PATCH 179/368] chore(release): 9.4.1 [skip ci] ## [9.4.1](https://github.com/appium/WebDriverAgent/compare/v9.4.0...v9.4.1) (2025-04-05) ### Miscellaneous Chores * bump appium-ios-simulator ([445741d](https://github.com/appium/WebDriverAgent/commit/445741d03313019016d4232f49e656d50f673f16)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77ee27af5..6cb85ea72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.4.1](https://github.com/appium/WebDriverAgent/compare/v9.4.0...v9.4.1) (2025-04-05) + +### Miscellaneous Chores + +* bump appium-ios-simulator ([445741d](https://github.com/appium/WebDriverAgent/commit/445741d03313019016d4232f49e656d50f673f16)) + ## [9.4.0](https://github.com/appium/WebDriverAgent/compare/v9.3.3...v9.4.0) (2025-04-02) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index be415d865..9c4dcda35 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.4.0 + 9.4.1 CFBundleSignature ???? CFBundleVersion - 9.4.0 + 9.4.1 NSPrincipalClass diff --git a/package.json b/package.json index 9ae481c96..8eb150709 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.4.0", + "version": "9.4.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 85962aa374bbe0b46a4d42a715a1605cfcb61ad3 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Mon, 7 Apr 2025 19:42:13 +0900 Subject: [PATCH 180/368] ci: run on all Node LTS versions instead of only active (#1000) --- .github/workflows/unit-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index b23ecbee6..6ff82176d 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -7,9 +7,9 @@ jobs: prepare_matrix: runs-on: ubuntu-latest outputs: - versions: ${{ steps.generate-matrix.outputs.active }} + versions: ${{ steps.generate-matrix.outputs.lts }} steps: - - name: Select all active LTS versions of Node.js + - name: Select all current LTS versions of Node.js id: generate-matrix uses: msimerson/node-lts-versions@v1 From fd31b9589199d0a7bc76919f6aa7c7c74c498b90 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 10 Apr 2025 08:04:29 +0200 Subject: [PATCH 181/368] feat: Add support for the autoClickAlertSelector setting (#1002) --- .../Categories/XCUIElement+FBClassChain.h | 3 +- .../Commands/FBSessionCommands.m | 29 +++++++++++ WebDriverAgentLib/Routing/FBCommandStatus.h | 2 +- WebDriverAgentLib/Routing/FBCommandStatus.m | 5 ++ WebDriverAgentLib/Routing/FBSession.h | 16 ++++++ WebDriverAgentLib/Routing/FBSession.m | 49 ++++++++++++++++--- WebDriverAgentLib/Utilities/FBConfiguration.h | 6 +++ WebDriverAgentLib/Utilities/FBConfiguration.m | 12 +++++ WebDriverAgentLib/Utilities/FBSettings.h | 1 + WebDriverAgentLib/Utilities/FBSettings.m | 1 + 10 files changed, 115 insertions(+), 9 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h b/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h index 1cd1e8b93..b6e9ab924 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h @@ -50,7 +50,8 @@ NS_ASSUME_NONNULL_BEGIN @return an array of descendants matching given class chain @throws FBUnknownAttributeException if any of predicates in the chain contains unknown attribute(s) */ -- (NSArray *)fb_descendantsMatchingClassChain:(NSString *)classChainQuery shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch; +- (NSArray *)fb_descendantsMatchingClassChain:(NSString *)classChainQuery + shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch; @end diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 67b6b81e9..01409ab02 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -10,6 +10,7 @@ #import "FBSessionCommands.h" #import "FBCapabilities.h" +#import "FBClassChainQueryParser.h" #import "FBConfiguration.h" #import "FBExceptions.h" #import "FBLogger.h" @@ -347,6 +348,7 @@ + (NSArray *)routes FB_SETTING_INCLUDE_NON_MODAL_ELEMENTS: @([FBConfiguration includeNonModalElements]), FB_SETTING_ACCEPT_ALERT_BUTTON_SELECTOR: FBConfiguration.acceptAlertButtonSelector, FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR: FBConfiguration.dismissAlertButtonSelector, + FB_SETTING_AUTO_CLICK_ALERT_SELECTOR: FBConfiguration.autoClickAlertSelector, FB_SETTING_DEFAULT_ALERT_ACTION: request.session.defaultAlertAction ?: @"", FB_SETTING_MAX_TYPING_FREQUENCY: @([FBConfiguration maxTypingFrequency]), FB_SETTING_RESPECT_SYSTEM_ALERTS: @([FBConfiguration shouldRespectSystemAlerts]), @@ -431,6 +433,13 @@ + (NSArray *)routes if (nil != [settings objectForKey:FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR]) { [FBConfiguration setDismissAlertButtonSelector:(NSString *)[settings objectForKey:FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR]]; } + if (nil != [settings objectForKey:FB_SETTING_AUTO_CLICK_ALERT_SELECTOR]) { + FBCommandStatus *status = [self.class configureAutoClickAlertWithSelector:settings[FB_SETTING_AUTO_CLICK_ALERT_SELECTOR] + forSession:request.session]; + if (status.hasError) { + return FBResponseWithStatus(status); + } + } if (nil != [settings objectForKey:FB_SETTING_WAIT_FOR_IDLE_TIMEOUT]) { [FBConfiguration setWaitForIdleTimeout:[[settings objectForKey:FB_SETTING_WAIT_FOR_IDLE_TIMEOUT] doubleValue]]; } @@ -467,6 +476,26 @@ + (NSArray *)routes #pragma mark - Helpers ++ (FBCommandStatus *)configureAutoClickAlertWithSelector:(NSString *)selector + forSession:(FBSession *)session +{ + if (0 == [selector length]) { + [FBConfiguration setAutoClickAlertSelector:selector]; + [session disableAlertsMonitor]; + return [FBCommandStatus ok]; + } + + NSError *error; + FBClassChain *parsedChain = [FBClassChainQueryParser parseQuery:selector error:&error]; + if (nil == parsedChain) { + return [FBCommandStatus invalidSelectorErrorWithMessage:error.localizedDescription + traceback:nil]; + } + [FBConfiguration setAutoClickAlertSelector:selector]; + [session enableAlertsMonitor]; + return [FBCommandStatus ok]; +} + + (NSString *)buildTimestamp { return [NSString stringWithFormat:@"%@ %@", diff --git a/WebDriverAgentLib/Routing/FBCommandStatus.h b/WebDriverAgentLib/Routing/FBCommandStatus.h index 82bee1f60..7d61f68aa 100644 --- a/WebDriverAgentLib/Routing/FBCommandStatus.h +++ b/WebDriverAgentLib/Routing/FBCommandStatus.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, nullable, readonly) NSString* message; @property (nonatomic, nullable, readonly) NSString* traceback; @property (nonatomic, readonly) HTTPStatusCode statusCode; - +@property (nonatomic, readonly) BOOL hasError; + (instancetype)ok; diff --git a/WebDriverAgentLib/Routing/FBCommandStatus.m b/WebDriverAgentLib/Routing/FBCommandStatus.m index 453fb6192..4d1d9c589 100644 --- a/WebDriverAgentLib/Routing/FBCommandStatus.m +++ b/WebDriverAgentLib/Routing/FBCommandStatus.m @@ -109,6 +109,11 @@ - (instancetype)initWithError:(NSString *)error return self; } +- (BOOL)hasError +{ + return self.statusCode != kHTTPStatusCodeOK; +} + + (instancetype)ok { return [[FBCommandStatus alloc] initWithValue:nil]; diff --git a/WebDriverAgentLib/Routing/FBSession.h b/WebDriverAgentLib/Routing/FBSession.h index b617ae096..ca5be963d 100644 --- a/WebDriverAgentLib/Routing/FBSession.h +++ b/WebDriverAgentLib/Routing/FBSession.h @@ -121,6 +121,22 @@ extern NSString* const FB_SAFARI_BUNDLE_ID; */ - (NSUInteger)applicationStateWithBundleId:(NSString *)bundleIdentifier; +/** + Allows to enable automated session alerts monitoring. + Repeated calls are ignored if alerts monitoring has been already enabled. + + @returns YES if the actual alerts monitoring state has been changed + */ +- (BOOL)enableAlertsMonitor; + +/** + Allows to disable automated alerts monitoring + Repeated calls are ignored if alerts monitoring has been already disabled. + + @returns YES if the actual alerts monitoring state has been changed + */ +- (BOOL)disableAlertsMonitor; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index e8fb95a18..06afa5157 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -25,6 +25,7 @@ #import "FBXCTestDaemonsProxy.h" #import "XCUIApplication+FBQuiescence.h" #import "XCUIElement.h" +#import "XCUIElement+FBClassChain.h" /*! The intial value for the default application property. @@ -53,6 +54,22 @@ @implementation FBSession (FBAlertsMonitorDelegate) - (void)didDetectAlert:(FBAlert *)alert { + NSString *autoClickAlertSelector = FBConfiguration.autoClickAlertSelector; + if ([autoClickAlertSelector length] > 0) { + @try { + NSArray *matches = [alert.alertElement fb_descendantsMatchingClassChain:autoClickAlertSelector + shouldReturnAfterFirstMatch:YES]; + if (matches.count > 0) { + [[matches objectAtIndex:0] tap]; + } + } @catch (NSException *e) { + [FBLogger logFmt:@"Could not click at the alert element '%@'. Original error: %@", + autoClickAlertSelector, e.description]; + } + // This setting has priority over other settings if enabled + return; + } + if (nil == self.defaultAlertAction || 0 == self.defaultAlertAction.length) { return; } @@ -125,23 +142,41 @@ + (instancetype)initWithApplication:(nullable XCUIApplication *)application defaultAlertAction:(NSString *)defaultAlertAction { FBSession *session = [self.class initWithApplication:application]; - session.alertsMonitor = [[FBAlertsMonitor alloc] init]; - session.alertsMonitor.delegate = (id)session; session.defaultAlertAction = [defaultAlertAction lowercaseString]; - [session.alertsMonitor enable]; + [session enableAlertsMonitor]; return session; } +- (BOOL)enableAlertsMonitor +{ + if (nil != self.alertsMonitor) { + return NO; + } + + self.alertsMonitor = [[FBAlertsMonitor alloc] init]; + self.alertsMonitor.delegate = (id)self; + [self.alertsMonitor enable]; + return YES; +} + +- (BOOL)disableAlertsMonitor +{ + if (nil == self.alertsMonitor) { + return NO; + } + + [self.alertsMonitor disable]; + self.alertsMonitor = nil; + return YES; +} + - (void)kill { if (nil == _activeSession) { return; } - if (nil != self.alertsMonitor) { - [self.alertsMonitor disable]; - self.alertsMonitor = nil; - } + [self disableAlertsMonitor]; FBScreenRecordingPromise *activeScreenRecording = FBScreenRecordingContainer.sharedInstance.screenRecordingPromise; if (nil != activeScreenRecording) { diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index cb0a67dcf..f2da06736 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -283,6 +283,12 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) { + (void)setDismissAlertButtonSelector:(NSString *)classChainSelector; + (NSString *)dismissAlertButtonSelector; +/** + Sets class chain selector to apply for an automated alert click + */ ++ (void)setAutoClickAlertSelector:(NSString *)classChainSelector; ++ (NSString *)autoClickAlertSelector; + /** * Whether to use HIDEvent for text clear. * By default this is enabled and HIDEvent is used for text clear. diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index f3cf8e42f..7b75bcd9a 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -51,6 +51,7 @@ static BOOL FBIncludeNonModalElements; static NSString *FBAcceptAlertButtonSelector; static NSString *FBDismissAlertButtonSelector; +static NSString *FBAutoClickAlertSelector; static NSTimeInterval FBWaitForIdleTimeout; static NSTimeInterval FBAnimationCoolOffTimeout; static BOOL FBShouldUseCompactResponses; @@ -429,6 +430,16 @@ + (NSString *)dismissAlertButtonSelector return FBDismissAlertButtonSelector; } ++ (void)setAutoClickAlertSelector:(NSString *)classChainSelector +{ + FBAutoClickAlertSelector = classChainSelector; +} + ++ (NSString *)autoClickAlertSelector +{ + return FBAutoClickAlertSelector; +} + + (void)setUseClearTextShortcut:(BOOL)enabled { FBUseClearTextShortcut = enabled; @@ -509,6 +520,7 @@ + (void)resetSessionSettings FBIncludeNonModalElements = NO; FBAcceptAlertButtonSelector = @""; FBDismissAlertButtonSelector = @""; + FBAutoClickAlertSelector = @""; FBWaitForIdleTimeout = 10.; FBAnimationCoolOffTimeout = 2.; // 50 should be enough for the majority of the cases. The performance is acceptable for values up to 100. diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index 7f6d57970..cc25fe50c 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -39,6 +39,7 @@ extern NSString* const FB_SETTING_MAX_TYPING_FREQUENCY; extern NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS; extern NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT; extern NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE; +extern NSString* const FB_SETTING_AUTO_CLICK_ALERT_SELECTOR; NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index d91e343ed..09badf744 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -35,3 +35,4 @@ NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS = @"respectSystemAlerts"; NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT = @"useClearTextShortcut"; NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE = @"limitXPathContextScope"; +NSString* const FB_SETTING_AUTO_CLICK_ALERT_SELECTOR = @"autoClickAlertSelector"; From e22fb9a6409f30d86ef97c6c2e468ddac7c73f58 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 10 Apr 2025 06:10:54 +0000 Subject: [PATCH 182/368] chore(release): 9.5.0 [skip ci] ## [9.5.0](https://github.com/appium/WebDriverAgent/compare/v9.4.1...v9.5.0) (2025-04-10) ### Features * Add support for the autoClickAlertSelector setting ([#1002](https://github.com/appium/WebDriverAgent/issues/1002)) ([fd31b95](https://github.com/appium/WebDriverAgent/commit/fd31b9589199d0a7bc76919f6aa7c7c74c498b90)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cb85ea72..b3848005f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.5.0](https://github.com/appium/WebDriverAgent/compare/v9.4.1...v9.5.0) (2025-04-10) + +### Features + +* Add support for the autoClickAlertSelector setting ([#1002](https://github.com/appium/WebDriverAgent/issues/1002)) ([fd31b95](https://github.com/appium/WebDriverAgent/commit/fd31b9589199d0a7bc76919f6aa7c7c74c498b90)) + ## [9.4.1](https://github.com/appium/WebDriverAgent/compare/v9.4.0...v9.4.1) (2025-04-05) ### Miscellaneous Chores diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 9c4dcda35..5cc707d9a 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.4.1 + 9.5.0 CFBundleSignature ???? CFBundleVersion - 9.4.1 + 9.5.0 NSPrincipalClass diff --git a/package.json b/package.json index 8eb150709..5ba6ed9b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.4.1", + "version": "9.5.0", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From cfe052bb3adb3f3b24d0a34f386c60cf1516b308 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Thu, 10 Apr 2025 12:51:07 +0200 Subject: [PATCH 183/368] fix: Make sure we don't store element snapshot in the cache (#1001) --- WebDriverAgentLib/Commands/FBElementCommands.m | 1 + WebDriverAgentLib/Routing/FBResponsePayload.m | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index adcfa6ed6..b9f3faeb1 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -269,6 +269,7 @@ + (NSArray *)routes NSString *focusedUUID = [elementCache storeElement:(useNativeCachingStrategy ? focusedElement : [focusedElement fb_stableInstanceWithUid:focusedElement.fb_uid])]; + focusedElement.lastSnapshot = nil; if (focusedUUID && [focusedUUID isEqualToString:(id)request.parameters[@"uuid"]]) { isFocused = YES; } diff --git a/WebDriverAgentLib/Routing/FBResponsePayload.m b/WebDriverAgentLib/Routing/FBResponsePayload.m index f17517633..e94abee03 100644 --- a/WebDriverAgentLib/Routing/FBResponsePayload.m +++ b/WebDriverAgentLib/Routing/FBResponsePayload.m @@ -55,7 +55,9 @@ id FBResponseWithCachedElement(XCUIElement *element, FBElementCache *elementCache, BOOL compact) { [elementCache storeElement:maybeStable(element)]; - return FBResponseWithStatus([FBCommandStatus okWithValue:FBDictionaryResponseWithElement(element, compact)]); + NSDictionary *response = FBDictionaryResponseWithElement(element, compact); + element.lastSnapshot = nil; + return FBResponseWithStatus([FBCommandStatus okWithValue:response]); } id FBResponseWithCachedElements(NSArray *elements, FBElementCache *elementCache, BOOL compact) @@ -64,6 +66,7 @@ for (XCUIElement *element in elements) { [elementCache storeElement:maybeStable(element)]; [elementsResponse addObject:FBDictionaryResponseWithElement(element, compact)]; + element.lastSnapshot = nil; } return FBResponseWithStatus([FBCommandStatus okWithValue:elementsResponse]); } From 4b256c1a90b105d8c5f8799b0d0b2370f89ebc52 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 10 Apr 2025 10:55:05 +0000 Subject: [PATCH 184/368] chore(release): 9.5.1 [skip ci] ## [9.5.1](https://github.com/appium/WebDriverAgent/compare/v9.5.0...v9.5.1) (2025-04-10) ### Bug Fixes * Make sure we don't store element snapshot in the cache ([#1001](https://github.com/appium/WebDriverAgent/issues/1001)) ([cfe052b](https://github.com/appium/WebDriverAgent/commit/cfe052bb3adb3f3b24d0a34f386c60cf1516b308)) --- CHANGELOG.md | 6 ++++++ WebDriverAgentLib/Info.plist | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3848005f..0513dbb2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [9.5.1](https://github.com/appium/WebDriverAgent/compare/v9.5.0...v9.5.1) (2025-04-10) + +### Bug Fixes + +* Make sure we don't store element snapshot in the cache ([#1001](https://github.com/appium/WebDriverAgent/issues/1001)) ([cfe052b](https://github.com/appium/WebDriverAgent/commit/cfe052bb3adb3f3b24d0a34f386c60cf1516b308)) + ## [9.5.0](https://github.com/appium/WebDriverAgent/compare/v9.4.1...v9.5.0) (2025-04-10) ### Features diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 5cc707d9a..b8a53c683 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 9.5.0 + 9.5.1 CFBundleSignature ???? CFBundleVersion - 9.5.0 + 9.5.1 NSPrincipalClass diff --git a/package.json b/package.json index 5ba6ed9b5..502b4bdbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "appium-webdriveragent", - "version": "9.5.0", + "version": "9.5.1", "description": "Package bundling WebDriverAgent", "main": "./build/index.js", "types": "./build/index.d.ts", From 6603a0ba384917d39389509958ccac03ad174610 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Sat, 19 Apr 2025 16:52:11 +0900 Subject: [PATCH 185/368] fix: Missing text in long text for get text/value (#1007) * replace long text test * add workaround * here too * add comments --- .../XCUIElement+FBWebDriverAttributes.m | 2 + .../Commands/FBElementCommands.m | 3 +- .../Resources/Base.lproj/Main.storyboard | 71 ++++++++++--------- .../FBElementAttributeTests.m | 2 +- 4 files changed, 44 insertions(+), 34 deletions(-) diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m index 4efe2dde6..ac029d791 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m @@ -30,6 +30,8 @@ @implementation XCUIElement (WebDriverAttributesForwarding) { BOOL inDepth = [name isEqualToString:FBStringify(XCUIElement, isWDAccessible)] || [name isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)] + // To retrice entire text https://github.com/appium/appium-xcuitest-driver/issues/2552 + || [name isEqualToString:FBStringify(XCUIElement, wdValue)] || [name isEqualToString:FBStringify(XCUIElement, wdIndex)]; return [self fb_takeSnapshot:inDepth]; } diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index b9f3faeb1..67d5dbe5f 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -151,7 +151,8 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[element fb_takeSnapshot:NO]]; + // 'fb_takeSnapshot:YES' is to retrice entire text https://github.com/appium/appium-xcuitest-driver/issues/2552 + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[element fb_takeSnapshot:YES]]; id text = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel); return FBResponseWithObject(text ?: @""); } diff --git a/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard b/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard index db5221045..5fb805f28 100644 --- a/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard +++ b/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard @@ -1,9 +1,10 @@ - + - + + @@ -19,7 +20,7 @@ - - - - - - - - - - - + @@ -240,32 +240,32 @@ - + - + - + - + - + - + @@ -349,6 +349,9 @@ + + + @@ -367,7 +370,7 @@ - + @@ -377,7 +380,7 @@