diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index 9782c3b08..f1d2e418f 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -354,6 +354,7 @@ + (NSArray *)routes FB_SETTING_RESPECT_SYSTEM_ALERTS: @([FBConfiguration shouldRespectSystemAlerts]), FB_SETTING_USE_CLEAR_TEXT_SHORTCUT: @([FBConfiguration useClearTextShortcut]), FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE: @([FBConfiguration includeHittableInPageSource]), + FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE: @([FBConfiguration includeNativeFrameInPageSource]), FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE: @([FBConfiguration limitXpathContextScope]), #if !TARGET_OS_TV FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation], @@ -457,7 +458,10 @@ + (NSArray *)routes [FBConfiguration setUseClearTextShortcut:[[settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT] boolValue]]; } if (nil != [settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE]) { - [FBConfiguration setincludeHittableInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE] boolValue]]; + [FBConfiguration setIncludeHittableInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE] boolValue]]; + } + if (nil != [settings objectForKey:FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE]) { + [FBConfiguration setIncludeNativeFrameInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE] boolValue]]; } if (nil != [settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE]) { [FBConfiguration setLimitXpathContextScope:[[settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE] boolValue]]; diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index 743d48850..cfadf4cbb 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -340,9 +340,25 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) { * * @param enabled Either YES or NO */ -+ (void)setincludeHittableInPageSource:(BOOL)enabled; ++ (void)setIncludeHittableInPageSource:(BOOL)enabled; + (BOOL)includeHittableInPageSource; +/** + * Whether to include `nativeFrame` attribute in the XML page source. + * + * When enabled, the XML representation will contain the precise rendered + * frame of the UI element. + * + * This value is more accurate than the legacy `wdFrame`, which applies rounding + * and may introduce inconsistencies in size and position calculations. + * + * The value is disabled by default to avoid potential performance overhead. + * + * @param enabled Either YES or NO + */ ++ (void)setIncludeNativeFrameInPageSource:(BOOL)enabled; ++ (BOOL)includeNativeFrameInPageSource; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index a28290237..56057c83d 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -61,7 +61,8 @@ #if !TARGET_OS_TV static UIInterfaceOrientation FBScreenshotOrientation; #endif -static BOOL FBShouldincludeHittableInPageSource = NO; +static BOOL FBShouldIncludeHittableInPageSource = NO; +static BOOL FBShouldIncludeNativeFrameInPageSource = NO; @implementation FBConfiguration @@ -643,14 +644,24 @@ + (BOOL)reduceMotionEnabled return NO; } -+ (void)setincludeHittableInPageSource:(BOOL)enabled ++ (void)setIncludeHittableInPageSource:(BOOL)enabled { - FBShouldincludeHittableInPageSource = enabled; + FBShouldIncludeHittableInPageSource = enabled; } + (BOOL)includeHittableInPageSource { - return FBShouldincludeHittableInPageSource; + return FBShouldIncludeHittableInPageSource; +} + ++ (void)setIncludeNativeFrameInPageSource:(BOOL)enabled +{ + FBShouldIncludeNativeFrameInPageSource = enabled; +} + ++ (BOOL)includeNativeFrameInPageSource +{ + return FBShouldIncludeNativeFrameInPageSource; } @end diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index 2b259563b..ab1a5cb9c 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -41,6 +41,7 @@ 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; extern NSString *const FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE; +extern NSString *const FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE; NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index 6a019b2d7..441f2e5cd 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -37,3 +37,4 @@ NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE = @"limitXPathContextScope"; NSString* const FB_SETTING_AUTO_CLICK_ALERT_SELECTOR = @"autoClickAlertSelector"; NSString* const FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE = @"includeHittableInPageSource"; +NSString* const FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE = @"includeNativeFrameInPageSource"; diff --git a/WebDriverAgentLib/Utilities/FBXPath.m b/WebDriverAgentLib/Utilities/FBXPath.m index 0f9ae4016..f91d096c4 100644 --- a/WebDriverAgentLib/Utilities/FBXPath.m +++ b/WebDriverAgentLib/Utilities/FBXPath.m @@ -105,6 +105,10 @@ @interface FBPlaceholderValueAttribute : FBElementAttribute @end +@interface FBNativeFrameAttribute : FBElementAttribute + +@end + @interface FBTraitsAttribute : FBElementAttribute @end @@ -366,6 +370,10 @@ + (int)xmlRepresentationWithRootElement:(id)root // thus we only include it when requested explicitly [includedAttributes removeObject:FBHittableAttribute.class]; } + if (!FBConfiguration.includeNativeFrameInPageSource) { + // Include nativeFrame only when requested + [includedAttributes removeObject:FBNativeFrameAttribute.class]; + } if (nil != excludedAttributes) { for (NSString *excludedAttributeName in excludedAttributes) { for (Class supportedAttribute in FBElementAttribute.supportedAttributes) { @@ -588,6 +596,7 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forElement:(id)eleme FBHittableAttribute.class, FBPlaceholderValueAttribute.class, FBTraitsAttribute.class, + FBNativeFrameAttribute.class, ]; } @@ -823,7 +832,19 @@ + (NSString *)valueForElement:(id)element { return element.wdPlaceholderValue; } +@end + +@implementation FBNativeFrameAttribute ++ (NSString *)name +{ + return @"nativeFrame"; +} + ++ (NSString *)valueForElement:(id)element +{ + return NSStringFromCGRect(element.wdNativeFrame); +} @end @implementation FBTraitsAttribute diff --git a/WebDriverAgentTests/UnitTests/FBXPathTests.m b/WebDriverAgentTests/UnitTests/FBXPathTests.m index a0e478218..1f162d1d1 100644 --- a/WebDriverAgentTests/UnitTests/FBXPathTests.m +++ b/WebDriverAgentTests/UnitTests/FBXPathTests.m @@ -75,7 +75,7 @@ - (void)testtXPathPresentationWithSomeAttributesExcluded id element = (id)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot]; NSString *resultXml = [self xmlStringWithElement:(id)element xpathQuery:nil - excludingAttributes:@[@"type", @"visible", @"value", @"index", @"traits"]]; + excludingAttributes:@[@"type", @"visible", @"value", @"index", @"traits", @"nativeFrame"]]; 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); @@ -90,8 +90,8 @@ - (void)testXPathPresentationBasedOnQueryMatchingAllAttributes 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=\"%@\" traits=\"%@\" 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, element.wdTraits]; + NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" hittable=\"%@\" placeholderValue=\"%@\" traits=\"%@\" nativeFrame=\"%@\" 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, element.wdTraits, NSStringFromCGRect(element.wdNativeFrame)]; XCTAssertEqualObjects(expectedXml, resultXml); }