appium-webdriveragent 4.7.0 → 4.8.2

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 +3 -3
  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.m +73 -51
  35. package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +11 -10
  36. package/WebDriverAgentLib/Categories/XCUIElement+FBUID.h +10 -5
  37. package/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +15 -3
  38. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +7 -7
  39. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +29 -20
  40. package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h +2 -2
  41. package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +17 -14
  42. package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h +2 -3
  43. package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m +3 -3
  44. package/WebDriverAgentLib/Commands/FBElementCommands.m +17 -15
  45. package/WebDriverAgentLib/Commands/FBFindElementCommands.m +5 -6
  46. package/WebDriverAgentLib/FBAlert.m +16 -13
  47. package/WebDriverAgentLib/FBApplication.m +8 -8
  48. package/WebDriverAgentLib/Routing/FBElementUtils.h +11 -2
  49. package/WebDriverAgentLib/Routing/FBElementUtils.m +15 -12
  50. package/WebDriverAgentLib/Routing/FBResponsePayload.m +11 -10
  51. package/WebDriverAgentLib/Routing/FBSession.m +1 -1
  52. package/{PrivateHeaders/XCTest/XCAccessibilityElement.h → WebDriverAgentLib/Routing/FBXCAccessibilityElement.h} +19 -18
  53. package/WebDriverAgentLib/{Categories/XCAccessibilityElement+FBComparison.m → Routing/FBXCAccessibilityElement.m} +5 -11
  54. package/WebDriverAgentLib/Routing/FBXCDeviceEvent.h +35 -0
  55. package/WebDriverAgentLib/Routing/FBXCDeviceEvent.m +43 -0
  56. package/{PrivateHeaders/XCTest/XCElementSnapshot.h → WebDriverAgentLib/Routing/FBXCElementSnapshot.h} +25 -44
  57. package/WebDriverAgentLib/Routing/FBXCElementSnapshot.m +10 -0
  58. package/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h +30 -0
  59. package/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m +45 -0
  60. package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h +3 -4
  61. package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m +4 -4
  62. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +2 -2
  63. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +7 -8
  64. package/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m +1 -2
  65. package/WebDriverAgentLib/Utilities/FBConfiguration.m +0 -1
  66. package/WebDriverAgentLib/Utilities/FBImageIOScaler.m +3 -0
  67. package/WebDriverAgentLib/Utilities/FBKeyboard.m +1 -2
  68. package/WebDriverAgentLib/Utilities/FBPasteboard.m +91 -3
  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/FBPasteboardTests.m +1 -5
  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
@@ -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"
@@ -105,7 +104,7 @@
105
104
  {
106
105
  FBElementCache *elementCache = request.session.elementCache;
107
106
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
108
- BOOL isEnabled = element.lastSnapshot.isWDEnabled;
107
+ BOOL isEnabled = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDEnabled;
109
108
  return FBResponseWithObject(isEnabled ? @YES : @NO);
110
109
  }
111
110
 
@@ -113,7 +112,7 @@
113
112
  {
114
113
  FBElementCache *elementCache = request.session.elementCache;
115
114
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
116
- return FBResponseWithObject(element.lastSnapshot.wdRect);
115
+ return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdRect);
117
116
  }
118
117
 
119
118
  + (id<FBResponsePayload>)handleGetAttribute:(FBRouteRequest *)request
@@ -135,7 +134,8 @@
135
134
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
136
135
  resolveForAdditionalAttributes:additionalAttributes
137
136
  andMaxDepth:maxDepth];
138
- id attributeValue = [element.lastSnapshot fb_valueForWDAttributeName:attributeName];
137
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot];
138
+ id attributeValue = [wrappedSnapshot fb_valueForWDAttributeName:attributeName];
139
139
  return FBResponseWithObject(attributeValue ?: [NSNull null]);
140
140
  }
141
141
 
@@ -143,7 +143,8 @@
143
143
  {
144
144
  FBElementCache *elementCache = request.session.elementCache;
145
145
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
146
- id text = FBFirstNonEmptyValue(element.lastSnapshot.wdValue, element.lastSnapshot.wdLabel);
146
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot];
147
+ id text = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel);
147
148
  return FBResponseWithObject(text ?: @"");
148
149
  }
149
150
 
@@ -153,7 +154,7 @@
153
154
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
154
155
  resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName]
155
156
  andMaxDepth:@1];
156
- return FBResponseWithObject(@(element.lastSnapshot.isWDVisible));
157
+ return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDVisible));
157
158
  }
158
159
 
159
160
  + (id<FBResponsePayload>)handleGetAccessible:(FBRouteRequest *)request
@@ -162,7 +163,7 @@
162
163
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
163
164
  resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName]
164
165
  andMaxDepth:@1];
165
- return FBResponseWithObject(@(element.lastSnapshot.isWDAccessible));
166
+ return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessible));
166
167
  }
167
168
 
168
169
  + (id<FBResponsePayload>)handleGetIsAccessibilityContainer:(FBRouteRequest *)request
@@ -171,21 +172,21 @@
171
172
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
172
173
  resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName]
173
174
  andMaxDepth:nil];
174
- return FBResponseWithObject(@(element.lastSnapshot.isWDAccessibilityContainer));
175
+ return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessibilityContainer));
175
176
  }
176
177
 
177
178
  + (id<FBResponsePayload>)handleGetName:(FBRouteRequest *)request
178
179
  {
179
180
  FBElementCache *elementCache = request.session.elementCache;
180
181
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
181
- return FBResponseWithObject(element.lastSnapshot.wdType);
182
+ return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdType);
182
183
  }
183
184
 
184
185
  + (id<FBResponsePayload>)handleGetSelected:(FBRouteRequest *)request
185
186
  {
186
187
  FBElementCache *elementCache = request.session.elementCache;
187
188
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
188
- return FBResponseWithObject(@(element.lastSnapshot.wdSelected));
189
+ return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdSelected));
189
190
  }
190
191
 
191
192
  + (id<FBResponsePayload>)handleSetValue:(FBRouteRequest *)request
@@ -199,7 +200,7 @@
199
200
  NSString *textToType = [value isKindOfClass:NSArray.class]
200
201
  ? [value componentsJoinedByString:@""]
201
202
  : value;
202
- XCUIElementType elementType = element.lastSnapshot.elementType;
203
+ XCUIElementType elementType = [(id<FBXCElementSnapshot>)element.lastSnapshot elementType];
203
204
  #if !TARGET_OS_TV
204
205
  if (elementType == XCUIElementTypePickerWheel) {
205
206
  [element adjustToPickerWheelValue:textToType];
@@ -370,7 +371,8 @@
370
371
 
371
372
  NSString *const predicateString = request.arguments[@"predicateString"];
372
373
  if (predicateString) {
373
- NSPredicate *formattedPredicate = [NSPredicate fb_formatSearchPredicate:[FBPredicate predicateWithFormat:predicateString]];
374
+ NSPredicate *formattedPredicate = [NSPredicate fb_snapshotBlockPredicateWithPredicate:[NSPredicate
375
+ predicateWithFormat:predicateString]];
374
376
  XCUIElement *childElement = [[[[element.fb_query descendantsMatchingType:XCUIElementTypeAny] matchingPredicate:formattedPredicate] allElementsBoundByAccessibilityElement] lastObject];
375
377
  if (!childElement) {
376
378
  return FBResponseWithStatus([FBCommandStatus noSuchElementErrorWithMessage:[NSString stringWithFormat:@"'%@' predicate didn't match any elements", predicateString] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
@@ -414,7 +416,7 @@
414
416
  FBSession *session = request.session;
415
417
  FBElementCache *elementCache = session.elementCache;
416
418
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
417
- CGRect frame = element.lastSnapshot.frame;
419
+ CGRect frame = [(id<FBXCElementSnapshot>)element.lastSnapshot frame];
418
420
  CGPoint startPoint = CGPointMake((CGFloat)(frame.origin.x + [request.arguments[@"fromX"] doubleValue]), (CGFloat)(frame.origin.y + [request.arguments[@"fromY"] doubleValue]));
419
421
  CGPoint endPoint = CGPointMake((CGFloat)(frame.origin.x + [request.arguments[@"toX"] doubleValue]), (CGFloat)(frame.origin.y + [request.arguments[@"toY"] doubleValue]));
420
422
  NSTimeInterval duration = [request.arguments[@"duration"] doubleValue];
@@ -564,7 +566,7 @@ static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
564
566
  {
565
567
  FBElementCache *elementCache = request.session.elementCache;
566
568
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
567
- if (element.lastSnapshot.elementType != XCUIElementTypePickerWheel) {
569
+ if ([element.lastSnapshot elementType] != XCUIElementTypePickerWheel) {
568
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]]);
569
571
  }
570
572
  NSString* order = [request.arguments[@"order"] lowercaseString];
@@ -634,7 +636,7 @@ static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
634
636
  XCUIElement *window = application.windows.fb_firstMatch;
635
637
  if (window) {
636
638
  element = window;
637
- XCElementSnapshot *snapshot = element.fb_cachedSnapshot ?: element.fb_takeSnapshot;
639
+ id<FBXCElementSnapshot> snapshot = element.fb_cachedSnapshot ?: element.fb_takeSnapshot;
638
640
  point.x -= snapshot.frame.origin.x;
639
641
  point.y -= snapshot.frame.origin.y;
640
642
  }
@@ -15,7 +15,6 @@
15
15
  #import "FBElementCache.h"
16
16
  #import "FBExceptions.h"
17
17
  #import "FBMacros.h"
18
- #import "FBPredicate.h"
19
18
  #import "FBRouteRequest.h"
20
19
  #import "FBSession.h"
21
20
  #import "XCTestPrivateSymbols.h"
@@ -84,11 +83,12 @@ static id<FBResponsePayload> FBNoSuchElementErrorResponseForRequest(FBRouteReque
84
83
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
85
84
  resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName]
86
85
  andMaxDepth:nil];
87
- NSArray<XCElementSnapshot *> *visibleCellSnapshots = [element.lastSnapshot descendantsByFilteringWithBlock:^BOOL(XCElementSnapshot *snapshot) {
88
- return snapshot.elementType == XCUIElementTypeCell && snapshot.wdVisible;
86
+ NSArray<id<FBXCElementSnapshot>> *visibleCellSnapshots = [element.lastSnapshot descendantsByFilteringWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot) {
87
+ return snapshot.elementType == XCUIElementTypeCell
88
+ && [FBXCElementSnapshotWrapper ensureWrapped:snapshot].wdVisible;
89
89
  }];
90
90
  NSArray *cells = [element fb_filterDescendantsWithSnapshots:visibleCellSnapshots
91
- selfUID:element.lastSnapshot.wdUID
91
+ selfUID:[FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdUID
92
92
  onlyChildren:NO];
93
93
  return FBResponseWithCachedElements(cells, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
94
94
  }
@@ -169,8 +169,7 @@ shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch
169
169
  return [element fb_descendantsMatchingXPathQuery:value
170
170
  shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
171
171
  } else if ([usingText isEqualToString:@"predicate string"]) {
172
- NSPredicate *predicate = [FBPredicate predicateWithFormat:value];
173
- return [element fb_descendantsMatchingPredicate:predicate
172
+ return [element fb_descendantsMatchingPredicate:[NSPredicate predicateWithFormat:value]
174
173
  shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
175
174
  } else if ([usingText isEqualToString:@"name"]
176
175
  || [usingText isEqualToString:@"id"]