appium-webdriveragent 4.7.0 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) 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/WebDriverAgent.xcodeproj/project.xcworkspace/xcuserdata/elf.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  18. package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +91 -0
  19. package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcschemes/xcschememanagement.plist +59 -0
  20. package/WebDriverAgentLib/Categories/{XCElementSnapshot+FBHelpers.h → FBXCElementSnapshotWrapper+Helpers.h} +18 -11
  21. package/WebDriverAgentLib/Categories/{XCElementSnapshot+FBHelpers.m → FBXCElementSnapshotWrapper+Helpers.m} +57 -39
  22. package/WebDriverAgentLib/Categories/NSExpression+FBFormat.m +8 -3
  23. package/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +8 -7
  24. package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +2 -2
  25. package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +29 -28
  26. package/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m +5 -0
  27. package/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m +0 -1
  28. package/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +8 -5
  29. package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h +2 -2
  30. package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m +5 -4
  31. package/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +3 -2
  32. package/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +22 -18
  33. package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h +2 -3
  34. package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +28 -26
  35. package/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +2 -1
  36. package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +8 -4
  37. package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +73 -51
  38. package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +11 -10
  39. package/WebDriverAgentLib/Categories/XCUIElement+FBUID.h +10 -5
  40. package/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +15 -3
  41. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +7 -7
  42. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +29 -20
  43. package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h +2 -2
  44. package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +16 -13
  45. package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h +2 -3
  46. package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m +3 -3
  47. package/WebDriverAgentLib/Commands/FBElementCommands.m +15 -14
  48. package/WebDriverAgentLib/Commands/FBFindElementCommands.m +5 -6
  49. package/WebDriverAgentLib/FBAlert.m +16 -13
  50. package/WebDriverAgentLib/FBApplication.m +8 -8
  51. package/WebDriverAgentLib/Routing/FBElementUtils.h +11 -2
  52. package/WebDriverAgentLib/Routing/FBElementUtils.m +15 -12
  53. package/WebDriverAgentLib/Routing/FBResponsePayload.m +11 -10
  54. package/WebDriverAgentLib/Routing/FBSession.m +1 -1
  55. package/{PrivateHeaders/XCTest/XCAccessibilityElement.h → WebDriverAgentLib/Routing/FBXCAccessibilityElement.h} +19 -18
  56. package/WebDriverAgentLib/{Categories/XCAccessibilityElement+FBComparison.m → Routing/FBXCAccessibilityElement.m} +5 -11
  57. package/WebDriverAgentLib/Routing/FBXCDeviceEvent.h +35 -0
  58. package/WebDriverAgentLib/Routing/FBXCDeviceEvent.m +43 -0
  59. package/{PrivateHeaders/XCTest/XCElementSnapshot.h → WebDriverAgentLib/Routing/FBXCElementSnapshot.h} +25 -44
  60. package/WebDriverAgentLib/Routing/FBXCElementSnapshot.m +10 -0
  61. package/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h +30 -0
  62. package/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m +45 -0
  63. package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h +3 -4
  64. package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m +4 -4
  65. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +2 -2
  66. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +7 -8
  67. package/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m +1 -2
  68. package/WebDriverAgentLib/Utilities/FBConfiguration.m +0 -1
  69. package/WebDriverAgentLib/Utilities/FBImageIOScaler.m +3 -0
  70. package/WebDriverAgentLib/Utilities/FBKeyboard.m +1 -2
  71. package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +1 -1
  72. package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +3 -3
  73. package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +10 -9
  74. package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +14 -8
  75. package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +0 -1
  76. package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +6 -0
  77. package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +0 -10
  78. package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +0 -24
  79. package/WebDriverAgentLib/Utilities/FBXPath-Private.h +1 -1
  80. package/WebDriverAgentLib/Utilities/FBXPath.h +3 -3
  81. package/WebDriverAgentLib/Utilities/FBXPath.m +15 -13
  82. package/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.h +14 -1
  83. package/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m +18 -9
  84. package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +9 -3
  85. package/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m +7 -1
  86. package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +7 -1
  87. package/WebDriverAgentLib/WebDriverAgentLib.h +0 -1
  88. package/WebDriverAgentRunner-Runner.app.zip +0 -0
  89. package/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +26 -19
  90. package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m +24 -29
  91. package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m +2 -2
  92. package/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +5 -3
  93. package/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +2 -1
  94. package/{WebDriverAgentLib/Categories/XCElementSnapshot+FBHitPoint.h → WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.h} +3 -14
  95. package/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +99 -0
  96. package/WebDriverAgentTests/UnitTests/FBXPathTests.m +21 -13
  97. package/WebDriverAgentTests/UnitTests/NSPredicateFBFormatTests.m +4 -5
  98. package/package.json +1 -1
  99. package/WebDriverAgentLib/Categories/XCAccessibilityElement+FBComparison.h +0 -27
  100. package/WebDriverAgentLib/Categories/XCElementSnapshot+FBHitPoint.m +0 -29
  101. package/WebDriverAgentLib/Utilities/FBPredicate.h +0 -28
  102. package/WebDriverAgentLib/Utilities/FBPredicate.m +0 -29
@@ -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
  {
@@ -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