appium-webdriveragent 4.6.1 → 4.8.1

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.
Files changed (101) hide show
  1. package/PrivateHeaders/XCTest/XCAXClient_iOS.h +2 -4
  2. package/PrivateHeaders/XCTest/XCActivityRecord.h +3 -3
  3. package/PrivateHeaders/XCTest/XCApplicationQuery.h +3 -3
  4. package/PrivateHeaders/XCTest/XCTElementSetTransformer-Protocol.h +2 -2
  5. package/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h +1 -1
  6. package/PrivateHeaders/XCTest/XCTestManager_IDEInterface-Protocol.h +5 -5
  7. package/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +8 -8
  8. package/PrivateHeaders/XCTest/XCUIApplication.h +2 -2
  9. package/PrivateHeaders/XCTest/XCUIApplicationImpl.h +2 -2
  10. package/PrivateHeaders/XCTest/XCUIApplicationProcess.h +3 -5
  11. package/PrivateHeaders/XCTest/XCUIElement.h +4 -4
  12. package/PrivateHeaders/XCTest/XCUIElementQuery.h +4 -4
  13. package/PrivateHeaders/XCTest/XCUIRecorderNodeFinder.h +3 -3
  14. package/PrivateHeaders/XCTest/XCUIRecorderUtilities.h +3 -3
  15. package/Scripts/build.sh +3 -6
  16. package/WebDriverAgent.xcodeproj/project.pbxproj +66 -70
  17. package/WebDriverAgentLib/Categories/{XCElementSnapshot+FBHelpers.h → FBXCElementSnapshotWrapper+Helpers.h} +18 -11
  18. package/WebDriverAgentLib/Categories/{XCElementSnapshot+FBHelpers.m → FBXCElementSnapshotWrapper+Helpers.m} +57 -39
  19. package/WebDriverAgentLib/Categories/NSExpression+FBFormat.m +8 -3
  20. package/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +8 -7
  21. package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +2 -2
  22. package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +29 -28
  23. package/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m +5 -0
  24. package/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m +0 -1
  25. package/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +8 -5
  26. package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h +2 -2
  27. package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m +5 -4
  28. package/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +3 -2
  29. package/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +22 -18
  30. package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h +2 -3
  31. package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +28 -26
  32. package/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +2 -1
  33. package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +8 -4
  34. package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.h +10 -0
  35. package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +81 -50
  36. package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +11 -10
  37. package/WebDriverAgentLib/Categories/XCUIElement+FBUID.h +10 -5
  38. package/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +15 -3
  39. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +7 -7
  40. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +29 -20
  41. package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h +2 -2
  42. package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +17 -14
  43. package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h +2 -3
  44. package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m +3 -3
  45. package/WebDriverAgentLib/Commands/FBElementCommands.m +31 -16
  46. package/WebDriverAgentLib/Commands/FBFindElementCommands.m +5 -6
  47. package/WebDriverAgentLib/FBAlert.m +16 -13
  48. package/WebDriverAgentLib/FBApplication.m +8 -8
  49. package/WebDriverAgentLib/Routing/FBElementUtils.h +11 -2
  50. package/WebDriverAgentLib/Routing/FBElementUtils.m +15 -12
  51. package/WebDriverAgentLib/Routing/FBResponsePayload.m +11 -10
  52. package/WebDriverAgentLib/Routing/FBSession.m +1 -1
  53. package/{PrivateHeaders/XCTest/XCAccessibilityElement.h → WebDriverAgentLib/Routing/FBXCAccessibilityElement.h} +19 -18
  54. package/WebDriverAgentLib/{Categories/XCAccessibilityElement+FBComparison.m → Routing/FBXCAccessibilityElement.m} +5 -11
  55. package/WebDriverAgentLib/Routing/FBXCDeviceEvent.h +35 -0
  56. package/WebDriverAgentLib/Routing/FBXCDeviceEvent.m +43 -0
  57. package/{PrivateHeaders/XCTest/XCElementSnapshot.h → WebDriverAgentLib/Routing/FBXCElementSnapshot.h} +25 -44
  58. package/WebDriverAgentLib/Routing/FBXCElementSnapshot.m +10 -0
  59. package/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h +30 -0
  60. package/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m +45 -0
  61. package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h +3 -4
  62. package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m +4 -4
  63. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +2 -2
  64. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +7 -8
  65. package/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m +1 -2
  66. package/WebDriverAgentLib/Utilities/FBConfiguration.m +0 -1
  67. package/WebDriverAgentLib/Utilities/FBImageIOScaler.m +3 -0
  68. package/WebDriverAgentLib/Utilities/FBKeyboard.m +1 -2
  69. package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +1 -1
  70. package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +3 -3
  71. package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +10 -9
  72. package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +14 -8
  73. package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +0 -1
  74. package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +6 -0
  75. package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +0 -10
  76. package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +0 -24
  77. package/WebDriverAgentLib/Utilities/FBXPath-Private.h +1 -1
  78. package/WebDriverAgentLib/Utilities/FBXPath.h +3 -3
  79. package/WebDriverAgentLib/Utilities/FBXPath.m +15 -13
  80. package/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.h +14 -1
  81. package/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m +18 -9
  82. package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +9 -3
  83. package/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m +7 -1
  84. package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +7 -1
  85. package/WebDriverAgentLib/WebDriverAgentLib.h +0 -1
  86. package/WebDriverAgentRunner-Runner.app.zip +0 -0
  87. package/WebDriverAgentTests/IntegrationTests/FBScrollingTests.m +10 -0
  88. package/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +26 -19
  89. package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m +24 -29
  90. package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m +2 -2
  91. package/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +5 -3
  92. package/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +2 -1
  93. package/{WebDriverAgentLib/Categories/XCElementSnapshot+FBHitPoint.h → WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.h} +3 -14
  94. package/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +99 -0
  95. package/WebDriverAgentTests/UnitTests/FBXPathTests.m +21 -13
  96. package/WebDriverAgentTests/UnitTests/NSPredicateFBFormatTests.m +4 -5
  97. package/package.json +1 -1
  98. package/WebDriverAgentLib/Categories/XCAccessibilityElement+FBComparison.h +0 -27
  99. package/WebDriverAgentLib/Categories/XCElementSnapshot+FBHitPoint.m +0 -29
  100. package/WebDriverAgentLib/Utilities/FBPredicate.h +0 -28
  101. package/WebDriverAgentLib/Utilities/FBPredicate.m +0 -29
@@ -13,7 +13,8 @@
13
13
  #import "FBErrorBuilder.h"
14
14
  #import "FBKeyboard.h"
15
15
  #import "NSString+FBVisualLength.h"
16
- #import "XCElementSnapshot+FBHelpers.h"
16
+ #import "FBXCElementSnapshotWrapper.h"
17
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
17
18
  #import "XCUIElement+FBCaching.h"
18
19
  #import "XCUIElement+FBTap.h"
19
20
  #import "XCUIElement+FBUtilities.h"
@@ -39,19 +40,19 @@
39
40
  @end
40
41
 
41
42
 
42
- @interface XCElementSnapshot (FBKeyboardFocus)
43
+ @interface FBXCElementSnapshotWrapper (FBKeyboardFocus)
43
44
 
44
45
  - (BOOL)fb_hasKeyboardFocus;
45
46
 
46
47
  @end
47
48
 
48
- @implementation XCElementSnapshot (FBKeyboardFocus)
49
+ @implementation FBXCElementSnapshotWrapper (FBKeyboardFocus)
49
50
 
50
51
  - (BOOL)fb_hasKeyboardFocus
51
52
  {
52
53
  // https://developer.apple.com/documentation/xctest/xcuielement/1500968-typetext?language=objc
53
54
  // > The element or a descendant must have keyboard focus; otherwise an error is raised.
54
- return self.hasKeyboardFocus || [self descendantsByFilteringWithBlock:^BOOL(XCElementSnapshot *snapshot) {
55
+ return self.hasKeyboardFocus || [self descendantsByFilteringWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot) {
55
56
  return snapshot.hasKeyboardFocus;
56
57
  }].count > 0;
57
58
  }
@@ -61,7 +62,7 @@
61
62
 
62
63
  @implementation XCUIElement (FBTyping)
63
64
 
64
- - (void)fb_prepareForTextInputWithSnapshot:(XCElementSnapshot *)snapshot
65
+ - (void)fb_prepareForTextInputWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot
65
66
  {
66
67
  if (snapshot.fb_hasKeyboardFocus) {
67
68
  return;
@@ -92,10 +93,10 @@
92
93
  frequency:(NSUInteger)frequency
93
94
  error:(NSError **)error
94
95
  {
95
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
96
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
96
97
  ? self.lastSnapshot
97
98
  : self.fb_takeSnapshot;
98
- [self fb_prepareForTextInputWithSnapshot:snapshot];
99
+ [self fb_prepareForTextInputWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot]];
99
100
  if (shouldClear && ![self fb_clearTextWithSnapshot:self.lastSnapshot
100
101
  shouldPrepareForInput:NO
101
102
  error:error]) {
@@ -106,15 +107,15 @@
106
107
 
107
108
  - (BOOL)fb_clearTextWithError:(NSError **)error
108
109
  {
109
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
110
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
110
111
  ? self.lastSnapshot
111
112
  : self.fb_takeSnapshot;
112
- return [self fb_clearTextWithSnapshot:snapshot
113
+ return [self fb_clearTextWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot]
113
114
  shouldPrepareForInput:YES
114
115
  error:error];
115
116
  }
116
117
 
117
- - (BOOL)fb_clearTextWithSnapshot:(XCElementSnapshot *)snapshot
118
+ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot
118
119
  shouldPrepareForInput:(BOOL)shouldPrepareForInput
119
120
  error:(NSError **)error
120
121
  {
@@ -7,24 +7,29 @@
7
7
  * of patent rights can be found in the PATENTS file in the same directory.
8
8
  */
9
9
 
10
- #import <WebDriverAgentLib/XCElementSnapshot.h>
11
- #import <WebDriverAgentLib/XCUIElement.h>
10
+ #import "FBXCElementSnapshotWrapper.h"
12
11
 
13
12
  NS_ASSUME_NONNULL_BEGIN
14
13
 
15
14
  @interface XCUIElement (FBUID)
16
15
 
17
- /*! Represents unique internal element identifier, which is the same for an element and its snapshot */
16
+ /*! Represents unique internal element identifier, which is the same for an element and its snapshot as UUIDv4 */
18
17
  @property (nonatomic, nullable, readonly, copy) NSString *fb_uid;
19
18
 
19
+ /*! Represents unique internal element identifier, which is the same for an element and its snapshot */
20
+ @property (nonatomic, readonly) unsigned long long fb_accessibiltyId;
21
+
20
22
  @end
21
23
 
22
24
 
23
- @interface XCElementSnapshot (FBUID)
25
+ @interface FBXCElementSnapshotWrapper (FBUID)
24
26
 
25
- /*! Represents unique internal element identifier, which is the same for an element and its snapshot */
27
+ /*! Represents unique internal element identifier, which is the same for an element and its snapshot as UUIDv4 */
26
28
  @property (nonatomic, nullable, readonly, copy) NSString *fb_uid;
27
29
 
30
+ /*! Represents unique internal element identifier, which is the same for an element and its snapshot */
31
+ @property (nonatomic, readonly) unsigned long long fb_accessibiltyId;
32
+
28
33
  @end
29
34
 
30
35
  NS_ASSUME_NONNULL_END
@@ -15,20 +15,32 @@
15
15
 
16
16
  @implementation XCUIElement (FBUID)
17
17
 
18
+ - (unsigned long long)fb_accessibiltyId
19
+ {
20
+ return [FBElementUtils idWithAccessibilityElement:([self isKindOfClass:XCUIApplication.class]
21
+ ? [(XCUIApplication *)self accessibilityElement]
22
+ : [self fb_takeSnapshot].accessibilityElement)];
23
+ }
24
+
18
25
  - (NSString *)fb_uid
19
26
  {
20
27
  return [self isKindOfClass:XCUIApplication.class]
21
28
  ? [FBElementUtils uidWithAccessibilityElement:[(XCUIApplication *)self accessibilityElement]]
22
- : [self fb_takeSnapshot].fb_uid;
29
+ : [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]].fb_uid;
23
30
  }
24
31
 
25
32
  @end
26
33
 
27
- @implementation XCElementSnapshot (FBUID)
34
+ @implementation FBXCElementSnapshotWrapper (FBUID)
35
+
36
+ - (unsigned long long)fb_accessibiltyId
37
+ {
38
+ return [FBElementUtils idWithAccessibilityElement:self.accessibilityElement];
39
+ }
28
40
 
29
41
  - (NSString *)fb_uid
30
42
  {
31
- return [FBElementUtils uidWithAccessibilityElement:self.accessibilityElement];
43
+ return [FBElementUtils uidWithAccessibilityElement:[self accessibilityElement]];
32
44
  }
33
45
 
34
46
  @end
@@ -8,8 +8,8 @@
8
8
  */
9
9
 
10
10
  #import <XCTest/XCTest.h>
11
- #import <WebDriverAgentLib/XCElementSnapshot.h>
12
11
  #import <WebDriverAgentLib/FBElement.h>
12
+ #import "FBXCElementSnapshot.h"
13
13
 
14
14
  NS_ASSUME_NONNULL_BEGIN
15
15
 
@@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
24
24
  @return The recent snapshot of the element
25
25
  @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
26
26
  */
27
- - (XCElementSnapshot *)fb_takeSnapshot;
27
+ - (id<FBXCElementSnapshot>)fb_takeSnapshot;
28
28
 
29
29
  /**
30
30
  Extracts the cached element snapshot from its query.
@@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
34
34
 
35
35
  @return Either the cached snapshot or nil
36
36
  */
37
- - (nullable XCElementSnapshot *)fb_cachedSnapshot;
37
+ - (nullable id<FBXCElementSnapshot>)fb_cachedSnapshot;
38
38
 
39
39
  /**
40
40
  Gets the most recent snapshot of the current element and already resolves the accessibility attributes
@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
50
50
  attributes resolved if there was a failure while resolving additional attributes
51
51
  @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
52
52
  */
53
- - (nullable XCElementSnapshot *)fb_snapshotWithAllAttributesAndMaxDepth:(nullable NSNumber *)maxDepth;
53
+ - (nullable id<FBXCElementSnapshot>)fb_snapshotWithAllAttributesAndMaxDepth:(nullable NSNumber *)maxDepth;
54
54
 
55
55
  /**
56
56
  Gets the most recent snapshot of the current element with given attributes resolved.
@@ -67,8 +67,8 @@ NS_ASSUME_NONNULL_BEGIN
67
67
  attributes resolved if there was a failure while resolving additional attributes
68
68
  @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
69
69
  */
70
- - (nullable XCElementSnapshot *)fb_snapshotWithAttributes:(nullable NSArray<NSString *> *)attributeNames
71
- maxDepth:(nullable NSNumber *)maxDepth;
70
+ - (nullable id<FBXCElementSnapshot>)fb_snapshotWithAttributes:(nullable NSArray<NSString *> *)attributeNames
71
+ maxDepth:(nullable NSNumber *)maxDepth;
72
72
 
73
73
  /**
74
74
  Filters elements by matching them to snapshots from the corresponding array
@@ -80,7 +80,7 @@ NS_ASSUME_NONNULL_BEGIN
80
80
 
81
81
  @return Array of filtered elements, which have matches in snapshots array
82
82
  */
83
- - (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<XCElementSnapshot *> *)snapshots
83
+ - (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<id<FBXCElementSnapshot>> *)snapshots
84
84
  selfUID:(nullable NSString *)selfUID
85
85
  onlyChildren:(BOOL)onlyChildren;
86
86
 
@@ -22,6 +22,8 @@
22
22
  #import "FBScreenshot.h"
23
23
  #import "FBXCAXClientProxy.h"
24
24
  #import "FBXCodeCompatibility.h"
25
+ #import "FBXCElementSnapshot.h"
26
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
25
27
  #import "XCUIApplication.h"
26
28
  #import "XCUIApplication+FBQuiescence.h"
27
29
  #import "XCUIApplicationImpl.h"
@@ -41,7 +43,7 @@
41
43
 
42
44
  @implementation XCUIElement (FBUtilities)
43
45
 
44
- - (XCElementSnapshot *)fb_takeSnapshot
46
+ - (id<FBXCElementSnapshot>)fb_takeSnapshot
45
47
  {
46
48
  NSError *error = nil;
47
49
  self.fb_isResolvedFromCache = @(NO);
@@ -61,12 +63,12 @@
61
63
  return self.lastSnapshot;
62
64
  }
63
65
 
64
- - (XCElementSnapshot *)fb_cachedSnapshot
66
+ - (id<FBXCElementSnapshot>)fb_cachedSnapshot
65
67
  {
66
68
  return [self.query fb_cachedSnapshot];
67
69
  }
68
70
 
69
- - (nullable XCElementSnapshot *)fb_snapshotWithAllAttributesAndMaxDepth:(NSNumber *)maxDepth
71
+ - (nullable id<FBXCElementSnapshot>)fb_snapshotWithAllAttributesAndMaxDepth:(NSNumber *)maxDepth
70
72
  {
71
73
  NSMutableArray *allNames = [NSMutableArray arrayWithArray:FBStandardAttributeNames()];
72
74
  [allNames addObjectsFromArray:FBCustomAttributeNames()];
@@ -74,11 +76,11 @@
74
76
  maxDepth:maxDepth];
75
77
  }
76
78
 
77
- - (nullable XCElementSnapshot *)fb_snapshotWithAttributes:(NSArray<NSString *> *)attributeNames
78
- maxDepth:(NSNumber *)maxDepth
79
+ - (nullable id<FBXCElementSnapshot>)fb_snapshotWithAttributes:(NSArray<NSString *> *)attributeNames
80
+ maxDepth:(NSNumber *)maxDepth
79
81
  {
80
82
  NSSet<NSString *> *standardAttributes = [NSSet setWithArray:FBStandardAttributeNames()];
81
- XCElementSnapshot *snapshot = self.fb_takeSnapshot;
83
+ id<FBXCElementSnapshot> snapshot = self.fb_takeSnapshot;
82
84
  NSTimeInterval axTimeout = FBConfiguration.customSnapshotTimeout;
83
85
  if (nil == attributeNames
84
86
  || [[NSSet setWithArray:attributeNames] isSubsetOfSet:standardAttributes]
@@ -87,7 +89,7 @@
87
89
  return snapshot;
88
90
  }
89
91
 
90
- XCAccessibilityElement *axElement = snapshot.accessibilityElement;
92
+ id<FBXCAccessibilityElement> axElement = snapshot.accessibilityElement;
91
93
  if (nil == axElement) {
92
94
  return nil;
93
95
  }
@@ -101,16 +103,17 @@
101
103
  }
102
104
 
103
105
  NSError *error;
104
- XCElementSnapshot *snapshotWithAttributes = [FBXCAXClientProxy.sharedClient snapshotForElement:axElement
105
- attributes:attributeNames
106
- maxDepth:maxDepth
107
- error:&error];
106
+ id<FBXCElementSnapshot> snapshotWithAttributes = [FBXCAXClientProxy.sharedClient snapshotForElement:axElement
107
+ attributes:attributeNames
108
+ maxDepth:maxDepth
109
+ error:&error];
108
110
  if (nil == snapshotWithAttributes) {
111
+ NSString *description = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_description;
109
112
  [FBLogger logFmt:@"Cannot take a snapshot with attribute(s) %@ of '%@' after %.2f seconds",
110
- attributeNames, snapshot.fb_description, axTimeout];
113
+ attributeNames, description, axTimeout];
111
114
  [FBLogger logFmt:@"This timeout could be customized via '%@' setting", FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT];
112
115
  [FBLogger logFmt:@"Internal error: %@", error.localizedDescription];
113
- [FBLogger logFmt:@"Falling back to the default snapshotting mechanism for the element '%@' (some attribute values, like visibility or accessibility might not be precise though)", snapshot.fb_description];
116
+ [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];
114
117
  snapshotWithAttributes = self.lastSnapshot;
115
118
  } else {
116
119
  self.lastSnapshot = snapshotWithAttributes;
@@ -122,19 +125,22 @@
122
125
  return snapshotWithAttributes;
123
126
  }
124
127
 
125
- - (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<XCElementSnapshot *> *)snapshots
128
+ - (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<id<FBXCElementSnapshot>> *)snapshots
126
129
  selfUID:(NSString *)selfUID
127
130
  onlyChildren:(BOOL)onlyChildren
128
131
  {
129
132
  if (0 == snapshots.count) {
130
133
  return @[];
131
134
  }
132
- NSArray<NSString *> *sortedIds = [snapshots valueForKey:FBStringify(XCUIElement, wdUID)];
135
+ NSMutableArray<NSString *> *sortedIds = [NSMutableArray new];
136
+ for (id<FBXCElementSnapshot> snapshot in snapshots) {
137
+ [sortedIds addObject:(NSString *)[FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_uid];
138
+ }
133
139
  NSMutableArray<XCUIElement *> *matchedElements = [NSMutableArray array];
134
140
  NSString *uid = selfUID;
135
141
  if (nil == uid) {
136
142
  uid = self.fb_isResolvedFromCache.boolValue
137
- ? self.lastSnapshot.fb_uid
143
+ ? [FBXCElementSnapshotWrapper ensureWrapped:self.lastSnapshot].fb_uid
138
144
  : self.fb_uid;
139
145
  }
140
146
  if ([sortedIds containsObject:uid]) {
@@ -151,7 +157,10 @@
151
157
  XCUIElementQuery *query = onlyChildren
152
158
  ? [self.fb_query childrenMatchingType:type]
153
159
  : [self.fb_query descendantsMatchingType:type];
154
- query = [query matchingPredicate:[NSPredicate predicateWithFormat:@"%K IN %@", FBStringify(XCUIElement, wdUID), sortedIds]];
160
+ NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot, NSDictionary *bindings) {
161
+ return [sortedIds containsObject:(NSString *)[FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_uid];
162
+ }];
163
+ query = [query matchingPredicate:predicate];
155
164
  if (1 == snapshots.count) {
156
165
  XCUIElement *result = query.fb_firstMatch;
157
166
  result.fb_isResolvedNatively = @NO;
@@ -206,7 +215,7 @@
206
215
 
207
216
  - (NSData *)fb_screenshotWithError:(NSError **)error
208
217
  {
209
- XCElementSnapshot *selfSnapshot = self.fb_isResolvedFromCache.boolValue
218
+ id<FBXCElementSnapshot> selfSnapshot = self.fb_isResolvedFromCache.boolValue
210
219
  ? self.lastSnapshot
211
220
  : self.fb_takeSnapshot;
212
221
  if (CGRectIsEmpty(selfSnapshot.frame)) {
@@ -221,8 +230,8 @@
221
230
  UIInterfaceOrientation orientation = self.application.interfaceOrientation;
222
231
  if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
223
232
  // Workaround XCTest bug when element frame is returned as in portrait mode even if the screenshot is rotated
224
- NSArray<XCElementSnapshot *> *ancestors = selfSnapshot.fb_ancestors;
225
- XCElementSnapshot *parentWindow = nil;
233
+ NSArray<id<FBXCElementSnapshot>> *ancestors = [FBXCElementSnapshotWrapper ensureWrapped:selfSnapshot].fb_ancestors;
234
+ id<FBXCElementSnapshot> parentWindow = nil;
226
235
  if (1 == ancestors.count) {
227
236
  parentWindow = selfSnapshot;
228
237
  } else if (ancestors.count > 1) {
@@ -8,8 +8,8 @@
8
8
  */
9
9
 
10
10
  #import <WebDriverAgentLib/FBElement.h>
11
- #import <WebDriverAgentLib/XCElementSnapshot.h>
12
11
  #import <WebDriverAgentLib/XCUIElement.h>
12
+ #import "FBXCElementSnapshotWrapper.h"
13
13
 
14
14
  NS_ASSUME_NONNULL_BEGIN
15
15
 
@@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
18
18
  @end
19
19
 
20
20
 
21
- @interface XCElementSnapshot (WebDriverAttributes) <FBElement>
21
+ @interface FBXCElementSnapshotWrapper (WebDriverAttributes) <FBElement>
22
22
 
23
23
  @end
24
24
 
@@ -14,6 +14,7 @@
14
14
  #import "FBElementTypeTransformer.h"
15
15
  #import "FBLogger.h"
16
16
  #import "FBMacros.h"
17
+ #import "FBXCElementSnapshotWrapper.h"
17
18
  #import "XCUIElement+FBAccessibility.h"
18
19
  #import "XCUIElement+FBIsVisible.h"
19
20
  #import "XCUIElement+FBUID.h"
@@ -26,9 +27,9 @@
26
27
 
27
28
  @implementation XCUIElement (WebDriverAttributesForwarding)
28
29
 
29
- - (XCElementSnapshot *)fb_snapshotForAttributeName:(NSString *)name
30
+ - (id<FBXCElementSnapshot>)fb_snapshotForAttributeName:(NSString *)name
30
31
  {
31
- // These attrbiutes are special, because we can only retrieve them from
32
+ // These attributes are special, because we can only retrieve them from
32
33
  // the snapshot if we explicitly ask XCTest to include them into the query while taking it.
33
34
  // That is why fb_snapshotWithAllAttributes method must be used instead of the default snapshot
34
35
  // call
@@ -51,8 +52,8 @@
51
52
  - (id)fb_valueForWDAttributeName:(NSString *)name
52
53
  {
53
54
  NSString *wdAttributeName = [FBElementUtils wdAttributeNameForAttributeName:name];
54
- XCElementSnapshot *snapshot = [self fb_snapshotForAttributeName:wdAttributeName];
55
- return [snapshot fb_valueForWDAttributeName:name];
55
+ id<FBXCElementSnapshot> snapshot = [self fb_snapshotForAttributeName:wdAttributeName];
56
+ return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_valueForWDAttributeName:name];
56
57
  }
57
58
 
58
59
  - (id)forwardingTargetForSelector:(SEL)aSelector
@@ -61,13 +62,13 @@
61
62
  SEL webDriverAttributesSelector = descr.name;
62
63
  return nil == webDriverAttributesSelector
63
64
  ? nil
64
- : [self fb_snapshotForAttributeName:NSStringFromSelector(webDriverAttributesSelector)];
65
+ : [FBXCElementSnapshotWrapper ensureWrapped:[self fb_snapshotForAttributeName:NSStringFromSelector(webDriverAttributesSelector)]];
65
66
  }
66
67
 
67
68
  @end
68
69
 
69
70
 
70
- @implementation XCElementSnapshot (WebDriverAttributes)
71
+ @implementation FBXCElementSnapshotWrapper (WebDriverAttributes)
71
72
 
72
73
  - (id)fb_valueForWDAttributeName:(NSString *)name
73
74
  {
@@ -161,8 +162,8 @@
161
162
  // Text fields: actual accessible element isn't text field itself, but nested element
162
163
  if (elementType == XCUIElementTypeCell) {
163
164
  if (!self.fb_isAccessibilityElement) {
164
- XCElementSnapshot *containerView = [[self children] firstObject];
165
- if (!containerView.fb_isAccessibilityElement) {
165
+ id<FBXCElementSnapshot> containerView = [[self children] firstObject];
166
+ if (![FBXCElementSnapshotWrapper ensureWrapped:containerView].fb_isAccessibilityElement) {
166
167
  return NO;
167
168
  }
168
169
  }
@@ -171,12 +172,13 @@
171
172
  return NO;
172
173
  }
173
174
  }
174
- XCElementSnapshot *parentSnapshot = self.parent;
175
+ id<FBXCElementSnapshot> parentSnapshot = self.parent;
175
176
  while (parentSnapshot) {
176
177
  // In the scenario when table provides Search results controller, table could be marked as accessible element, even though it isn't
177
178
  // As it is highly unlikely that table view should ever be an accessibility element itself,
178
179
  // for now we work around that by skipping Table View in container checks
179
- if (parentSnapshot.fb_isAccessibilityElement && parentSnapshot.elementType != XCUIElementTypeTable) {
180
+ if ([FBXCElementSnapshotWrapper ensureWrapped:parentSnapshot].fb_isAccessibilityElement
181
+ && parentSnapshot.elementType != XCUIElementTypeTable) {
180
182
  return NO;
181
183
  }
182
184
  parentSnapshot = parentSnapshot.parent;
@@ -186,9 +188,10 @@
186
188
 
187
189
  - (BOOL)isWDAccessibilityContainer
188
190
  {
189
- NSArray<XCElementSnapshot *> *children = self.children;
190
- for (XCElementSnapshot *child in children) {
191
- if (child.isWDAccessibilityContainer || child.fb_isAccessibilityElement) {
191
+ NSArray<id<FBXCElementSnapshot>> *children = self.children;
192
+ for (id<FBXCElementSnapshot> child in children) {
193
+ FBXCElementSnapshotWrapper *wrappedChild = [FBXCElementSnapshotWrapper ensureWrapped:child];
194
+ if (wrappedChild.isWDAccessibilityContainer || wrappedChild.fb_isAccessibilityElement) {
192
195
  return YES;
193
196
  }
194
197
  }
@@ -209,7 +212,7 @@
209
212
  {
210
213
  if (nil != self.parent) {
211
214
  for (NSUInteger index = 0; index < self.parent.children.count; ++index) {
212
- if ([self.parent.children objectAtIndex:index] == self) {
215
+ if ([self.parent.children objectAtIndex:index] == self.snapshot) {
213
216
  return index;
214
217
  }
215
218
  }
@@ -8,8 +8,7 @@
8
8
  */
9
9
 
10
10
  #import <XCTest/XCTest.h>
11
-
12
- @class XCElementSnapshot;
11
+ #import "FBXCElementSnapshot.h"
13
12
 
14
13
  NS_ASSUME_NONNULL_BEGIN
15
14
 
@@ -23,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
23
22
 
24
23
  @return Either the cached snapshot or nil
25
24
  */
26
- - (nullable XCElementSnapshot *)fb_cachedSnapshot;
25
+ - (nullable id<FBXCElementSnapshot>)fb_cachedSnapshot;
27
26
 
28
27
  @end
29
28
 
@@ -11,13 +11,13 @@
11
11
 
12
12
  #import "FBXCodeCompatibility.h"
13
13
  #import "XCUIElementQuery.h"
14
-
14
+ #import "FBXCElementSnapshot.h"
15
15
 
16
16
  @implementation XCUIElementQuery (FBHelpers)
17
17
 
18
- - (nullable XCElementSnapshot *)fb_cachedSnapshot
18
+ - (nullable id<FBXCElementSnapshot>)fb_cachedSnapshot
19
19
  {
20
- XCElementSnapshot *rootElementSnapshot = self.rootElementSnapshot;
20
+ id<FBXCElementSnapshot> rootElementSnapshot = self.rootElementSnapshot;
21
21
  if (nil == rootElementSnapshot) {
22
22
  return nil;
23
23
  }
@@ -12,7 +12,6 @@
12
12
  #import "FBApplication.h"
13
13
  #import "FBConfiguration.h"
14
14
  #import "FBKeyboard.h"
15
- #import "FBPredicate.h"
16
15
  #import "FBRoute.h"
17
16
  #import "FBRouteRequest.h"
18
17
  #import "FBRunLoopSpinner.h"
@@ -84,6 +83,7 @@
84
83
  [[FBRoute POST:@"/wda/element/:uuid/tapWithNumberOfTaps"] respondWithTarget:self action:@selector(handleTapWithNumberOfTaps:)],
85
84
  [[FBRoute POST:@"/wda/element/:uuid/touchAndHold"] respondWithTarget:self action:@selector(handleTouchAndHold:)],
86
85
  [[FBRoute POST:@"/wda/element/:uuid/scroll"] respondWithTarget:self action:@selector(handleScroll:)],
86
+ [[FBRoute POST:@"/wda/element/:uuid/scrollTo"] respondWithTarget:self action:@selector(handleScrollTo:)],
87
87
  [[FBRoute POST:@"/wda/element/:uuid/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDrag:)],
88
88
  [[FBRoute POST:@"/wda/element/:uuid/forceTouch"] respondWithTarget:self action:@selector(handleForceTouch:)],
89
89
  [[FBRoute POST:@"/wda/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDragCoordinate:)],
@@ -104,7 +104,7 @@
104
104
  {
105
105
  FBElementCache *elementCache = request.session.elementCache;
106
106
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
107
- BOOL isEnabled = element.lastSnapshot.isWDEnabled;
107
+ BOOL isEnabled = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDEnabled;
108
108
  return FBResponseWithObject(isEnabled ? @YES : @NO);
109
109
  }
110
110
 
@@ -112,7 +112,7 @@
112
112
  {
113
113
  FBElementCache *elementCache = request.session.elementCache;
114
114
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
115
- return FBResponseWithObject(element.lastSnapshot.wdRect);
115
+ return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdRect);
116
116
  }
117
117
 
118
118
  + (id<FBResponsePayload>)handleGetAttribute:(FBRouteRequest *)request
@@ -134,7 +134,8 @@
134
134
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
135
135
  resolveForAdditionalAttributes:additionalAttributes
136
136
  andMaxDepth:maxDepth];
137
- id attributeValue = [element.lastSnapshot fb_valueForWDAttributeName:attributeName];
137
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot];
138
+ id attributeValue = [wrappedSnapshot fb_valueForWDAttributeName:attributeName];
138
139
  return FBResponseWithObject(attributeValue ?: [NSNull null]);
139
140
  }
140
141
 
@@ -142,7 +143,8 @@
142
143
  {
143
144
  FBElementCache *elementCache = request.session.elementCache;
144
145
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
145
- id text = FBFirstNonEmptyValue(element.lastSnapshot.wdValue, element.lastSnapshot.wdLabel);
146
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot];
147
+ id text = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel);
146
148
  return FBResponseWithObject(text ?: @"");
147
149
  }
148
150
 
@@ -152,7 +154,7 @@
152
154
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
153
155
  resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName]
154
156
  andMaxDepth:@1];
155
- return FBResponseWithObject(@(element.lastSnapshot.isWDVisible));
157
+ return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDVisible));
156
158
  }
157
159
 
158
160
  + (id<FBResponsePayload>)handleGetAccessible:(FBRouteRequest *)request
@@ -161,7 +163,7 @@
161
163
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
162
164
  resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName]
163
165
  andMaxDepth:@1];
164
- return FBResponseWithObject(@(element.lastSnapshot.isWDAccessible));
166
+ return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessible));
165
167
  }
166
168
 
167
169
  + (id<FBResponsePayload>)handleGetIsAccessibilityContainer:(FBRouteRequest *)request
@@ -170,21 +172,21 @@
170
172
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
171
173
  resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName]
172
174
  andMaxDepth:nil];
173
- return FBResponseWithObject(@(element.lastSnapshot.isWDAccessibilityContainer));
175
+ return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessibilityContainer));
174
176
  }
175
177
 
176
178
  + (id<FBResponsePayload>)handleGetName:(FBRouteRequest *)request
177
179
  {
178
180
  FBElementCache *elementCache = request.session.elementCache;
179
181
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
180
- return FBResponseWithObject(element.lastSnapshot.wdType);
182
+ return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdType);
181
183
  }
182
184
 
183
185
  + (id<FBResponsePayload>)handleGetSelected:(FBRouteRequest *)request
184
186
  {
185
187
  FBElementCache *elementCache = request.session.elementCache;
186
188
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
187
- return FBResponseWithObject(@(element.lastSnapshot.wdSelected));
189
+ return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdSelected));
188
190
  }
189
191
 
190
192
  + (id<FBResponsePayload>)handleSetValue:(FBRouteRequest *)request
@@ -198,7 +200,7 @@
198
200
  NSString *textToType = [value isKindOfClass:NSArray.class]
199
201
  ? [value componentsJoinedByString:@""]
200
202
  : value;
201
- XCUIElementType elementType = element.lastSnapshot.elementType;
203
+ XCUIElementType elementType = [(id<FBXCElementSnapshot>)element.lastSnapshot elementType];
202
204
  #if !TARGET_OS_TV
203
205
  if (elementType == XCUIElementTypePickerWheel) {
204
206
  [element adjustToPickerWheelValue:textToType];
@@ -369,7 +371,8 @@
369
371
 
370
372
  NSString *const predicateString = request.arguments[@"predicateString"];
371
373
  if (predicateString) {
372
- NSPredicate *formattedPredicate = [NSPredicate fb_formatSearchPredicate:[FBPredicate predicateWithFormat:predicateString]];
374
+ NSPredicate *formattedPredicate = [NSPredicate fb_snapshotBlockPredicateWithPredicate:[NSPredicate
375
+ predicateWithFormat:predicateString]];
373
376
  XCUIElement *childElement = [[[[element.fb_query descendantsMatchingType:XCUIElementTypeAny] matchingPredicate:formattedPredicate] allElementsBoundByAccessibilityElement] lastObject];
374
377
  if (!childElement) {
375
378
  return FBResponseWithStatus([FBCommandStatus noSuchElementErrorWithMessage:[NSString stringWithFormat:@"'%@' predicate didn't match any elements", predicateString] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
@@ -383,6 +386,17 @@
383
386
  return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"Unsupported scroll type" traceback:nil]);
384
387
  }
385
388
 
389
+ + (id<FBResponsePayload>)handleScrollTo:(FBRouteRequest *)request
390
+ {
391
+ FBElementCache *elementCache = request.session.elementCache;
392
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
393
+ NSError *error;
394
+ return [element fb_nativeScrollToVisibleWithError:&error]
395
+ ? FBResponseWithOK()
396
+ : FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description
397
+ traceback:nil]);
398
+ }
399
+
386
400
  + (id<FBResponsePayload>)handleDragCoordinate:(FBRouteRequest *)request
387
401
  {
388
402
  FBSession *session = request.session;
@@ -402,7 +416,7 @@
402
416
  FBSession *session = request.session;
403
417
  FBElementCache *elementCache = session.elementCache;
404
418
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
405
- CGRect frame = element.lastSnapshot.frame;
419
+ CGRect frame = [(id<FBXCElementSnapshot>)element.lastSnapshot frame];
406
420
  CGPoint startPoint = CGPointMake((CGFloat)(frame.origin.x + [request.arguments[@"fromX"] doubleValue]), (CGFloat)(frame.origin.y + [request.arguments[@"fromY"] doubleValue]));
407
421
  CGPoint endPoint = CGPointMake((CGFloat)(frame.origin.x + [request.arguments[@"toX"] doubleValue]), (CGFloat)(frame.origin.y + [request.arguments[@"toY"] doubleValue]));
408
422
  NSTimeInterval duration = [request.arguments[@"duration"] doubleValue];
@@ -537,7 +551,8 @@
537
551
  NSError *error;
538
552
  NSData *screenshotData = [element fb_screenshotWithError:&error];
539
553
  if (nil == screenshotData) {
540
- return FBResponseWithStatus([FBCommandStatus unableToCaptureScreenErrorWithMessage:error.description traceback:nil]);
554
+ return FBResponseWithStatus([FBCommandStatus unableToCaptureScreenErrorWithMessage:error.description
555
+ traceback:nil]);
541
556
  }
542
557
  NSString *screenshot = [screenshotData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
543
558
  return FBResponseWithObject(screenshot);
@@ -551,7 +566,7 @@ static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
551
566
  {
552
567
  FBElementCache *elementCache = request.session.elementCache;
553
568
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
554
- if (element.lastSnapshot.elementType != XCUIElementTypePickerWheel) {
569
+ if ([element.lastSnapshot elementType] != XCUIElementTypePickerWheel) {
555
570
  return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:[NSString stringWithFormat:@"The element is expected to be a valid Picker Wheel control. '%@' was given instead", element.wdType] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
556
571
  }
557
572
  NSString* order = [request.arguments[@"order"] lowercaseString];
@@ -621,7 +636,7 @@ static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
621
636
  XCUIElement *window = application.windows.fb_firstMatch;
622
637
  if (window) {
623
638
  element = window;
624
- XCElementSnapshot *snapshot = element.fb_cachedSnapshot ?: element.fb_takeSnapshot;
639
+ id<FBXCElementSnapshot> snapshot = element.fb_cachedSnapshot ?: element.fb_takeSnapshot;
625
640
  point.x -= snapshot.frame.origin.x;
626
641
  point.y -= snapshot.frame.origin.y;
627
642
  }