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
@@ -11,6 +11,7 @@
11
11
 
12
12
  #import <objc/runtime.h>
13
13
 
14
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
14
15
  #import "XCUIElement+FBWebDriverAttributes.h"
15
16
  #import "XCUIElement+FBUtilities.h"
16
17
  #import "XCUIElement+FBUID.h"
@@ -46,8 +47,8 @@ static char XCUIELEMENT_CACHE_ID_KEY;
46
47
  if ([self isKindOfClass:XCUIApplication.class]) {
47
48
  uid = self.fb_uid;
48
49
  } else {
49
- XCElementSnapshot *snapshot = self.fb_cachedSnapshot ?: self.fb_takeSnapshot;
50
- uid = snapshot.wdUID;
50
+ id<FBXCElementSnapshot> snapshot = self.fb_cachedSnapshot ?: self.fb_takeSnapshot;
51
+ uid = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].wdUID;
51
52
  }
52
53
 
53
54
  objc_setAssociatedObject(self, &XCUIELEMENT_CACHE_ID_KEY, uid, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
@@ -12,10 +12,8 @@
12
12
 
13
13
  #import "FBMacros.h"
14
14
  #import "FBElementTypeTransformer.h"
15
- #import "FBPredicate.h"
16
15
  #import "NSPredicate+FBFormat.h"
17
- #import "XCElementSnapshot.h"
18
- #import "XCElementSnapshot+FBHelpers.h"
16
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
19
17
  #import "FBXCodeCompatibility.h"
20
18
  #import "XCUIElement+FBCaching.h"
21
19
  #import "XCUIElement+FBUtilities.h"
@@ -37,7 +35,7 @@
37
35
  return matchedElement ? @[matchedElement] : @[];
38
36
  }
39
37
 
40
- - (XCElementSnapshot *)fb_cachedSnapshotWithQuery:(XCUIElementQuery *)query
38
+ - (id<FBXCElementSnapshot>)fb_cachedSnapshotWithQuery:(XCUIElementQuery *)query
41
39
  {
42
40
  return [self isKindOfClass:XCUIApplication.class] ? query.rootElementSnapshot : self.fb_cachedSnapshot;
43
41
  }
@@ -51,7 +49,7 @@
51
49
  XCUIElementQuery *query = [self.fb_query descendantsMatchingType:type];
52
50
  NSMutableArray *result = [NSMutableArray array];
53
51
  [result addObjectsFromArray:[self.class fb_extractMatchingElementsFromQuery:query shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch]];
54
- XCElementSnapshot *cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
52
+ id<FBXCElementSnapshot> cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
55
53
  if (type == XCUIElementTypeAny || cachedSnapshot.elementType == type) {
56
54
  if (shouldReturnAfterFirstMatch || result.count == 0) {
57
55
  return @[self];
@@ -73,7 +71,9 @@
73
71
  return elements;
74
72
  }
75
73
 
76
- - (void)descendantsWithProperty:(NSString *)property value:(NSString *)value partial:(BOOL)partialSearch results:(NSMutableArray<XCUIElement *> *)results
74
+ - (void)descendantsWithProperty:(NSString *)property value:(NSString *)value
75
+ partial:(BOOL)partialSearch
76
+ results:(NSMutableArray<XCUIElement *> *)results
77
77
  {
78
78
  if (partialSearch) {
79
79
  NSString *text = [self fb_valueForWDAttributeName:property];
@@ -88,12 +88,12 @@
88
88
  }
89
89
 
90
90
  property = [FBElementUtils wdAttributeNameForAttributeName:property];
91
- value = [value stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
92
- NSString *operation = partialSearch ?
93
- [NSString stringWithFormat:@"%@ like '*%@*'", property, value] :
94
- [NSString stringWithFormat:@"%@ == '%@'", property, value];
95
-
96
- NSPredicate *predicate = [FBPredicate predicateWithFormat:operation];
91
+ NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot,
92
+ NSDictionary<NSString *,id> * _Nullable bindings) {
93
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
94
+ NSString *propertyValue = [NSString stringWithFormat:@"%@", [wrappedSnapshot fb_valueForWDAttributeName:property]];
95
+ return partialSearch ? [value containsString:propertyValue] : [value isEqualToString:propertyValue];
96
+ }];
97
97
  XCUIElementQuery *query = [[self.fb_query descendantsMatchingType:XCUIElementTypeAny] matchingPredicate:predicate];
98
98
  NSArray *childElements = query.fb_allMatches;
99
99
  [results addObjectsFromArray:childElements];
@@ -105,12 +105,12 @@
105
105
  - (NSArray<XCUIElement *> *)fb_descendantsMatchingPredicate:(NSPredicate *)predicate
106
106
  shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch
107
107
  {
108
- NSPredicate *formattedPredicate = [NSPredicate fb_formatSearchPredicate:predicate];
108
+ NSPredicate *formattedPredicate = [NSPredicate fb_snapshotBlockPredicateWithPredicate:predicate];
109
109
  XCUIElementQuery *query = [[self.fb_query descendantsMatchingType:XCUIElementTypeAny] matchingPredicate:formattedPredicate];
110
110
  NSMutableArray<XCUIElement *> *result = [NSMutableArray array];
111
111
  [result addObjectsFromArray:[self.class fb_extractMatchingElementsFromQuery:query
112
112
  shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch]];
113
- XCElementSnapshot *cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
113
+ id<FBXCElementSnapshot> cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
114
114
  // Include self element into predicate search
115
115
  if ([formattedPredicate evaluateWithObject:cachedSnapshot]) {
116
116
  if (shouldReturnAfterFirstMatch || result.count == 0) {
@@ -129,16 +129,16 @@
129
129
  {
130
130
  // XPath will try to match elements only class name, so requesting elements by XCUIElementTypeAny will not work. We should use '*' instead.
131
131
  xpathQuery = [xpathQuery stringByReplacingOccurrencesOfString:@"XCUIElementTypeAny" withString:@"*"];
132
- NSArray<XCElementSnapshot *> *matchingSnapshots = [FBXPath matchesWithRootElement:self forQuery:xpathQuery];
132
+ NSArray<id<FBXCElementSnapshot>> *matchingSnapshots = [FBXPath matchesWithRootElement:self forQuery:xpathQuery];
133
133
  if (0 == [matchingSnapshots count]) {
134
134
  return @[];
135
135
  }
136
136
  if (shouldReturnAfterFirstMatch) {
137
- XCElementSnapshot *snapshot = matchingSnapshots.firstObject;
137
+ id<FBXCElementSnapshot> snapshot = matchingSnapshots.firstObject;
138
138
  matchingSnapshots = @[snapshot];
139
139
  }
140
140
  return [self fb_filterDescendantsWithSnapshots:matchingSnapshots
141
- selfUID:self.lastSnapshot.wdUID
141
+ selfUID:[FBXCElementSnapshotWrapper ensureWrapped:self.lastSnapshot].wdUID
142
142
  onlyChildren:NO];
143
143
  }
144
144
 
@@ -148,7 +148,11 @@
148
148
  - (NSArray<XCUIElement *> *)fb_descendantsMatchingIdentifier:(NSString *)accessibilityId
149
149
  shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch
150
150
  {
151
- NSPredicate *predicate = [FBPredicate predicateWithFormat:@"name == %@", accessibilityId];
151
+ NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot,
152
+ NSDictionary<NSString *,id> * _Nullable bindings) {
153
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
154
+ return [wrappedSnapshot.wdName isEqualToString:accessibilityId];
155
+ }];
152
156
  return [self fb_descendantsMatchingPredicate:predicate
153
157
  shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
154
158
  }
@@ -7,8 +7,7 @@
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
 
@@ -20,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
20
19
  @end
21
20
 
22
21
 
23
- @interface XCElementSnapshot (FBIsVisible)
22
+ @interface FBXCElementSnapshotWrapper (FBIsVisible)
24
23
 
25
24
  /*! Whether or not the element is visible */
26
25
  @property (atomic, readonly) BOOL fb_isVisible;
@@ -14,10 +14,9 @@
14
14
  #import "FBMathUtils.h"
15
15
  #import "FBActiveAppDetectionPoint.h"
16
16
  #import "FBSession.h"
17
+ #import "FBXCAccessibilityElement.h"
17
18
  #import "FBXCodeCompatibility.h"
18
- #import "XCAccessibilityElement+FBComparison.h"
19
- #import "XCElementSnapshot+FBHelpers.h"
20
- #import "XCElementSnapshot+FBHitPoint.h"
19
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
21
20
  #import "XCUIElement+FBUtilities.h"
22
21
  #import "XCUIElement+FBUID.h"
23
22
  #import "XCTestPrivateSymbols.h"
@@ -26,13 +25,14 @@
26
25
 
27
26
  - (BOOL)fb_isVisible
28
27
  {
29
- return [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName]
30
- maxDepth:@1].fb_isVisible;
28
+ id<FBXCElementSnapshot> snapshot = [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName]
29
+ maxDepth:@1];
30
+ return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isVisible;
31
31
  }
32
32
 
33
33
  @end
34
34
 
35
- @implementation XCElementSnapshot (FBIsVisible)
35
+ @implementation FBXCElementSnapshotWrapper (FBIsVisible)
36
36
 
37
37
  - (NSString *)fb_uniqId
38
38
  {
@@ -57,7 +57,7 @@
57
57
  }
58
58
 
59
59
  - (BOOL)fb_cacheVisibilityWithValue:(BOOL)isVisible
60
- forAncestors:(nullable NSArray<XCElementSnapshot *> *)ancestors
60
+ forAncestors:(nullable NSArray<id<FBXCElementSnapshot>> *)ancestors
61
61
  {
62
62
  NSMutableDictionary *cache = FBSession.activeSession.elementsVisibilityCache;
63
63
  if (nil == cache) {
@@ -72,8 +72,8 @@
72
72
  [destination setObject:visibleObj forKey:self.fb_uniqId];
73
73
  if (isVisible && nil != ancestors) {
74
74
  // if an element is visible then all its ancestors must be visible as well
75
- for (XCElementSnapshot *ancestor in ancestors) {
76
- NSString *ancestorId = ancestor.fb_uniqId;
75
+ for (id<FBXCElementSnapshot> ancestor in ancestors) {
76
+ NSString *ancestorId = [FBXCElementSnapshotWrapper ensureWrapped:ancestor].fb_uniqId;
77
77
  if (nil == [destination objectForKey:ancestorId]) {
78
78
  [destination setObject:visibleObj forKey:ancestorId];
79
79
  }
@@ -82,17 +82,17 @@
82
82
  return isVisible;
83
83
  }
84
84
 
85
- - (CGRect)fb_frameInContainer:(XCElementSnapshot *)container
85
+ - (CGRect)fb_frameInContainer:(id<FBXCElementSnapshot>)container
86
86
  hierarchyIntersection:(nullable NSValue *)intersectionRectange
87
87
  {
88
88
  CGRect currentRectangle = nil == intersectionRectange ? self.frame : [intersectionRectange CGRectValue];
89
- XCElementSnapshot *parent = self.parent;
89
+ id<FBXCElementSnapshot> parent = self.parent;
90
90
  CGRect parentFrame = parent.frame;
91
91
  CGRect containerFrame = container.frame;
92
92
  if (CGSizeEqualToSize(parentFrame.size, CGSizeZero) &&
93
93
  CGPointEqualToPoint(parentFrame.origin, CGPointZero)) {
94
94
  // Special case (or XCTest bug). Shift the origin and return immediately after shift
95
- XCElementSnapshot *nextParent = parent.parent;
95
+ id<FBXCElementSnapshot> nextParent = parent.parent;
96
96
  BOOL isGrandparent = YES;
97
97
  while (nextParent && nextParent != container) {
98
98
  CGRect nextParentFrame = nextParent.frame;
@@ -133,18 +133,19 @@
133
133
  if (CGRectIsEmpty(intersectionWithParent) || parent == container) {
134
134
  return intersectionWithParent;
135
135
  }
136
- return [parent fb_frameInContainer:container hierarchyIntersection:[NSValue valueWithCGRect:intersectionWithParent]];
136
+ return [[FBXCElementSnapshotWrapper ensureWrapped:parent] fb_frameInContainer:container
137
+ hierarchyIntersection:[NSValue valueWithCGRect:intersectionWithParent]];
137
138
  }
138
139
 
139
140
  - (BOOL)fb_hasAnyVisibleLeafs
140
141
  {
141
- NSArray<XCElementSnapshot *> *children = self.children;
142
+ NSArray<id<FBXCElementSnapshot>> *children = self.children;
142
143
  if (0 == children.count) {
143
144
  return self.fb_isVisible;
144
145
  }
145
146
 
146
- for (XCElementSnapshot *child in children) {
147
- if (child.fb_hasAnyVisibleLeafs) {
147
+ for (id<FBXCElementSnapshot> child in children) {
148
+ if ([FBXCElementSnapshotWrapper ensureWrapped:child].fb_hasAnyVisibleLeafs) {
148
149
  return YES;
149
150
  }
150
151
  }
@@ -169,13 +170,13 @@
169
170
  return [self fb_cacheVisibilityWithValue:NO forAncestors:nil];
170
171
  }
171
172
 
172
- NSArray<XCElementSnapshot *> *ancestors = self.fb_ancestors;
173
+ NSArray<id<FBXCElementSnapshot>> *ancestors = self.fb_ancestors;
173
174
  if ([FBConfiguration shouldUseTestManagerForVisibilityDetection]) {
174
175
  BOOL visibleAttrValue = [(NSNumber *)[self fb_attributeValue:FB_XCAXAIsVisibleAttributeName] boolValue];
175
176
  return [self fb_cacheVisibilityWithValue:visibleAttrValue forAncestors:ancestors];
176
177
  }
177
178
 
178
- XCElementSnapshot *parentWindow = ancestors.count > 1 ? [ancestors objectAtIndex:ancestors.count - 2] : nil;
179
+ id<FBXCElementSnapshot> parentWindow = ancestors.count > 1 ? [ancestors objectAtIndex:ancestors.count - 2] : nil;
179
180
  CGRect visibleRect = selfFrame;
180
181
  if (nil != parentWindow) {
181
182
  visibleRect = [self fb_frameInContainer:parentWindow hierarchyIntersection:nil];
@@ -186,7 +187,7 @@
186
187
  CGPoint midPoint = CGPointMake(visibleRect.origin.x + visibleRect.size.width / 2,
187
188
  visibleRect.origin.y + visibleRect.size.height / 2);
188
189
  #if !TARGET_OS_TV // TV has no orientation, so it does not need to coordinate
189
- XCElementSnapshot *appElement = ancestors.count > 0 ? [ancestors lastObject] : self;
190
+ id<FBXCElementSnapshot> appElement = ancestors.count > 0 ? [ancestors lastObject] : self;
190
191
  CGRect appFrame = appElement.frame;
191
192
  CGRect windowFrame = nil == parentWindow ? selfFrame : parentWindow.frame;
192
193
  if ((appFrame.size.height > appFrame.size.width && windowFrame.size.height < windowFrame.size.width) ||
@@ -197,22 +198,23 @@
197
198
  midPoint = FBInvertPointForApplication(midPoint, appFrame.size, FBApplication.fb_activeApplication.interfaceOrientation);
198
199
  }
199
200
  #endif
200
- XCAccessibilityElement *hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint];
201
+ id<FBXCAccessibilityElement> hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint];
201
202
  if (nil != hitElement) {
202
- if ([self.accessibilityElement fb_isEqualToElement:hitElement]) {
203
+ if (FBIsAXElementEqualToOther(self.accessibilityElement, hitElement)) {
203
204
  return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors];
204
205
  }
205
- for (XCElementSnapshot *ancestor in ancestors) {
206
- if ([hitElement fb_isEqualToElement:ancestor.accessibilityElement]) {
206
+ for (id<FBXCElementSnapshot> ancestor in ancestors) {
207
+ if (FBIsAXElementEqualToOther(hitElement, ancestor.accessibilityElement)) {
207
208
  return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors];
208
209
  }
209
210
  }
210
211
  }
211
212
  if (self.children.count > 0) {
212
213
  if (nil != hitElement) {
213
- for (XCElementSnapshot *descendant in self._allDescendants) {
214
- if ([hitElement fb_isEqualToElement:descendant.accessibilityElement]) {
215
- return [self fb_cacheVisibilityWithValue:YES forAncestors:descendant.fb_ancestors];
214
+ for (id<FBXCElementSnapshot> descendant in self._allDescendants) {
215
+ if (FBIsAXElementEqualToOther(hitElement, descendant.accessibilityElement)) {
216
+ return [self fb_cacheVisibilityWithValue:YES
217
+ forAncestors:[FBXCElementSnapshotWrapper ensureWrapped:descendant].fb_ancestors];
216
218
  }
217
219
  }
218
220
  }
@@ -10,6 +10,7 @@
10
10
  #import "XCUIElement+FBPickerWheel.h"
11
11
 
12
12
  #import "FBRunLoopSpinner.h"
13
+ #import "FBXCElementSnapshot.h"
13
14
  #import "FBXCodeCompatibility.h"
14
15
  #import "XCUIApplication+FBTouchAction.h"
15
16
  #import "XCUICoordinate.h"
@@ -23,7 +24,7 @@ static const NSTimeInterval VALUE_CHANGE_TIMEOUT = 2;
23
24
 
24
25
  - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)error
25
26
  {
26
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
27
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
27
28
  ? self.lastSnapshot
28
29
  : self.fb_takeSnapshot;
29
30
  NSString *previousValue = snapshot.value;
@@ -41,11 +41,15 @@ static char XCUIELEMENT_IS_RESOLVED_NATIVELY_KEY;
41
41
  XCUIElementQuery *query = [self isKindOfClass:XCUIApplication.class]
42
42
  ? self.application.fb_query
43
43
  : [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny];
44
- XCElementSnapshot *cachedSnapshot = self.fb_cachedSnapshot;
44
+ FBXCElementSnapshotWrapper *cachedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:self.fb_cachedSnapshot];
45
45
  NSString *uid = nil == cachedSnapshot ? self.fb_uid : cachedSnapshot.fb_uid;
46
- return nil == uid
47
- ? self
48
- : [query matchingPredicate:[NSPredicate predicateWithFormat:@"%K = %@", FBStringify(XCUIElement, wdUID), uid]].fb_firstMatch;
46
+ if (nil == uid) {
47
+ return self;
48
+ }
49
+ NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot, NSDictionary *bindings) {
50
+ return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_uid isEqualToString:uid];
51
+ }];
52
+ return (XCUIElement *)[query matchingPredicate:predicate].fb_firstMatch;
49
53
  }
50
54
 
51
55
  @end
@@ -13,12 +13,11 @@
13
13
  #import "FBLogger.h"
14
14
  #import "FBMacros.h"
15
15
  #import "FBMathUtils.h"
16
- #import "FBPredicate.h"
17
16
  #import "FBXCodeCompatibility.h"
17
+ #import "FBXCElementSnapshotWrapper.h"
18
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
18
19
  #import "XCUIApplication+FBTouchAction.h"
19
20
  #import "XCUIElement+FBCaching.h"
20
- #import "XCElementSnapshot+FBHelpers.h"
21
- #import "XCElementSnapshot.h"
22
21
  #import "XCUIApplication.h"
23
22
  #import "XCUICoordinate.h"
24
23
  #import "XCUICoordinate+FBFix.h"
@@ -34,7 +33,7 @@ const CGFloat FBScrollTouchProportion = 0.75f;
34
33
 
35
34
  #if !TARGET_OS_TV
36
35
 
37
- @interface XCElementSnapshot (FBScrolling)
36
+ @interface FBXCElementSnapshotWrapper (FBScrolling)
38
37
 
39
38
  - (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application;
40
39
  - (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application;
@@ -49,7 +48,7 @@ const CGFloat FBScrollTouchProportion = 0.75f;
49
48
 
50
49
  - (BOOL)fb_nativeScrollToVisibleWithError:(NSError **)error
51
50
  {
52
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
51
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
53
52
  ? self.lastSnapshot
54
53
  : self.fb_takeSnapshot;
55
54
  return nil != [self _hitPointByAttemptingToScrollToVisibleSnapshot:snapshot
@@ -58,34 +57,38 @@ const CGFloat FBScrollTouchProportion = 0.75f;
58
57
 
59
58
  - (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance
60
59
  {
61
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
60
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
62
61
  ? self.lastSnapshot
63
62
  : self.fb_takeSnapshot;
64
- [snapshot fb_scrollUpByNormalizedDistance:distance inApplication:self.application];
63
+ [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollUpByNormalizedDistance:distance
64
+ inApplication:self.application];
65
65
  }
66
66
 
67
67
  - (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance
68
68
  {
69
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
69
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
70
70
  ? self.lastSnapshot
71
71
  : self.fb_takeSnapshot;
72
- [snapshot fb_scrollDownByNormalizedDistance:distance inApplication:self.application];
72
+ [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollDownByNormalizedDistance:distance
73
+ inApplication:self.application];
73
74
  }
74
75
 
75
76
  - (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance
76
77
  {
77
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
78
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
78
79
  ? self.lastSnapshot
79
80
  : self.fb_takeSnapshot;
80
- [snapshot fb_scrollLeftByNormalizedDistance:distance inApplication:self.application];
81
+ [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollLeftByNormalizedDistance:distance
82
+ inApplication:self.application];
81
83
  }
82
84
 
83
85
  - (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance
84
86
  {
85
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
87
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
86
88
  ? self.lastSnapshot
87
89
  : self.fb_takeSnapshot;
88
- [snapshot fb_scrollRightByNormalizedDistance:distance inApplication:self.application];
90
+ [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollRightByNormalizedDistance:distance
91
+ inApplication:self.application];
89
92
  }
90
93
 
91
94
  - (BOOL)fb_scrollToVisibleWithError:(NSError **)error
@@ -100,9 +103,11 @@ const CGFloat FBScrollTouchProportion = 0.75f;
100
103
  error:error];
101
104
  }
102
105
 
103
- - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance scrollDirection:(FBXCUIElementScrollDirection)scrollDirection error:(NSError **)error
106
+ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance
107
+ scrollDirection:(FBXCUIElementScrollDirection)scrollDirection
108
+ error:(NSError **)error
104
109
  {
105
- XCElementSnapshot *prescrollSnapshot = [self fb_takeSnapshot];
110
+ FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]];
106
111
  if (prescrollSnapshot.isWDVisible) {
107
112
  return YES;
108
113
  }
@@ -118,23 +123,30 @@ const CGFloat FBScrollTouchProportion = 0.75f;
118
123
  ];
119
124
  });
120
125
 
121
- __block NSArray<XCElementSnapshot *> *cellSnapshots, *visibleCellSnapshots;
122
- XCElementSnapshot *scrollView = [prescrollSnapshot fb_parentMatchingOneOfTypes:acceptedParents
123
- filter:^(XCElementSnapshot *snapshot) {
124
-
125
- if (![snapshot isWDVisible]) {
126
- return NO;
127
- }
128
-
129
- cellSnapshots = [snapshot fb_descendantsCellSnapshots];
126
+ __block NSArray<id<FBXCElementSnapshot>> *cellSnapshots;
127
+ __block NSMutableArray<id<FBXCElementSnapshot>> *visibleCellSnapshots = [NSMutableArray new];
128
+ id<FBXCElementSnapshot> scrollView = [prescrollSnapshot fb_parentMatchingOneOfTypes:acceptedParents
129
+ filter:^(id<FBXCElementSnapshot> snapshot) {
130
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
131
+
132
+ if (![wrappedSnapshot isWDVisible]) {
133
+ return NO;
134
+ }
130
135
 
131
- visibleCellSnapshots = [cellSnapshots filteredArrayUsingPredicate:[FBPredicate predicateWithFormat:@"%K == YES", FBStringify(XCUIElement, fb_isVisible)]];
136
+ cellSnapshots = [wrappedSnapshot fb_descendantsCellSnapshots];
137
+
138
+ for (id<FBXCElementSnapshot> cellSnapshot in cellSnapshots) {
139
+ FBXCElementSnapshotWrapper *wrappedCellSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:cellSnapshot];
140
+ if (wrappedCellSnapshot.wdVisible) {
141
+ [visibleCellSnapshots addObject:cellSnapshot];
142
+ }
143
+ }
132
144
 
133
- if (visibleCellSnapshots.count > 1) {
134
- return YES;
135
- }
136
- return NO;
137
- }];
145
+ if (visibleCellSnapshots.count > 1) {
146
+ return YES;
147
+ }
148
+ return NO;
149
+ }];
138
150
 
139
151
  if (scrollView == nil) {
140
152
  return
@@ -143,20 +155,21 @@ const CGFloat FBScrollTouchProportion = 0.75f;
143
155
  buildError:error];
144
156
  }
145
157
 
146
- XCElementSnapshot *targetCellSnapshot = [prescrollSnapshot fb_parentCellSnapshot];
147
- XCElementSnapshot *lastSnapshot = visibleCellSnapshots.lastObject;
158
+ id<FBXCElementSnapshot> targetCellSnapshot = [prescrollSnapshot fb_parentCellSnapshot];
159
+ id<FBXCElementSnapshot> lastSnapshot = visibleCellSnapshots.lastObject;
148
160
  // Can't just do indexOfObject, because targetCellSnapshot may represent the same object represented by a member of cellSnapshots, yet be a different object
149
161
  // than that member. This reflects the fact that targetCellSnapshot came out of self.fb_parentCellSnapshot, not out of cellSnapshots directly.
150
162
  // If the result is NSNotFound, we'll just proceed by scrolling downward/rightward, since NSNotFound will always be larger than the current index.
151
- NSUInteger targetCellIndex = [cellSnapshots indexOfObjectPassingTest:^BOOL(XCElementSnapshot *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
163
+ NSUInteger targetCellIndex = [cellSnapshots indexOfObjectPassingTest:^BOOL(id<FBXCElementSnapshot> _Nonnull obj,
164
+ NSUInteger idx, BOOL *_Nonnull stop) {
152
165
  return [obj _matchesElement:targetCellSnapshot];
153
166
  }];
154
167
  NSUInteger visibleCellIndex = [cellSnapshots indexOfObject:lastSnapshot];
155
168
 
156
169
  if (scrollDirection == FBXCUIElementScrollDirectionUnknown) {
157
170
  // Try to determine the scroll direction by determining the vector between the first and last visible cells
158
- XCElementSnapshot *firstVisibleCell = visibleCellSnapshots.firstObject;
159
- XCElementSnapshot *lastVisibleCell = visibleCellSnapshots.lastObject;
171
+ id<FBXCElementSnapshot> firstVisibleCell = visibleCellSnapshots.firstObject;
172
+ id<FBXCElementSnapshot> lastVisibleCell = visibleCellSnapshots.lastObject;
160
173
  CGVector cellGrowthVector = CGVectorMake(firstVisibleCell.frame.origin.x - lastVisibleCell.frame.origin.x,
161
174
  firstVisibleCell.frame.origin.y - lastVisibleCell.frame.origin.y
162
175
  );
@@ -169,17 +182,22 @@ const CGFloat FBScrollTouchProportion = 0.75f;
169
182
 
170
183
  const NSUInteger maxScrollCount = 25;
171
184
  NSUInteger scrollCount = 0;
185
+ FBXCElementSnapshotWrapper *scrollViewWrapped = [FBXCElementSnapshotWrapper ensureWrapped:scrollView];
172
186
  // Scrolling till cell is visible and get current value of frames
173
187
  while (![self fb_isEquivalentElementSnapshotVisible:prescrollSnapshot] && scrollCount < maxScrollCount) {
174
188
  if (targetCellIndex < visibleCellIndex) {
175
189
  scrollDirection == FBXCUIElementScrollDirectionVertical ?
176
- [scrollView fb_scrollUpByNormalizedDistance:normalizedScrollDistance inApplication:self.application] :
177
- [scrollView fb_scrollLeftByNormalizedDistance:normalizedScrollDistance inApplication:self.application];
190
+ [scrollViewWrapped fb_scrollUpByNormalizedDistance:normalizedScrollDistance
191
+ inApplication:self.application] :
192
+ [scrollViewWrapped fb_scrollLeftByNormalizedDistance:normalizedScrollDistance
193
+ inApplication:self.application];
178
194
  }
179
195
  else {
180
196
  scrollDirection == FBXCUIElementScrollDirectionVertical ?
181
- [scrollView fb_scrollDownByNormalizedDistance:normalizedScrollDistance inApplication:self.application] :
182
- [scrollView fb_scrollRightByNormalizedDistance:normalizedScrollDistance inApplication:self.application];
197
+ [scrollViewWrapped fb_scrollDownByNormalizedDistance:normalizedScrollDistance
198
+ inApplication:self.application] :
199
+ [scrollViewWrapped fb_scrollRightByNormalizedDistance:normalizedScrollDistance
200
+ inApplication:self.application];
183
201
  }
184
202
  scrollCount++;
185
203
  // Wait for scroll animation
@@ -196,28 +214,32 @@ const CGFloat FBScrollTouchProportion = 0.75f;
196
214
  // Cell is now visible, but it might be only partialy visible, scrolling till whole frame is visible.
197
215
  // Sometimes, attempting to grab the parent snapshot of the target cell after scrolling is complete causes a stale element reference exception.
198
216
  // Trying fb_cachedSnapshot first
199
- targetCellSnapshot = [([self fb_cachedSnapshot] ?: [self fb_takeSnapshot]) fb_parentCellSnapshot];
200
- CGRect visibleFrame = targetCellSnapshot.fb_visibleFrameWithFallback;
217
+ FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:([self fb_cachedSnapshot] ?: [self fb_takeSnapshot])];
218
+ targetCellSnapshot = [targetCellSnapshotWrapped fb_parentCellSnapshot];
219
+ CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].fb_visibleFrameWithFallback;
201
220
 
202
221
  CGVector scrollVector = CGVectorMake(visibleFrame.size.width - targetCellSnapshot.frame.size.width,
203
222
  visibleFrame.size.height - targetCellSnapshot.frame.size.height
204
223
  );
205
- if (![scrollView fb_scrollByVector:scrollVector inApplication:self.application error:error]) {
206
- return NO;
207
- }
208
- return YES;
224
+ return [scrollViewWrapped fb_scrollByVector:scrollVector
225
+ inApplication:self.application
226
+ error:error];
209
227
  }
210
228
 
211
- - (BOOL)fb_isEquivalentElementSnapshotVisible:(XCElementSnapshot *)snapshot
229
+ - (BOOL)fb_isEquivalentElementSnapshotVisible:(id<FBXCElementSnapshot>)snapshot
212
230
  {
213
- if (snapshot.isWDVisible) {
231
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
232
+
233
+ if (wrappedSnapshot.isWDVisible) {
214
234
  return YES;
215
235
  }
216
236
 
217
- XCElementSnapshot *appSnapshot = [self.application fb_takeSnapshot];
218
- for (XCElementSnapshot *elementSnapshot in appSnapshot._allDescendants.copy) {
237
+ id<FBXCElementSnapshot> appSnapshot = [self.application fb_takeSnapshot];
238
+ for (id<FBXCElementSnapshot> elementSnapshot in appSnapshot._allDescendants.copy) {
239
+ FBXCElementSnapshotWrapper *wrappedElementSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:elementSnapshot];
219
240
  // We are comparing pre-scroll snapshot so frames are irrelevant.
220
- if ([snapshot fb_framelessFuzzyMatchesElement:elementSnapshot] && elementSnapshot.isWDVisible) {
241
+ if ([wrappedSnapshot fb_framelessFuzzyMatchesElement:elementSnapshot]
242
+ && wrappedElementSnapshot.isWDVisible) {
221
243
  return YES;
222
244
  }
223
245
  }
@@ -227,7 +249,7 @@ const CGFloat FBScrollTouchProportion = 0.75f;
227
249
  @end
228
250
 
229
251
 
230
- @implementation XCElementSnapshot (FBScrolling)
252
+ @implementation FBXCElementSnapshotWrapper (FBScrolling)
231
253
 
232
254
  - (CGRect)scrollingFrame
233
255
  {
@@ -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
  {