appium-webdriveragent 9.10.1 → 9.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [9.12.0](https://github.com/appium/WebDriverAgent/compare/v9.11.0...v9.12.0) (2025-06-04)
2
+
3
+ ### Features
4
+
5
+ * add accessibility traits to XML page source ([#1028](https://github.com/appium/WebDriverAgent/issues/1028)) ([2df6649](https://github.com/appium/WebDriverAgent/commit/2df6649cb532d65a8c14633591b76c90185644cb))
6
+
7
+ ## [9.11.0](https://github.com/appium/WebDriverAgent/compare/v9.10.1...v9.11.0) (2025-06-03)
8
+
9
+ ### Features
10
+
11
+ * Add includeHittableInSource setting for including real hittable attribute in XML source ([#1026](https://github.com/appium/WebDriverAgent/issues/1026)) ([0fa4e74](https://github.com/appium/WebDriverAgent/commit/0fa4e7417404b5975445d381d111753fe681edd4))
12
+
1
13
  ## [9.10.1](https://github.com/appium/WebDriverAgent/compare/v9.10.0...v9.10.1) (2025-05-30)
2
14
 
3
15
  ### Miscellaneous Chores
@@ -353,6 +353,7 @@
353
353
  FB_SETTING_MAX_TYPING_FREQUENCY: @([FBConfiguration maxTypingFrequency]),
354
354
  FB_SETTING_RESPECT_SYSTEM_ALERTS: @([FBConfiguration shouldRespectSystemAlerts]),
355
355
  FB_SETTING_USE_CLEAR_TEXT_SHORTCUT: @([FBConfiguration useClearTextShortcut]),
356
+ FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE: @([FBConfiguration includeHittableInPageSource]),
356
357
  FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE: @([FBConfiguration limitXpathContextScope]),
357
358
  #if !TARGET_OS_TV
358
359
  FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation],
@@ -455,6 +456,9 @@
455
456
  if (nil != [settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT]) {
456
457
  [FBConfiguration setUseClearTextShortcut:[[settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT] boolValue]];
457
458
  }
459
+ if (nil != [settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE]) {
460
+ [FBConfiguration setincludeHittableInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE] boolValue]];
461
+ }
458
462
  if (nil != [settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE]) {
459
463
  [FBConfiguration setLimitXpathContextScope:[[settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE] boolValue]];
460
464
  }
@@ -15,11 +15,11 @@
15
15
  <key>CFBundlePackageType</key>
16
16
  <string>FMWK</string>
17
17
  <key>CFBundleShortVersionString</key>
18
- <string>9.10.1</string>
18
+ <string>9.12.0</string>
19
19
  <key>CFBundleSignature</key>
20
20
  <string>????</string>
21
21
  <key>CFBundleVersion</key>
22
- <string>9.10.1</string>
22
+ <string>9.12.0</string>
23
23
  <key>NSPrincipalClass</key>
24
24
  <string/>
25
25
  </dict>
@@ -332,6 +332,17 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) {
332
332
  */
333
333
  + (void)resetSessionSettings;
334
334
 
335
+ /**
336
+ * Whether to calculate `hittable` attribute using native APIs
337
+ * instead of legacy heuristics.
338
+ * This flag improves accuracy, but may affect performance.
339
+ * Disabled by default.
340
+ *
341
+ * @param enabled Either YES or NO
342
+ */
343
+ + (void)setincludeHittableInPageSource:(BOOL)enabled;
344
+ + (BOOL)includeHittableInPageSource;
345
+
335
346
  @end
336
347
 
337
348
  NS_ASSUME_NONNULL_END
@@ -61,6 +61,7 @@ static BOOL FBLimitXpathContextScope = YES;
61
61
  #if !TARGET_OS_TV
62
62
  static UIInterfaceOrientation FBScreenshotOrientation;
63
63
  #endif
64
+ static BOOL FBShouldincludeHittableInPageSource = NO;
64
65
 
65
66
  @implementation FBConfiguration
66
67
 
@@ -642,4 +643,14 @@ static UIInterfaceOrientation FBScreenshotOrientation;
642
643
  return NO;
643
644
  }
644
645
 
646
+ + (void)setincludeHittableInPageSource:(BOOL)enabled
647
+ {
648
+ FBShouldincludeHittableInPageSource = enabled;
649
+ }
650
+
651
+ + (BOOL)includeHittableInPageSource
652
+ {
653
+ return FBShouldincludeHittableInPageSource;
654
+ }
655
+
645
656
  @end
@@ -40,6 +40,7 @@ extern NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS;
40
40
  extern NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT;
41
41
  extern NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE;
42
42
  extern NSString* const FB_SETTING_AUTO_CLICK_ALERT_SELECTOR;
43
+ extern NSString *const FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE;
43
44
 
44
45
 
45
46
  NS_ASSUME_NONNULL_END
@@ -36,3 +36,4 @@ NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS = @"respectSystemAlerts";
36
36
  NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT = @"useClearTextShortcut";
37
37
  NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE = @"limitXPathContextScope";
38
38
  NSString* const FB_SETTING_AUTO_CLICK_ALERT_SELECTOR = @"autoClickAlertSelector";
39
+ NSString* const FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE = @"includeHittableInPageSource";
@@ -105,6 +105,10 @@
105
105
 
106
106
  @end
107
107
 
108
+ @interface FBTraitsAttribute : FBElementAttribute
109
+
110
+ @end
111
+
108
112
  #if TARGET_OS_TV
109
113
 
110
114
  @interface FBFocusedAttribute : FBElementAttribute
@@ -147,7 +151,10 @@ static NSString *const topNodeIndexPath = @"top";
147
151
 
148
152
  if (rc >= 0) {
149
153
  [self waitUntilStableWithElement:root];
150
- rc = [self xmlRepresentationWithRootElement:[self snapshotWithRoot:root useNative:NO]
154
+ // If 'includeHittableInPageSource' setting is enabled, then use native snapshots
155
+ // to calculate a more accurate value for the 'hittable' attribute.
156
+ rc = [self xmlRepresentationWithRootElement:[self snapshotWithRoot:root
157
+ useNative:FBConfiguration.includeHittableInPageSource]
151
158
  writer:writer
152
159
  elementStore:nil
153
160
  query:nil
@@ -354,9 +361,11 @@ static NSString *const topNodeIndexPath = @"top";
354
361
  NSMutableSet<Class> *includedAttributes;
355
362
  if (nil == query) {
356
363
  includedAttributes = [NSMutableSet setWithArray:FBElementAttribute.supportedAttributes];
357
- // The hittable attribute is expensive to calculate for each snapshot item
358
- // thus we only include it when requested by an xPath query
359
- [includedAttributes removeObject:FBHittableAttribute.class];
364
+ if (!FBConfiguration.includeHittableInPageSource) {
365
+ // The hittable attribute is expensive to calculate for each snapshot item
366
+ // thus we only include it when requested explicitly
367
+ [includedAttributes removeObject:FBHittableAttribute.class];
368
+ }
360
369
  if (nil != excludedAttributes) {
361
370
  for (NSString *excludedAttributeName in excludedAttributes) {
362
371
  for (Class supportedAttribute in FBElementAttribute.supportedAttributes) {
@@ -578,6 +587,7 @@ static NSString *const FBAbstractMethodInvocationException = @"AbstractMethodInv
578
587
  FBIndexAttribute.class,
579
588
  FBHittableAttribute.class,
580
589
  FBPlaceholderValueAttribute.class,
590
+ FBTraitsAttribute.class,
581
591
  ];
582
592
  }
583
593
 
@@ -815,3 +825,17 @@ static NSString *const FBAbstractMethodInvocationException = @"AbstractMethodInv
815
825
  }
816
826
 
817
827
  @end
828
+
829
+ @implementation FBTraitsAttribute
830
+
831
+ + (NSString *)name
832
+ {
833
+ return @"traits";
834
+ }
835
+
836
+ + (NSString *)valueForElement:(id<FBElement>)element
837
+ {
838
+ return element.wdTraits;
839
+ }
840
+
841
+ @end
@@ -57,7 +57,7 @@
57
57
  NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot
58
58
  options:nil];
59
59
  XCTAssertNotNil(xmlStr);
60
- NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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];
60
+ NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" traits=\"%@\"/>\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.wdTraits];
61
61
  XCTAssertEqualObjects(xmlStr, expectedXml);
62
62
  }
63
63
 
@@ -70,7 +70,7 @@
70
70
  NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot
71
71
  options:options];
72
72
  XCTAssertNotNil(xmlStr);
73
- NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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];
73
+ NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@>\n <%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" traits=\"%@\"/>\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.wdTraits, scope];
74
74
  XCTAssertEqualObjects(xmlStr, expectedXml);
75
75
  }
76
76
 
@@ -83,7 +83,7 @@
83
83
  NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot
84
84
  options:options];
85
85
  XCTAssertNotNil(xmlStr);
86
- NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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]];
86
+ NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" traits=\"%@\"/>\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.wdTraits];
87
87
  XCTAssertEqualObjects(xmlStr, expectedXml);
88
88
  }
89
89
 
@@ -12,4 +12,5 @@
12
12
  @interface XCElementSnapshotDouble : NSObject<XCUIElementAttributes>
13
13
  @property (readwrite, nullable) id value;
14
14
  @property (readwrite, nullable, copy) NSString *label;
15
+ @property (nonatomic, assign) UIAccessibilityTraits traits;
15
16
  @end
@@ -108,4 +108,8 @@
108
108
  return CGRectZero;
109
109
  }
110
110
 
111
+ - (UIAccessibilityTraits)traits
112
+ {
113
+ return UIAccessibilityTraitButton;
114
+ }
111
115
  @end
@@ -63,8 +63,9 @@
63
63
  NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
64
64
  xpathQuery:nil
65
65
  excludingAttributes:nil];
66
- NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n",
67
- 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];
66
+ NSLog(@"[DefaultXPath] Result XML:\n%@", resultXml);
67
+ NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\" traits=\"%@\" private_indexPath=\"top\"/>\n",
68
+ 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, element.wdTraits];
68
69
  XCTAssertTrue([resultXml isEqualToString: expectedXml]);
69
70
  }
70
71
 
@@ -74,7 +75,7 @@
74
75
  id<FBElement> element = (id<FBElement>)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot];
75
76
  NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
76
77
  xpathQuery:nil
77
- excludingAttributes:@[@"type", @"visible", @"value", @"index"]];
78
+ excludingAttributes:@[@"type", @"visible", @"value", @"index", @"traits"]];
78
79
  NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ name=\"%@\" label=\"%@\" enabled=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n",
79
80
  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];
80
81
  XCTAssertEqualObjects(resultXml, expectedXml);
@@ -89,8 +90,8 @@
89
90
  NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
90
91
  xpathQuery:[NSString stringWithFormat:@"//%@[@*]", element.wdType]
91
92
  excludingAttributes:@[@"visible"]];
92
- NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" hittable=\"%@\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n",
93
- element.wdType, element.wdType, @"йоло&lt;&gt;&amp;&quot;", element.wdName, @"a&#10;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];
93
+ NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" hittable=\"%@\" placeholderValue=\"%@\" traits=\"%@\" private_indexPath=\"top\"/>\n",
94
+ element.wdType, element.wdType, @"йоло&lt;&gt;&amp;&quot;", element.wdName, @"a&#10;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];
94
95
  XCTAssertEqualObjects(expectedXml, resultXml);
95
96
  }
96
97
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "9.10.1",
3
+ "version": "9.12.0",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",