appium-webdriveragent 9.12.0 → 9.14.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.14.0](https://github.com/appium/WebDriverAgent/compare/v9.13.0...v9.14.0) (2025-06-09)
2
+
3
+ ### Features
4
+
5
+ * add minimum and maximum value attributes to page source ([#1031](https://github.com/appium/WebDriverAgent/issues/1031)) ([0e4e7e7](https://github.com/appium/WebDriverAgent/commit/0e4e7e7c483b9196edae576481f4e37f99fc8705))
6
+
7
+ ## [9.13.0](https://github.com/appium/WebDriverAgent/compare/v9.12.0...v9.13.0) (2025-06-05)
8
+
9
+ ### Features
10
+
11
+ * expose nativeFrame attribute in XML page source ([#1029](https://github.com/appium/WebDriverAgent/issues/1029)) ([5b56a45](https://github.com/appium/WebDriverAgent/commit/5b56a453f836cbc4358ce24ae43032658467c35c))
12
+
1
13
  ## [9.12.0](https://github.com/appium/WebDriverAgent/compare/v9.11.0...v9.12.0) (2025-06-04)
2
14
 
3
15
  ### Features
@@ -7,6 +7,10 @@
7
7
  objects = {
8
8
 
9
9
  /* Begin PBXBuildFile section */
10
+ 0E0413382DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */; };
11
+ 0E0413392DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */; };
12
+ 0E04133B2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */; };
13
+ 0E04133C2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */; };
10
14
  1357E296233D05240054BDB8 /* XCUIHitPointResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1357E295233D05240054BDB8 /* XCUIHitPointResult.h */; };
11
15
  1357E297233D05240054BDB8 /* XCUIHitPointResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1357E295233D05240054BDB8 /* XCUIHitPointResult.h */; };
12
16
  13815F6F2328D20400CDAB61 /* FBActiveAppDetectionPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 13815F6D2328D20400CDAB61 /* FBActiveAppDetectionPoint.h */; };
@@ -918,6 +922,8 @@
918
922
  /* End PBXCopyFilesBuildPhase section */
919
923
 
920
924
  /* Begin PBXFileReference section */
925
+ 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBMinMax.m"; sourceTree = "<group>"; };
926
+ 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBMinMax.h"; sourceTree = "<group>"; };
921
927
  1357E295233D05240054BDB8 /* XCUIHitPointResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCUIHitPointResult.h; sourceTree = "<group>"; };
922
928
  13815F6D2328D20400CDAB61 /* FBActiveAppDetectionPoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBActiveAppDetectionPoint.h; sourceTree = "<group>"; };
923
929
  13815F6E2328D20400CDAB61 /* FBActiveAppDetectionPoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBActiveAppDetectionPoint.m; sourceTree = "<group>"; };
@@ -1785,6 +1791,8 @@
1785
1791
  EE8DDD7C20C5733B004D4925 /* XCUIElement+FBForceTouch.m */,
1786
1792
  EE9AB7471CAEDF0C008C271F /* XCUIElement+FBIsVisible.h */,
1787
1793
  EE9AB7481CAEDF0C008C271F /* XCUIElement+FBIsVisible.m */,
1794
+ 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */,
1795
+ 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */,
1788
1796
  7136A4771E8918E60024FC3D /* XCUIElement+FBPickerWheel.h */,
1789
1797
  7136A4781E8918E60024FC3D /* XCUIElement+FBPickerWheel.m */,
1790
1798
  71D3B3D3267FC7260076473D /* XCUIElement+FBResolve.h */,
@@ -2377,6 +2385,7 @@
2377
2385
  641EE6782240C5CA00173FCB /* XCTNSNotificationExpectation.h in Headers */,
2378
2386
  641EE6792240C5CA00173FCB /* XCUIRecorderNodeFinder.h in Headers */,
2379
2387
  641EE67A2240C5CA00173FCB /* XCUIElement+FBAccessibility.h in Headers */,
2388
+ 0E04133C2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */,
2380
2389
  641EE67B2240C5CA00173FCB /* XCUIRecorderUtilities.h in Headers */,
2381
2390
  6496A5DA230D6EB30087F8CB /* AXSettings.h in Headers */,
2382
2391
  641EE67C2240C5CA00173FCB /* XCTestCaseRun.h in Headers */,
@@ -2701,6 +2710,7 @@
2701
2710
  EEE9B4721CD02B88009D2030 /* FBRunLoopSpinner.h in Headers */,
2702
2711
  EE3A18621CDE618F00DE4205 /* FBErrorBuilder.h in Headers */,
2703
2712
  EE35AD261E3B77D600A02D78 /* XCApplicationMonitor_iOS.h in Headers */,
2713
+ 0E04133B2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */,
2704
2714
  EE3A18661CDE734B00DE4205 /* FBKeyboard.h in Headers */,
2705
2715
  AD6C269C1CF2494200F8B5FF /* XCUIApplication+FBHelpers.h in Headers */,
2706
2716
  714D88CC2733FB970074A925 /* FBXMLGenerationOptions.h in Headers */,
@@ -3202,6 +3212,7 @@
3202
3212
  71BB58F92B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */,
3203
3213
  641EE6152240C5CA00173FCB /* XCUIElement+FBScrolling.m in Sources */,
3204
3214
  641EE6162240C5CA00173FCB /* FBSessionCommands.m in Sources */,
3215
+ 0E0413392DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */,
3205
3216
  641EE6192240C5CA00173FCB /* FBConfiguration.m in Sources */,
3206
3217
  641EE61A2240C5CA00173FCB /* FBElementCache.m in Sources */,
3207
3218
  71F5BE26252E576C00EE9EBA /* XCUIElement+FBSwiping.m in Sources */,
@@ -3249,6 +3260,7 @@
3249
3260
  13DE7A45287C2A8D003243C6 /* FBXCAccessibilityElement.m in Sources */,
3250
3261
  641EE70E2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */,
3251
3262
  71BD20741F86116100B36EC2 /* XCUIApplication+FBTouchAction.m in Sources */,
3263
+ 0E0413382DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */,
3252
3264
  EE158AE71CBD456F00A3E3F0 /* FBWebServer.m in Sources */,
3253
3265
  715557D4211DBCE700613B26 /* FBTCPSocket.m in Sources */,
3254
3266
  EE3A18631CDE618F00DE4205 /* FBErrorBuilder.m in Sources */,
@@ -49,6 +49,8 @@ static NSString* const FBExclusionAttributeFocused = @"focused";
49
49
  static NSString* const FBExclusionAttributePlaceholderValue = @"placeholderValue";
50
50
  static NSString* const FBExclusionAttributeNativeFrame = @"nativeFrame";
51
51
  static NSString* const FBExclusionAttributeTraits = @"traits";
52
+ static NSString* const FBExclusionAttributeMinValue = @"minValue";
53
+ static NSString* const FBExclusionAttributeMaxValue = @"maxValue";
52
54
 
53
55
  _Nullable id extractIssueProperty(id issue, NSString *propertyName) {
54
56
  SEL selector = NSSelectorFromString(propertyName);
@@ -211,6 +213,8 @@ NSDictionary<NSString *, NSString *> *customExclusionAttributesMap(void) {
211
213
  FBExclusionAttributePlaceholderValue,
212
214
  FBExclusionAttributeNativeFrame,
213
215
  FBExclusionAttributeTraits,
216
+ FBExclusionAttributeMinValue,
217
+ FBExclusionAttributeMaxValue,
214
218
  nil];
215
219
 
216
220
  for (NSString *key in attributeBlocks) {
@@ -248,7 +252,7 @@ NSDictionary<NSString *, NSString *> *customExclusionAttributesMap(void) {
248
252
 
249
253
  {
250
254
  // Base attributes common to every element
251
- NSMutableDictionary<NSString *, NSString *(^)(void)> *blocks =
255
+ NSMutableDictionary<NSString *, id(^)(void)> *blocks =
252
256
  [@{
253
257
  FBExclusionAttributeFrame: ^{
254
258
  return NSStringFromCGRect(wrappedSnapshot.wdFrame);
@@ -282,6 +286,16 @@ NSDictionary<NSString *, NSString *> *customExclusionAttributesMap(void) {
282
286
  };
283
287
  }
284
288
 
289
+ // Only for elements that support min/max value
290
+ if (FBDoesElementSupportMinMaxValue(elementType)) {
291
+ blocks[FBExclusionAttributeMinValue] = ^{
292
+ return wrappedSnapshot.wdMinValue;
293
+ };
294
+ blocks[FBExclusionAttributeMaxValue] = ^{
295
+ return wrappedSnapshot.wdMaxValue;
296
+ };
297
+ }
298
+
285
299
  return [blocks copy];
286
300
  }
287
301
 
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ */
9
+
10
+ #import <WebDriverAgentLib/FBXCElementSnapshotWrapper.h>
11
+
12
+ NS_ASSUME_NONNULL_BEGIN
13
+
14
+ @interface XCUIElement (FBMinMax)
15
+
16
+ /*! Minimum value (minValue) – may be nil if the element does not have this attribute */
17
+ @property (nonatomic, readonly, nullable) NSNumber *fb_minValue;
18
+
19
+ /*! Maximum value (maxValue) - may be nil if the element does not have this attribute */
20
+ @property (nonatomic, readonly, nullable) NSNumber *fb_maxValue;
21
+
22
+ @end
23
+
24
+ @interface FBXCElementSnapshotWrapper (FBMinMax)
25
+
26
+ /*! Minimum value (minValue) – may be nil if the element does not have this attribute */
27
+ @property (nonatomic, readonly, nullable) NSNumber *fb_minValue;
28
+
29
+ /*! Maximum value (maxValue) - may be nil if the element does not have this attribute */
30
+ @property (nonatomic, readonly, nullable) NSNumber *fb_maxValue;
31
+
32
+ @end
33
+
34
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ */
9
+
10
+ #import "FBLogger.h"
11
+ #import "XCUIElement+FBMinMax.h"
12
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
13
+ #import "XCUIElement+FBUtilities.h"
14
+ #import "XCTestPrivateSymbols.h"
15
+
16
+ @interface FBXCElementSnapshotWrapper (FBMinMaxInternal)
17
+
18
+ - (NSNumber *)fb_numericAttribute:(NSString *)attributeName symbol:(NSNumber *)symbol;
19
+
20
+ @end
21
+
22
+ @implementation XCUIElement (FBMinMax)
23
+
24
+ - (NSNumber *)fb_minValue
25
+ {
26
+ @autoreleasepool {
27
+ id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
28
+ return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_minValue];
29
+ }
30
+ }
31
+
32
+ - (NSNumber *)fb_maxValue
33
+ {
34
+ @autoreleasepool {
35
+ id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
36
+ return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_maxValue];
37
+ }
38
+ }
39
+
40
+ @end
41
+
42
+ @implementation FBXCElementSnapshotWrapper (FBMinMax)
43
+
44
+ - (NSNumber *)fb_minValue
45
+ {
46
+ return [self fb_numericAttribute:FB_XCAXACustomMinValueAttributeName
47
+ symbol:FB_XCAXACustomMinValueAttribute];
48
+ }
49
+
50
+ - (NSNumber *)fb_maxValue
51
+ {
52
+ return [self fb_numericAttribute:FB_XCAXACustomMaxValueAttributeName
53
+ symbol:FB_XCAXACustomMaxValueAttribute];
54
+ }
55
+
56
+ - (NSNumber *)fb_numericAttribute:(NSString *)attributeName symbol:(NSNumber *)symbol
57
+ {
58
+ NSNumber *cached = (self.snapshot.additionalAttributes ?: @{})[symbol];
59
+ if (cached) {
60
+ return cached;
61
+ }
62
+
63
+ NSError *error = nil;
64
+ NSNumber *raw = [self fb_attributeValue:attributeName error:&error];
65
+ if (nil != raw) {
66
+ NSMutableDictionary *updated = [NSMutableDictionary dictionaryWithDictionary:self.additionalAttributes ?: @{}];
67
+ updated[symbol] = raw;
68
+ self.snapshot.additionalAttributes = updated.copy;
69
+ return raw;
70
+ }
71
+
72
+ [FBLogger logFmt:@"[FBMinMax] Cannot determine %@ for %@: %@", attributeName, self.fb_description, error.localizedDescription];
73
+ return nil;
74
+ }
75
+
76
+ @end
@@ -23,6 +23,7 @@
23
23
  #import "XCTestPrivateSymbols.h"
24
24
  #import "XCUIHitPointResult.h"
25
25
  #import "FBAccessibilityTraits.h"
26
+ #import "XCUIElement+FBMinMax.h"
26
27
 
27
28
  #define BROKEN_RECT CGRectMake(-1, -1, 0, 0)
28
29
 
@@ -76,6 +77,16 @@
76
77
  return [self valueForKey:[FBElementUtils wdAttributeNameForAttributeName:name]];
77
78
  }
78
79
 
80
+ - (NSNumber *)wdMinValue
81
+ {
82
+ return self.fb_minValue;
83
+ }
84
+
85
+ - (NSNumber *)wdMaxValue
86
+ {
87
+ return self.fb_maxValue;
88
+ }
89
+
79
90
  - (NSString *)wdValue
80
91
  {
81
92
  id value = self.value;
@@ -354,6 +354,8 @@
354
354
  FB_SETTING_RESPECT_SYSTEM_ALERTS: @([FBConfiguration shouldRespectSystemAlerts]),
355
355
  FB_SETTING_USE_CLEAR_TEXT_SHORTCUT: @([FBConfiguration useClearTextShortcut]),
356
356
  FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE: @([FBConfiguration includeHittableInPageSource]),
357
+ FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE: @([FBConfiguration includeNativeFrameInPageSource]),
358
+ FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE: @([FBConfiguration includeMinMaxValueInPageSource]),
357
359
  FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE: @([FBConfiguration limitXpathContextScope]),
358
360
  #if !TARGET_OS_TV
359
361
  FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation],
@@ -457,7 +459,13 @@
457
459
  [FBConfiguration setUseClearTextShortcut:[[settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT] boolValue]];
458
460
  }
459
461
  if (nil != [settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE]) {
460
- [FBConfiguration setincludeHittableInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE] boolValue]];
462
+ [FBConfiguration setIncludeHittableInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE] boolValue]];
463
+ }
464
+ if (nil != [settings objectForKey:FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE]) {
465
+ [FBConfiguration setIncludeNativeFrameInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE] boolValue]];
466
+ }
467
+ if (nil != [settings objectForKey:FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE]) {
468
+ [FBConfiguration setIncludeMinMaxValueInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE] boolValue]];
461
469
  }
462
470
  if (nil != [settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE]) {
463
471
  [FBConfiguration setLimitXpathContextScope:[[settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE] boolValue]];
@@ -15,11 +15,11 @@
15
15
  <key>CFBundlePackageType</key>
16
16
  <string>FMWK</string>
17
17
  <key>CFBundleShortVersionString</key>
18
- <string>9.12.0</string>
18
+ <string>9.14.0</string>
19
19
  <key>CFBundleSignature</key>
20
20
  <string>????</string>
21
21
  <key>CFBundleVersion</key>
22
- <string>9.12.0</string>
22
+ <string>9.14.0</string>
23
23
  <key>NSPrincipalClass</key>
24
24
  <string/>
25
25
  </dict>
@@ -71,6 +71,12 @@ NS_ASSUME_NONNULL_BEGIN
71
71
  /*! Element's placeholder value */
72
72
  @property (nonatomic, readonly, copy, nullable) NSString *wdPlaceholderValue;
73
73
 
74
+ /*! Element's minimum value */
75
+ @property (nonatomic, readonly, strong, nullable) NSNumber *wdMinValue;
76
+
77
+ /*! Element's maximum value */
78
+ @property (nonatomic, readonly, strong, nullable) NSNumber *wdMaxValue;
79
+
74
80
  /**
75
81
  Returns value of given property specified in WebDriver Spec
76
82
  Check the FBElement protocol to get list of supported attributes.
@@ -340,9 +340,37 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) {
340
340
  *
341
341
  * @param enabled Either YES or NO
342
342
  */
343
- + (void)setincludeHittableInPageSource:(BOOL)enabled;
343
+ + (void)setIncludeHittableInPageSource:(BOOL)enabled;
344
344
  + (BOOL)includeHittableInPageSource;
345
345
 
346
+ /**
347
+ * Whether to include `nativeFrame` attribute in the XML page source.
348
+ *
349
+ * When enabled, the XML representation will contain the precise rendered
350
+ * frame of the UI element.
351
+ *
352
+ * This value is more accurate than the legacy `wdFrame`, which applies rounding
353
+ * and may introduce inconsistencies in size and position calculations.
354
+ *
355
+ * The value is disabled by default to avoid potential performance overhead.
356
+ *
357
+ * @param enabled Either YES or NO
358
+ */
359
+ + (void)setIncludeNativeFrameInPageSource:(BOOL)enabled;
360
+ + (BOOL)includeNativeFrameInPageSource;
361
+
362
+ /**
363
+ * Whether to include `minValue`/`maxValue` attributes in the page source.
364
+ * These attributes are retrieved from native element snapshots and represent
365
+ * value boundaries for elements like sliders or progress indicators.
366
+ * This may affect performance if used on many elements.
367
+ * Disabled by default.
368
+ *
369
+ * @param enabled Either YES or NO
370
+ */
371
+ + (void)setIncludeMinMaxValueInPageSource:(BOOL)enabled;
372
+ + (BOOL)includeMinMaxValueInPageSource;
373
+
346
374
  @end
347
375
 
348
376
  NS_ASSUME_NONNULL_END
@@ -61,7 +61,9 @@ static BOOL FBLimitXpathContextScope = YES;
61
61
  #if !TARGET_OS_TV
62
62
  static UIInterfaceOrientation FBScreenshotOrientation;
63
63
  #endif
64
- static BOOL FBShouldincludeHittableInPageSource = NO;
64
+ static BOOL FBShouldIncludeHittableInPageSource = NO;
65
+ static BOOL FBShouldIncludeNativeFrameInPageSource = NO;
66
+ static BOOL FBShouldIncludeMinMaxValueInPageSource = NO;
65
67
 
66
68
  @implementation FBConfiguration
67
69
 
@@ -643,14 +645,34 @@ static BOOL FBShouldincludeHittableInPageSource = NO;
643
645
  return NO;
644
646
  }
645
647
 
646
- + (void)setincludeHittableInPageSource:(BOOL)enabled
648
+ + (void)setIncludeHittableInPageSource:(BOOL)enabled
647
649
  {
648
- FBShouldincludeHittableInPageSource = enabled;
650
+ FBShouldIncludeHittableInPageSource = enabled;
649
651
  }
650
652
 
651
653
  + (BOOL)includeHittableInPageSource
652
654
  {
653
- return FBShouldincludeHittableInPageSource;
655
+ return FBShouldIncludeHittableInPageSource;
656
+ }
657
+
658
+ + (void)setIncludeNativeFrameInPageSource:(BOOL)enabled
659
+ {
660
+ FBShouldIncludeNativeFrameInPageSource = enabled;
661
+ }
662
+
663
+ + (BOOL)includeNativeFrameInPageSource
664
+ {
665
+ return FBShouldIncludeNativeFrameInPageSource;
666
+ }
667
+
668
+ + (void)setIncludeMinMaxValueInPageSource:(BOOL)enabled
669
+ {
670
+ FBShouldIncludeMinMaxValueInPageSource = enabled;
671
+ }
672
+
673
+ + (BOOL)includeMinMaxValueInPageSource
674
+ {
675
+ return FBShouldIncludeMinMaxValueInPageSource;
654
676
  }
655
677
 
656
678
  @end
@@ -15,8 +15,16 @@ NS_ASSUME_NONNULL_BEGIN
15
15
  Checks if the element is a text field
16
16
 
17
17
  @param elementType XCTest element type
18
- @return YES if the elemnt is a text field
18
+ @return YES if the element is a text field
19
19
  */
20
20
  BOOL FBDoesElementSupportInnerText(XCUIElementType elementType);
21
21
 
22
+ /**
23
+ Checks if the element supports min/max value attributes
24
+
25
+ @param elementType XCTest element type
26
+ @return YES if the element type supports min/max value attributes
27
+ */
28
+ BOOL FBDoesElementSupportMinMaxValue(XCUIElementType elementType);
29
+
22
30
  NS_ASSUME_NONNULL_END
@@ -15,3 +15,8 @@ BOOL FBDoesElementSupportInnerText(XCUIElementType elementType) {
15
15
  || elementType == XCUIElementTypeSearchField
16
16
  || elementType == XCUIElementTypeSecureTextField;
17
17
  }
18
+
19
+ BOOL FBDoesElementSupportMinMaxValue(XCUIElementType elementType) {
20
+ return elementType == XCUIElementTypeSlider
21
+ || elementType == XCUIElementTypeStepper;
22
+ }
@@ -41,6 +41,7 @@ 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
43
  extern NSString *const FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE;
44
-
44
+ extern NSString *const FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE;
45
+ extern NSString *const FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE;
45
46
 
46
47
  NS_ASSUME_NONNULL_END
@@ -37,3 +37,5 @@ 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
39
  NSString* const FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE = @"includeHittableInPageSource";
40
+ NSString* const FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE = @"includeNativeFrameInPageSource";
41
+ NSString* const FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE = @"includeMinMaxValueInPageSource";
@@ -22,6 +22,7 @@
22
22
  #import "XCUIElement+FBUtilities.h"
23
23
  #import "XCUIElement+FBWebDriverAttributes.h"
24
24
  #import "XCTestPrivateSymbols.h"
25
+ #import "FBElementHelpers.h"
25
26
 
26
27
 
27
28
  @interface FBElementAttribute : NSObject
@@ -105,10 +106,22 @@
105
106
 
106
107
  @end
107
108
 
109
+ @interface FBNativeFrameAttribute : FBElementAttribute
110
+
111
+ @end
112
+
108
113
  @interface FBTraitsAttribute : FBElementAttribute
109
114
 
110
115
  @end
111
116
 
117
+ @interface FBMinValueAttribute : FBElementAttribute
118
+
119
+ @end
120
+
121
+ @interface FBMaxValueAttribute : FBElementAttribute
122
+
123
+ @end
124
+
112
125
  #if TARGET_OS_TV
113
126
 
114
127
  @interface FBFocusedAttribute : FBElementAttribute
@@ -366,6 +379,15 @@ static NSString *const topNodeIndexPath = @"top";
366
379
  // thus we only include it when requested explicitly
367
380
  [includedAttributes removeObject:FBHittableAttribute.class];
368
381
  }
382
+ if (!FBConfiguration.includeNativeFrameInPageSource) {
383
+ // Include nativeFrame only when requested
384
+ [includedAttributes removeObject:FBNativeFrameAttribute.class];
385
+ }
386
+ if (!FBConfiguration.includeMinMaxValueInPageSource) {
387
+ // minValue/maxValue are retrieved from private APIs and may be slow on deep trees
388
+ [includedAttributes removeObject:FBMinValueAttribute.class];
389
+ [includedAttributes removeObject:FBMaxValueAttribute.class];
390
+ }
369
391
  if (nil != excludedAttributes) {
370
392
  for (NSString *excludedAttributeName in excludedAttributes) {
371
393
  for (Class supportedAttribute in FBElementAttribute.supportedAttributes) {
@@ -429,6 +451,16 @@ static NSString *const topNodeIndexPath = @"top";
429
451
  if (includedAttributes && ![includedAttributes containsObject:attributeCls]) {
430
452
  continue;
431
453
  }
454
+ // Text-input placeholder (only for elements that support inner text)
455
+ if ((attributeCls == FBPlaceholderValueAttribute.class) &&
456
+ !FBDoesElementSupportInnerText(element.elementType)) {
457
+ continue;
458
+ }
459
+ // Only for elements that support min/max value
460
+ if ((attributeCls == FBMinValueAttribute.class || attributeCls == FBMaxValueAttribute.class) &&
461
+ !FBDoesElementSupportMinMaxValue(element.elementType)) {
462
+ continue;
463
+ }
432
464
  int rc = [attributeCls recordWithWriter:writer
433
465
  forElement:[FBXCElementSnapshotWrapper ensureWrapped:element]];
434
466
  if (rc < 0) {
@@ -588,6 +620,9 @@ static NSString *const FBAbstractMethodInvocationException = @"AbstractMethodInv
588
620
  FBHittableAttribute.class,
589
621
  FBPlaceholderValueAttribute.class,
590
622
  FBTraitsAttribute.class,
623
+ FBNativeFrameAttribute.class,
624
+ FBMinValueAttribute.class,
625
+ FBMaxValueAttribute.class,
591
626
  ];
592
627
  }
593
628
 
@@ -823,7 +858,19 @@ static NSString *const FBAbstractMethodInvocationException = @"AbstractMethodInv
823
858
  {
824
859
  return element.wdPlaceholderValue;
825
860
  }
861
+ @end
862
+
863
+ @implementation FBNativeFrameAttribute
826
864
 
865
+ + (NSString *)name
866
+ {
867
+ return @"nativeFrame";
868
+ }
869
+
870
+ + (NSString *)valueForElement:(id<FBElement>)element
871
+ {
872
+ return NSStringFromCGRect(element.wdNativeFrame);
873
+ }
827
874
  @end
828
875
 
829
876
  @implementation FBTraitsAttribute
@@ -839,3 +886,31 @@ static NSString *const FBAbstractMethodInvocationException = @"AbstractMethodInv
839
886
  }
840
887
 
841
888
  @end
889
+
890
+ @implementation FBMinValueAttribute
891
+
892
+ + (NSString *)name
893
+ {
894
+ return @"minValue";
895
+ }
896
+
897
+ + (NSString *)valueForElement:(id<FBElement>)element
898
+ {
899
+ return [element.wdMinValue stringValue];
900
+ }
901
+
902
+ @end
903
+
904
+ @implementation FBMaxValueAttribute
905
+
906
+ + (NSString *)name
907
+ {
908
+ return @"maxValue";
909
+ }
910
+
911
+ + (NSString *)valueForElement:(id<FBElement>)element
912
+ {
913
+ return [element.wdMaxValue stringValue];
914
+ }
915
+
916
+ @end
@@ -22,6 +22,14 @@ extern NSString *FB_XCAXAIsElementAttributeName;
22
22
  /*! Accessibility identifier for visible frame attribute */
23
23
  extern NSString *FB_XCAXAVisibleFrameAttributeName;
24
24
 
25
+ /*! Accessibility identifier для минимума */
26
+ extern NSNumber *FB_XCAXACustomMinValueAttribute;
27
+ extern NSString *FB_XCAXACustomMinValueAttributeName;
28
+
29
+ /*! Accessibility identifier для максимума */
30
+ extern NSNumber *FB_XCAXACustomMaxValueAttribute;
31
+ extern NSString *FB_XCAXACustomMaxValueAttributeName;
32
+
25
33
  /*! Getter for XCTest logger */
26
34
  extern id<XCDebugLogDelegate> (*XCDebugLogger)(void);
27
35
 
@@ -19,6 +19,10 @@ NSString *FB_XCAXAIsVisibleAttributeName = @"XC_kAXXCAttributeIsVisible";
19
19
  NSNumber *FB_XCAXAIsElementAttribute;
20
20
  NSString *FB_XCAXAIsElementAttributeName = @"XC_kAXXCAttributeIsElement";
21
21
  NSString *FB_XCAXAVisibleFrameAttributeName = @"XC_kAXXCAttributeVisibleFrame";
22
+ NSNumber *FB_XCAXACustomMinValueAttribute;
23
+ NSString *FB_XCAXACustomMinValueAttributeName = @"XC_kAXXCAttributeMinValue";
24
+ NSNumber *FB_XCAXACustomMaxValueAttribute;
25
+ NSString *FB_XCAXACustomMaxValueAttributeName = @"XC_kAXXCAttributeMaxValue";
22
26
 
23
27
  void (*XCSetDebugLogger)(id <XCDebugLogDelegate>);
24
28
  id<XCDebugLogDelegate> (*XCDebugLogger)(void);
@@ -42,6 +46,16 @@ __attribute__((constructor)) void FBLoadXCTestSymbols(void)
42
46
 
43
47
  NSCAssert(FB_XCAXAIsVisibleAttribute != nil , @"Failed to retrieve FB_XCAXAIsVisibleAttribute", FB_XCAXAIsVisibleAttribute);
44
48
  NSCAssert(FB_XCAXAIsElementAttribute != nil , @"Failed to retrieve FB_XCAXAIsElementAttribute", FB_XCAXAIsElementAttribute);
49
+
50
+ NSString *XC_kAXXCAttributeMinValue = *(NSString *__autoreleasing *)FBRetrieveXCTestSymbol([FB_XCAXACustomMinValueAttributeName UTF8String]);
51
+ NSString *XC_kAXXCAttributeMaxValue = *(NSString *__autoreleasing *)FBRetrieveXCTestSymbol([FB_XCAXACustomMaxValueAttributeName UTF8String]);
52
+
53
+ NSArray<NSNumber *> *minMaxAttrs = XCAXAccessibilityAttributesForStringAttributes(@[XC_kAXXCAttributeMinValue, XC_kAXXCAttributeMaxValue]);
54
+ FB_XCAXACustomMinValueAttribute = minMaxAttrs[0];
55
+ FB_XCAXACustomMaxValueAttribute = minMaxAttrs[1];
56
+
57
+ NSCAssert(FB_XCAXACustomMinValueAttribute != nil, @"Failed to retrieve FB_XCAXACustomMinValueAttribute", FB_XCAXACustomMinValueAttribute);
58
+ NSCAssert(FB_XCAXACustomMaxValueAttribute != nil, @"Failed to retrieve FB_XCAXACustomMaxValueAttribute", FB_XCAXACustomMaxValueAttribute);
45
59
  }
46
60
 
47
61
  void *FBRetrieveXCTestSymbol(const char *name)
@@ -74,7 +88,9 @@ NSArray<NSString*> *FBCustomAttributeNames(void)
74
88
  dispatch_once(&onceCustomAttributeNamesToken, ^{
75
89
  customNames = @[
76
90
  FB_XCAXAIsVisibleAttributeName,
77
- FB_XCAXAIsElementAttributeName
91
+ FB_XCAXAIsElementAttributeName,
92
+ FB_XCAXACustomMinValueAttributeName,
93
+ FB_XCAXACustomMaxValueAttributeName
78
94
  ];
79
95
  });
80
96
  return customNames;
@@ -180,8 +180,18 @@
180
180
  XCTAssertNil(element.wdName);
181
181
  XCTAssertNil(element.wdLabel);
182
182
  XCTAssertTrue([element.wdValue containsString:@"50"]);
183
+
184
+ NSNumber *minValue = element.wdMinValue;
185
+ NSNumber *maxValue = element.wdMaxValue;
186
+
187
+ XCTAssertNotNil(minValue, @"Slider minValue should not be nil");
188
+ XCTAssertNotNil(maxValue, @"Slider maxValue should not be nil");
189
+
190
+ XCTAssertEqualObjects(minValue, @0);
191
+ XCTAssertEqualObjects(maxValue, @1);
183
192
  }
184
193
 
194
+
185
195
  - (void)testActivityIndicatorAttributes
186
196
  {
187
197
  XCUIElement *element = self.testedApplication.activityIndicators.element;
@@ -64,8 +64,8 @@
64
64
  xpathQuery:nil
65
65
  excludingAttributes:nil];
66
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];
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\" 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.wdTraits];
69
69
  XCTAssertTrue([resultXml isEqualToString: expectedXml]);
70
70
  }
71
71
 
@@ -75,9 +75,9 @@
75
75
  id<FBElement> element = (id<FBElement>)[FBXCElementSnapshotWrapper ensureWrapped:(id)snapshot];
76
76
  NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
77
77
  xpathQuery:nil
78
- excludingAttributes:@[@"type", @"visible", @"value", @"index", @"traits"]];
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",
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];
78
+ excludingAttributes:@[@"type", @"visible", @"value", @"index", @"traits", @"nativeFrame"]];
79
+ NSString *expectedXml = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%@ name=\"%@\" label=\"%@\" enabled=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" private_indexPath=\"top\"/>\n",
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"]];
81
81
  XCTAssertEqualObjects(resultXml, expectedXml);
82
82
  }
83
83
 
@@ -90,8 +90,8 @@
90
90
  NSString *resultXml = [self xmlStringWithElement:(id<FBXCElementSnapshot>)element
91
91
  xpathQuery:[NSString stringWithFormat:@"//%@[@*]", element.wdType]
92
92
  excludingAttributes:@[@"visible"]];
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];
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=\"%@\" traits=\"%@\" nativeFrame=\"%@\" 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.wdTraits, NSStringFromCGRect(element.wdNativeFrame)];
95
95
  XCTAssertEqualObjects(expectedXml, resultXml);
96
96
  }
97
97
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "9.12.0",
3
+ "version": "9.14.0",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",