appium-webdriveragent 8.12.2 → 9.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +1 -0
  3. package/WebDriverAgent.xcodeproj/project.pbxproj +12 -0
  4. package/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.h +4 -9
  5. package/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.m +13 -25
  6. package/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +2 -2
  7. package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +4 -20
  8. package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m +15 -4
  9. package/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h +0 -3
  10. package/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +1 -22
  11. package/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +0 -1
  12. package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +28 -173
  13. package/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +3 -4
  14. package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h +2 -1
  15. package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +9 -13
  16. package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +33 -30
  17. package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +4 -8
  18. package/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +2 -2
  19. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +3 -39
  20. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +13 -74
  21. package/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h +36 -0
  22. package/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m +53 -0
  23. package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +7 -20
  24. package/WebDriverAgentLib/Commands/FBCustomCommands.m +2 -1
  25. package/WebDriverAgentLib/Commands/FBElementCommands.m +29 -48
  26. package/WebDriverAgentLib/Commands/FBFindElementCommands.m +9 -9
  27. package/WebDriverAgentLib/Commands/FBSessionCommands.m +0 -8
  28. package/WebDriverAgentLib/FBAlert.m +6 -5
  29. package/WebDriverAgentLib/Info.plist +2 -2
  30. package/WebDriverAgentLib/Routing/FBElementCache.h +4 -10
  31. package/WebDriverAgentLib/Routing/FBElementCache.m +4 -33
  32. package/WebDriverAgentLib/Routing/FBResponsePayload.m +19 -13
  33. package/WebDriverAgentLib/Utilities/FBConfiguration.h +0 -8
  34. package/WebDriverAgentLib/Utilities/FBConfiguration.m +0 -12
  35. package/WebDriverAgentLib/Utilities/FBSettings.h +0 -3
  36. package/WebDriverAgentLib/Utilities/FBSettings.m +0 -2
  37. package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +1 -3
  38. package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +1 -1
  39. package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +4 -3
  40. package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +7 -11
  41. package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +3 -1
  42. package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +2 -2
  43. package/WebDriverAgentLib/Utilities/FBXPath.m +1 -4
  44. package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h +3 -0
  45. package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +1 -0
  46. package/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +2 -1
  47. package/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m +1 -1
  48. package/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +1 -1
  49. package/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +1 -3
  50. package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m +21 -10
  51. package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m +1 -1
  52. package/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +5 -1
  53. package/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +4 -3
  54. package/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +10 -0
  55. package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +1 -2
  56. package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +1 -1
  57. package/WebDriverAgentTests/UnitTests/FBElementCacheTests.m +0 -2
  58. package/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h +0 -1
  59. package/package.json +1 -1
@@ -35,6 +35,7 @@
35
35
  #import "XCUIElement+FBWebDriverAttributes.h"
36
36
  #import "XCUIElement+FBTVFocuse.h"
37
37
  #import "XCUIElement+FBResolve.h"
38
+ #import "XCUIElement+FBUID.h"
38
39
  #import "FBElementTypeTransformer.h"
39
40
  #import "XCUIElement.h"
40
41
  #import "XCUIElementQuery.h"
@@ -126,38 +127,22 @@
126
127
  {
127
128
  FBElementCache *elementCache = request.session.elementCache;
128
129
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
129
- BOOL isEnabled = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDEnabled;
130
- return FBResponseWithObject(isEnabled ? @YES : @NO);
130
+ return FBResponseWithObject(@(element.isWDEnabled));
131
131
  }
132
132
 
133
133
  + (id<FBResponsePayload>)handleGetRect:(FBRouteRequest *)request
134
134
  {
135
135
  FBElementCache *elementCache = request.session.elementCache;
136
136
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
137
- return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdRect);
137
+ return FBResponseWithObject(element.wdRect);
138
138
  }
139
139
 
140
140
  + (id<FBResponsePayload>)handleGetAttribute:(FBRouteRequest *)request
141
141
  {
142
142
  FBElementCache *elementCache = request.session.elementCache;
143
143
  NSString *attributeName = request.parameters[@"name"];
144
- NSString *wdAttributeName = [FBElementUtils wdAttributeNameForAttributeName:attributeName];
145
- NSArray *additionalAttributes = nil;
146
- NSNumber *maxDepth = nil;
147
- if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDVisible)]) {
148
- additionalAttributes = @[FB_XCAXAIsVisibleAttributeName];
149
- maxDepth = @1;
150
- } else if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDEnabled)]) {
151
- additionalAttributes = @[FB_XCAXAIsElementAttributeName];
152
- maxDepth = @1;
153
- } else if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)]) {
154
- additionalAttributes = @[FB_XCAXAIsElementAttributeName];
155
- }
156
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
157
- resolveForAdditionalAttributes:additionalAttributes
158
- andMaxDepth:maxDepth];
159
- FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot];
160
- id attributeValue = [wrappedSnapshot fb_valueForWDAttributeName:attributeName];
144
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
145
+ id attributeValue = [element fb_valueForWDAttributeName:attributeName];
161
146
  return FBResponseWithObject(attributeValue ?: [NSNull null]);
162
147
  }
163
148
 
@@ -165,7 +150,7 @@
165
150
  {
166
151
  FBElementCache *elementCache = request.session.elementCache;
167
152
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
168
- FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot];
153
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[element fb_takeSnapshot:NO]];
169
154
  id text = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel);
170
155
  return FBResponseWithObject(text ?: @"");
171
156
  }
@@ -173,48 +158,43 @@
173
158
  + (id<FBResponsePayload>)handleGetDisplayed:(FBRouteRequest *)request
174
159
  {
175
160
  FBElementCache *elementCache = request.session.elementCache;
176
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
177
- resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName]
178
- andMaxDepth:@1];
179
- return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDVisible));
161
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
162
+ return FBResponseWithObject(@(element.isWDVisible));
180
163
  }
181
164
 
182
165
  + (id<FBResponsePayload>)handleGetAccessible:(FBRouteRequest *)request
183
166
  {
184
167
  FBElementCache *elementCache = request.session.elementCache;
185
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
186
- resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName]
187
- andMaxDepth:@1];
188
- return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessible));
168
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
169
+ return FBResponseWithObject(@(element.isWDAccessible));
189
170
  }
190
171
 
191
172
  + (id<FBResponsePayload>)handleGetIsAccessibilityContainer:(FBRouteRequest *)request
192
173
  {
193
174
  FBElementCache *elementCache = request.session.elementCache;
194
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
195
- resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName]
196
- andMaxDepth:nil];
197
- return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessibilityContainer));
175
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
176
+ return FBResponseWithObject(@(element.isWDAccessibilityContainer));
198
177
  }
199
178
 
200
179
  + (id<FBResponsePayload>)handleGetName:(FBRouteRequest *)request
201
180
  {
202
181
  FBElementCache *elementCache = request.session.elementCache;
203
182
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
204
- return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdType);
183
+ return FBResponseWithObject(element.wdType);
205
184
  }
206
185
 
207
186
  + (id<FBResponsePayload>)handleGetSelected:(FBRouteRequest *)request
208
187
  {
209
188
  FBElementCache *elementCache = request.session.elementCache;
210
189
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
211
- return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdSelected));
190
+ return FBResponseWithObject(@(element.wdSelected));
212
191
  }
213
192
 
214
193
  + (id<FBResponsePayload>)handleSetValue:(FBRouteRequest *)request
215
194
  {
216
195
  FBElementCache *elementCache = request.session.elementCache;
217
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
196
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
197
+ checkStaleness:YES];
218
198
  id value = request.arguments[@"value"] ?: request.arguments[@"text"];
219
199
  if (!value) {
220
200
  return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"Neither 'value' nor 'text' parameter is provided" traceback:nil]);
@@ -222,7 +202,7 @@
222
202
  NSString *textToType = [value isKindOfClass:NSArray.class]
223
203
  ? [value componentsJoinedByString:@""]
224
204
  : value;
225
- XCUIElementType elementType = [(id<FBXCElementSnapshot>)element.lastSnapshot elementType];
205
+ XCUIElementType elementType = [element elementType];
226
206
  #if !TARGET_OS_TV
227
207
  if (elementType == XCUIElementTypePickerWheel) {
228
208
  [element adjustToPickerWheelValue:textToType];
@@ -251,7 +231,7 @@
251
231
  + (id<FBResponsePayload>)handleClick:(FBRouteRequest *)request
252
232
  {
253
233
  FBElementCache *elementCache = request.session.elementCache;
254
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
234
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] checkStaleness:YES];
255
235
  #if TARGET_OS_IOS
256
236
  [element tap];
257
237
  #elif TARGET_OS_TV
@@ -285,7 +265,9 @@
285
265
  if (focusedElement != nil) {
286
266
  FBElementCache *elementCache = request.session.elementCache;
287
267
  BOOL useNativeCachingStrategy = request.session.useNativeCachingStrategy;
288
- NSString *focusedUUID = [elementCache storeElement:(useNativeCachingStrategy ? focusedElement : focusedElement.fb_stableInstance)];
268
+ NSString *focusedUUID = [elementCache storeElement:(useNativeCachingStrategy
269
+ ? focusedElement
270
+ : [focusedElement fb_stableInstanceWithUid:focusedElement.fb_uid])];
289
271
  if (focusedUUID && [focusedUUID isEqualToString:(id)request.parameters[@"uuid"]]) {
290
272
  isFocused = YES;
291
273
  }
@@ -353,7 +335,7 @@
353
335
  FBElementCache *elementCache = request.session.elementCache;
354
336
  XCUIElement *element = [self targetFromRequest:request];
355
337
  [element pressForDuration:[request.arguments[@"pressDuration"] doubleValue]
356
- thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"]]
338
+ thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"] checkStaleness:YES]
357
339
  withVelocity:[request.arguments[@"velocity"] doubleValue]
358
340
  thenHoldForDuration:[request.arguments[@"holdDuration"] doubleValue]];
359
341
  return FBResponseWithOK();
@@ -441,10 +423,7 @@
441
423
 
442
424
  + (id<FBResponsePayload>)handleDrag:(FBRouteRequest *)request
443
425
  {
444
- NSString *elementUdid = (NSString *)request.parameters[@"uuid"];
445
- XCUIElement *target = nil == elementUdid
446
- ? request.session.activeApplication
447
- : [request.session.elementCache elementForUUID:elementUdid];
426
+ XCUIElement *target = [self targetFromRequest:request];
448
427
  CGVector startOffset = CGVectorMake([request.arguments[@"fromX"] doubleValue],
449
428
  [request.arguments[@"fromY"] doubleValue]);
450
429
  XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset element:target];
@@ -561,7 +540,8 @@
561
540
  + (id<FBResponsePayload>)handleElementScreenshot:(FBRouteRequest *)request
562
541
  {
563
542
  FBElementCache *elementCache = request.session.elementCache;
564
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
543
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
544
+ checkStaleness:YES];
565
545
  NSData *screenshotData = [element.screenshot PNGRepresentation];
566
546
  if (nil == screenshotData) {
567
547
  NSString *errMsg = [NSString stringWithFormat:@"Cannot take a screenshot of %@", element.description];
@@ -581,8 +561,9 @@ static const NSInteger DEFAULT_MAX_PICKER_ATTEMPTS = 25;
581
561
  + (id<FBResponsePayload>)handleWheelSelect:(FBRouteRequest *)request
582
562
  {
583
563
  FBElementCache *elementCache = request.session.elementCache;
584
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
585
- if ([element.lastSnapshot elementType] != XCUIElementTypePickerWheel) {
564
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
565
+ checkStaleness:YES];
566
+ if ([element elementType] != XCUIElementTypePickerWheel) {
586
567
  NSString *errMsg = [NSString stringWithFormat:@"The element is expected to be a valid Picker Wheel control. '%@' was given instead", element.wdType];
587
568
  return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg
588
569
  traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
@@ -688,7 +669,7 @@ static const NSInteger DEFAULT_MAX_PICKER_ATTEMPTS = 25;
688
669
  NSString *elementUuid = (NSString *)request.parameters[@"uuid"];
689
670
  return nil == elementUuid
690
671
  ? request.session.activeApplication
691
- : [elementCache elementForUUID:elementUuid];
672
+ : [elementCache elementForUUID:elementUuid checkStaleness:YES];
692
673
  }
693
674
 
694
675
  #endif
@@ -80,15 +80,13 @@ static id<FBResponsePayload> FBNoSuchElementErrorResponseForRequest(FBRouteReque
80
80
  + (id<FBResponsePayload>)handleFindVisibleCells:(FBRouteRequest *)request
81
81
  {
82
82
  FBElementCache *elementCache = request.session.elementCache;
83
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
84
- resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName]
85
- andMaxDepth:nil];
86
- NSArray<id<FBXCElementSnapshot>> *visibleCellSnapshots = [element.lastSnapshot descendantsByFilteringWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot) {
87
- return snapshot.elementType == XCUIElementTypeCell
88
- && [FBXCElementSnapshotWrapper ensureWrapped:snapshot].wdVisible;
83
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
84
+ id<FBXCElementSnapshot> snapshot = [element fb_takeSnapshot:YES];
85
+ NSArray<id<FBXCElementSnapshot>> *visibleCellSnapshots = [snapshot descendantsByFilteringWithBlock:^BOOL(id<FBXCElementSnapshot> shot) {
86
+ return shot.elementType == XCUIElementTypeCell
87
+ && [FBXCElementSnapshotWrapper ensureWrapped:shot].wdVisible;
89
88
  }];
90
89
  NSArray *cells = [element fb_filterDescendantsWithSnapshots:visibleCellSnapshots
91
- selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:element.lastSnapshot]
92
90
  onlyChildren:NO];
93
91
  return FBResponseWithCachedElements(cells, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
94
92
  }
@@ -96,7 +94,8 @@ static id<FBResponsePayload> FBNoSuchElementErrorResponseForRequest(FBRouteReque
96
94
  + (id<FBResponsePayload>)handleFindSubElement:(FBRouteRequest *)request
97
95
  {
98
96
  FBElementCache *elementCache = request.session.elementCache;
99
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
97
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
98
+ checkStaleness:YES];
100
99
  XCUIElement *foundElement = [self.class elementUsing:request.arguments[@"using"]
101
100
  withValue:request.arguments[@"value"]
102
101
  under:element];
@@ -109,7 +108,8 @@ static id<FBResponsePayload> FBNoSuchElementErrorResponseForRequest(FBRouteReque
109
108
  + (id<FBResponsePayload>)handleFindSubElements:(FBRouteRequest *)request
110
109
  {
111
110
  FBElementCache *elementCache = request.session.elementCache;
112
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
111
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
112
+ checkStaleness:YES];
113
113
  NSArray *foundElements = [self.class elementsUsing:request.arguments[@"using"]
114
114
  withValue:request.arguments[@"value"]
115
115
  under:element
@@ -336,7 +336,6 @@
336
336
  FB_SETTING_SCREENSHOT_QUALITY: @([FBConfiguration screenshotQuality]),
337
337
  FB_SETTING_KEYBOARD_AUTOCORRECTION: @([FBConfiguration keyboardAutocorrection]),
338
338
  FB_SETTING_KEYBOARD_PREDICTION: @([FBConfiguration keyboardPrediction]),
339
- FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT: @([FBConfiguration customSnapshotTimeout]),
340
339
  FB_SETTING_SNAPSHOT_MAX_DEPTH: @([FBConfiguration snapshotMaxDepth]),
341
340
  FB_SETTING_USE_FIRST_MATCH: @([FBConfiguration useFirstMatch]),
342
341
  FB_SETTING_WAIT_FOR_IDLE_TIMEOUT: @([FBConfiguration waitForIdleTimeout]),
@@ -395,13 +394,6 @@
395
394
  if (nil != [settings objectForKey:FB_SETTING_RESPECT_SYSTEM_ALERTS]) {
396
395
  [FBConfiguration setShouldRespectSystemAlerts:[[settings objectForKey:FB_SETTING_RESPECT_SYSTEM_ALERTS] boolValue]];
397
396
  }
398
- // SNAPSHOT_TIMEOUT setting is deprecated. Please use CUSTOM_SNAPSHOT_TIMEOUT instead
399
- if (nil != [settings objectForKey:FB_SETTING_SNAPSHOT_TIMEOUT]) {
400
- [FBConfiguration setCustomSnapshotTimeout:[[settings objectForKey:FB_SETTING_SNAPSHOT_TIMEOUT] doubleValue]];
401
- }
402
- if (nil != [settings objectForKey:FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT]) {
403
- [FBConfiguration setCustomSnapshotTimeout:[[settings objectForKey:FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT] doubleValue]];
404
- }
405
397
  if (nil != [settings objectForKey:FB_SETTING_SNAPSHOT_MAX_DEPTH]) {
406
398
  [FBConfiguration setSnapshotMaxDepth:[[settings objectForKey:FB_SETTING_SNAPSHOT_MAX_DEPTH] intValue]];
407
399
  }
@@ -50,7 +50,7 @@
50
50
  if (nil == self.alertElement) {
51
51
  return NO;
52
52
  }
53
- [self.alertElement fb_takeSnapshot];
53
+ [self.alertElement fb_takeSnapshot:YES];
54
54
  return YES;
55
55
  } @catch (NSException *) {
56
56
  return NO;
@@ -82,7 +82,7 @@
82
82
  }
83
83
 
84
84
  NSMutableArray<NSString *> *resultText = [NSMutableArray array];
85
- id<FBXCElementSnapshot> snapshot = self.alertElement.lastSnapshot;
85
+ id<FBXCElementSnapshot> snapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_takeSnapshot:YES];
86
86
  BOOL isSafariAlert = [self.class isSafariWebAlertWithSnapshot:snapshot];
87
87
  [snapshot enumerateDescendantsUsingBlock:^(id<FBXCElementSnapshot> descendant) {
88
88
  XCUIElementType elementType = descendant.elementType;
@@ -145,7 +145,8 @@
145
145
  }
146
146
 
147
147
  NSMutableArray<NSString *> *labels = [NSMutableArray array];
148
- [self.alertElement.lastSnapshot enumerateDescendantsUsingBlock:^(id<FBXCElementSnapshot> descendant) {
148
+ id<FBXCElementSnapshot> alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_takeSnapshot:YES];
149
+ [alertSnapshot enumerateDescendantsUsingBlock:^(id<FBXCElementSnapshot> descendant) {
149
150
  if (descendant.elementType != XCUIElementTypeButton) {
150
151
  return;
151
152
  }
@@ -163,7 +164,7 @@
163
164
  return [self notPresentWithError:error];
164
165
  }
165
166
 
166
- id<FBXCElementSnapshot> alertSnapshot = self.alertElement.lastSnapshot;
167
+ id<FBXCElementSnapshot> alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_takeSnapshot:YES];
167
168
  XCUIElement *acceptButton = nil;
168
169
  if (FBConfiguration.acceptAlertButtonSelector.length) {
169
170
  NSString *errorReason = nil;
@@ -204,7 +205,7 @@
204
205
  return [self notPresentWithError:error];
205
206
  }
206
207
 
207
- id<FBXCElementSnapshot> alertSnapshot = self.alertElement.lastSnapshot;
208
+ id<FBXCElementSnapshot> alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_takeSnapshot:YES];
208
209
  XCUIElement *dismissButton = nil;
209
210
  if (FBConfiguration.dismissAlertButtonSelector.length) {
210
211
  NSString *errorReason = nil;
@@ -15,11 +15,11 @@
15
15
  <key>CFBundlePackageType</key>
16
16
  <string>FMWK</string>
17
17
  <key>CFBundleShortVersionString</key>
18
- <string>8.12.2</string>
18
+ <string>9.0.1</string>
19
19
  <key>CFBundleSignature</key>
20
20
  <string>????</string>
21
21
  <key>CFBundleVersion</key>
22
- <string>8.12.2</string>
22
+ <string>9.0.1</string>
23
23
  <key>NSPrincipalClass</key>
24
24
  <string/>
25
25
  </dict>
@@ -35,26 +35,20 @@ extern const int ELEMENT_CACHE_SIZE;
35
35
 
36
36
  @param uuid uuid of element to fetch
37
37
  @return element
38
- @throws FBStaleElementException if the found element is not present in DOM anymore
39
38
  @throws FBInvalidArgumentException if uuid is nil
40
39
  */
41
40
  - (XCUIElement *)elementForUUID:(NSString *)uuid;
42
41
 
43
42
  /**
44
- Returns cached element
43
+ Returns cached element resolved with default snapshot attributes
45
44
 
46
45
  @param uuid uuid of element to fetch
47
- @param additionalAttributes Add additonal attribute names if the snapshot should contain
48
- them in `addtionalAttributes` section. nil value resolves the snapshot with standard attributes.
49
- @param maxDepth The maximum depth of the snapshot. Only works if additional attributes are provided.
50
- `nil` value means to use the default maximum depth value.
46
+ @param checkStaleness Whether to throw FBStaleElementException if the found element is not present in DOM anymore
51
47
  @return element
52
- @throws FBStaleElementException if the found element is not present in DOM anymore
48
+ @throws FBStaleElementException if `checkStaleness` is enabled
53
49
  @throws FBInvalidArgumentException if uuid is nil
54
50
  */
55
- - (XCUIElement *)elementForUUID:(NSString *)uuid
56
- resolveForAdditionalAttributes:(nullable NSArray <NSString *> *)additionalAttributes
57
- andMaxDepth:(nullable NSNumber *)maxDepth;
51
+ - (XCUIElement *)elementForUUID:(NSString *)uuid checkStaleness:(BOOL)checkStaleness;
58
52
 
59
53
  /**
60
54
  Checks element existence in the cache
@@ -26,7 +26,6 @@ const int ELEMENT_CACHE_SIZE = 1024;
26
26
 
27
27
  @interface FBElementCache ()
28
28
  @property (nonatomic, strong) LRUCache *elementCache;
29
- @property (nonatomic) BOOL elementsNeedReset;
30
29
  @end
31
30
 
32
31
  @implementation FBElementCache
@@ -38,7 +37,6 @@ const int ELEMENT_CACHE_SIZE = 1024;
38
37
  return nil;
39
38
  }
40
39
  _elementCache = [[LRUCache alloc] initWithCapacity:ELEMENT_CACHE_SIZE];
41
- _elementsNeedReset = NO;
42
40
  return self;
43
41
  }
44
42
 
@@ -50,19 +48,16 @@ const int ELEMENT_CACHE_SIZE = 1024;
50
48
  }
51
49
  @synchronized (self.elementCache) {
52
50
  [self.elementCache setObject:element forKey:uuid];
53
- self.elementsNeedReset = YES;
54
51
  }
55
52
  return uuid;
56
53
  }
57
54
 
58
55
  - (XCUIElement *)elementForUUID:(NSString *)uuid
59
56
  {
60
- return [self elementForUUID:uuid resolveForAdditionalAttributes:nil andMaxDepth:nil];
57
+ return [self elementForUUID:uuid checkStaleness:NO];
61
58
  }
62
59
 
63
- - (XCUIElement *)elementForUUID:(NSString *)uuid
64
- resolveForAdditionalAttributes:(NSArray <NSString *> *)additionalAttributes
65
- andMaxDepth:(NSNumber *)maxDepth
60
+ - (XCUIElement *)elementForUUID:(NSString *)uuid checkStaleness:(BOOL)checkStaleness
66
61
  {
67
62
  if (!uuid) {
68
63
  NSString *reason = [NSString stringWithFormat:@"Cannot extract cached element for UUID: %@", uuid];
@@ -71,23 +66,15 @@ const int ELEMENT_CACHE_SIZE = 1024;
71
66
 
72
67
  XCUIElement *element;
73
68
  @synchronized (self.elementCache) {
74
- [self resetElements];
75
69
  element = [self.elementCache objectForKey:uuid];
76
70
  }
77
71
  if (nil == element) {
78
72
  NSString *reason = [NSString stringWithFormat:@"The element identified by \"%@\" is either not present or it has expired from the internal cache. Try to find it again", uuid];
79
73
  @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}];
80
74
  }
81
- // This will throw FBStaleElementException exception if the element is stale
82
- // or resolve the element and set lastSnapshot property
83
- if (nil == additionalAttributes) {
84
- [element fb_takeSnapshot];
85
- } else {
86
- NSMutableArray *attributes = [NSMutableArray arrayWithArray:FBStandardAttributeNames()];
87
- [attributes addObjectsFromArray:additionalAttributes];
88
- [element fb_snapshotWithAttributes:attributes.copy maxDepth:maxDepth];
75
+ if (checkStaleness) {
76
+ [element fb_takeSnapshot:NO];
89
77
  }
90
- element.fb_isResolvedFromCache = @(YES);
91
78
  return element;
92
79
  }
93
80
 
@@ -101,20 +88,4 @@ const int ELEMENT_CACHE_SIZE = 1024;
101
88
  }
102
89
  }
103
90
 
104
- - (void)resetElements
105
- {
106
- if (!self.elementsNeedReset) {
107
- return;
108
- }
109
-
110
- for (XCUIElement *element in self.elementCache.allObjects) {
111
- element.lastSnapshot = nil;
112
- if (nil != element.query) {
113
- element.query.rootElementSnapshot = nil;
114
- }
115
- element.fb_isResolvedFromCache = @(NO);
116
- }
117
- self.elementsNeedReset = NO;
118
- }
119
-
120
91
  @end
@@ -34,23 +34,35 @@ id<FBResponsePayload> FBResponseWithObject(id object)
34
34
  return FBResponseWithStatus([FBCommandStatus okWithValue:object]);
35
35
  }
36
36
 
37
- id<FBResponsePayload> FBResponseWithCachedElement(XCUIElement *element, FBElementCache *elementCache, BOOL compact)
37
+ XCUIElement *maybeStable(XCUIElement *element)
38
38
  {
39
39
  BOOL useNativeCachingStrategy = nil == FBSession.activeSession
40
40
  ? YES
41
41
  : FBSession.activeSession.useNativeCachingStrategy;
42
- [elementCache storeElement:(useNativeCachingStrategy ? element : element.fb_stableInstance)];
42
+ if (useNativeCachingStrategy) {
43
+ return element;
44
+ }
45
+
46
+ XCUIElement *result = element;
47
+ id<FBXCElementSnapshot> snapshot = element.lastSnapshot ?: [element fb_cachedSnapshot] ?: [element fb_takeSnapshot:NO];
48
+ NSString *uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot];
49
+ if (nil != uid) {
50
+ result = [element fb_stableInstanceWithUid:uid];
51
+ }
52
+ return result;
53
+ }
54
+
55
+ id<FBResponsePayload> FBResponseWithCachedElement(XCUIElement *element, FBElementCache *elementCache, BOOL compact)
56
+ {
57
+ [elementCache storeElement:maybeStable(element)];
43
58
  return FBResponseWithStatus([FBCommandStatus okWithValue:FBDictionaryResponseWithElement(element, compact)]);
44
59
  }
45
60
 
46
61
  id<FBResponsePayload> FBResponseWithCachedElements(NSArray<XCUIElement *> *elements, FBElementCache *elementCache, BOOL compact)
47
62
  {
48
63
  NSMutableArray *elementsResponse = [NSMutableArray array];
49
- BOOL useNativeCachingStrategy = nil == FBSession.activeSession
50
- ? YES
51
- : FBSession.activeSession.useNativeCachingStrategy;
52
64
  for (XCUIElement *element in elements) {
53
- [elementCache storeElement:(useNativeCachingStrategy ? element : element.fb_stableInstance)];
65
+ [elementCache storeElement:maybeStable(element)];
54
66
  [elementsResponse addObject:FBDictionaryResponseWithElement(element, compact)];
55
67
  }
56
68
  return FBResponseWithStatus([FBCommandStatus okWithValue:elementsResponse]);
@@ -91,13 +103,7 @@ id<FBResponsePayload> FBResponseWithStatus(FBCommandStatus *status)
91
103
 
92
104
  inline NSDictionary *FBDictionaryResponseWithElement(XCUIElement *element, BOOL compact)
93
105
  {
94
- id<FBXCElementSnapshot> snapshot = nil;
95
- if (nil != element.query.rootElementSnapshot) {
96
- snapshot = element.fb_cachedSnapshot;
97
- }
98
- if (nil == snapshot) {
99
- snapshot = element.lastSnapshot ?: element.fb_takeSnapshot;
100
- }
106
+ id<FBXCElementSnapshot> snapshot = element.lastSnapshot ?: element.fb_cachedSnapshot ?: [element fb_takeSnapshot:YES];
101
107
  NSDictionary *compactResult = FBToElementDict((NSString *)[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]);
102
108
  if (compact) {
103
109
  return compactResult;
@@ -177,14 +177,6 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) {
177
177
  + (void)setKeyboardPrediction:(BOOL)isEnabled;
178
178
  + (FBConfigurationKeyboardPreference)keyboardPrediction;
179
179
 
180
- /**
181
- * The maximum time to wait until accessibility snapshot is taken
182
- *
183
- * @param timeout The number of float seconds to wait (15 seconds by default)
184
- */
185
- + (void)setCustomSnapshotTimeout:(NSTimeInterval)timeout;
186
- + (NSTimeInterval)customSnapshotTimeout;
187
-
188
180
  /**
189
181
  Sets maximum depth for traversing elements tree from parents to children while requesting XCElementSnapshot.
190
182
  Used to set maxDepth value in a dictionary provided by XCAXClient_iOS's method defaultParams.
@@ -46,7 +46,6 @@ static NSUInteger FBMjpegServerFramerate = 10;
46
46
  static BOOL FBShouldTerminateApp;
47
47
  static NSNumber* FBMaxTypingFrequency;
48
48
  static NSUInteger FBScreenshotQuality;
49
- static NSTimeInterval FBCustomSnapshotTimeout;
50
49
  static BOOL FBShouldUseFirstMatch;
51
50
  static BOOL FBShouldBoundElementsByIndex;
52
51
  static BOOL FBIncludeNonModalElements;
@@ -359,16 +358,6 @@ static UIInterfaceOrientation FBScreenshotOrientation;
359
358
  [self configureKeyboardsPreference:isEnabled forPreferenceKey:FBKeyboardPredictionKey];
360
359
  }
361
360
 
362
- + (void)setCustomSnapshotTimeout:(NSTimeInterval)timeout
363
- {
364
- FBCustomSnapshotTimeout = timeout;
365
- }
366
-
367
- + (NSTimeInterval)customSnapshotTimeout
368
- {
369
- return FBCustomSnapshotTimeout;
370
- }
371
-
372
361
  + (void)setSnapshotMaxDepth:(int)maxDepth
373
362
  {
374
363
  FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @(maxDepth));
@@ -502,7 +491,6 @@ static UIInterfaceOrientation FBScreenshotOrientation;
502
491
  FBElementResponseAttributes = @"type,label";
503
492
  FBMaxTypingFrequency = @([self defaultTypingFrequency]);
504
493
  FBScreenshotQuality = 3;
505
- FBCustomSnapshotTimeout = 15.;
506
494
  FBShouldUseFirstMatch = NO;
507
495
  FBShouldBoundElementsByIndex = NO;
508
496
  // This is diabled by default because enabling it prevents the accessbility snapshot to be taken
@@ -22,9 +22,6 @@ extern NSString* const FB_SETTING_MJPEG_SCALING_FACTOR;
22
22
  extern NSString* const FB_SETTING_SCREENSHOT_QUALITY;
23
23
  extern NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION;
24
24
  extern NSString* const FB_SETTING_KEYBOARD_PREDICTION;
25
- // This setting is deprecated. Please use CUSTOM_SNAPSHOT_TIMEOUT instead
26
- extern NSString* const FB_SETTING_SNAPSHOT_TIMEOUT;
27
- extern NSString* const FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT;
28
25
  extern NSString* const FB_SETTING_SNAPSHOT_MAX_DEPTH;
29
26
  extern NSString* const FB_SETTING_USE_FIRST_MATCH;
30
27
  extern NSString* const FB_SETTING_BOUND_ELEMENTS_BY_INDEX;
@@ -18,8 +18,6 @@ NSString* const FB_SETTING_MJPEG_FIX_ORIENTATION = @"mjpegFixOrientation";
18
18
  NSString* const FB_SETTING_SCREENSHOT_QUALITY = @"screenshotQuality";
19
19
  NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION = @"keyboardAutocorrection";
20
20
  NSString* const FB_SETTING_KEYBOARD_PREDICTION = @"keyboardPrediction";
21
- NSString* const FB_SETTING_SNAPSHOT_TIMEOUT = @"snapshotTimeout";
22
- NSString* const FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT = @"customSnapshotTimeout";
23
21
  NSString* const FB_SETTING_SNAPSHOT_MAX_DEPTH = @"snapshotMaxDepth";
24
22
  NSString* const FB_SETTING_USE_FIRST_MATCH = @"useFirstMatch";
25
23
  NSString* const FB_SETTING_BOUND_ELEMENTS_BY_INDEX = @"boundElementsByIndex";
@@ -57,9 +57,7 @@
57
57
  self = [super init];
58
58
  if (self) {
59
59
  _targetElement = targetElement;
60
- CGRect frame = targetElement.fb_isResolvedFromCache.boolValue
61
- ? [FBXCElementSnapshotWrapper ensureWrapped:targetElement.lastSnapshot].wdFrame
62
- : targetElement.wdFrame;
60
+ CGRect frame = targetElement.wdFrame;
63
61
  _targetCenter = FBRectGetCenter(frame);
64
62
  _navigationItems = [NSMutableDictionary dictionary];
65
63
  }
@@ -661,7 +661,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
661
661
  if ([origin isKindOfClass:XCUIElement.class]) {
662
662
  instance = origin;
663
663
  } else if ([origin isKindOfClass:NSString.class]) {
664
- instance = [self.elementCache elementForUUID:(NSString *)origin];
664
+ instance = [self.elementCache elementForUUID:(NSString *)origin checkStaleness:YES];
665
665
  } else {
666
666
  [result addObject:actionItem];
667
667
  continue;
@@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
27
27
 
28
28
  - (nullable id<FBXCElementSnapshot>)snapshotForElement:(id<FBXCAccessibilityElement>)element
29
29
  attributes:(nullable NSArray<NSString *> *)attributes
30
- maxDepth:(nullable NSNumber *)maxDepth
30
+ inDepth:(BOOL)inDepth
31
31
  error:(NSError **)error;
32
32
 
33
33
  - (NSArray<id<FBXCAccessibilityElement>> *)activeApplications;
@@ -39,8 +39,9 @@ NS_ASSUME_NONNULL_BEGIN
39
39
  - (void)notifyWhenNoAnimationsAreActiveForApplication:(XCUIApplication *)application
40
40
  reply:(void (^)(void))reply;
41
41
 
42
- - (NSDictionary *)attributesForElement:(id<FBXCAccessibilityElement>)element
43
- attributes:(NSArray *)attributes;
42
+ - (nullable NSDictionary *)attributesForElement:(id<FBXCAccessibilityElement>)element
43
+ attributes:(NSArray *)attributes
44
+ error:(NSError**)error;
44
45
 
45
46
  - (XCUIApplication *)monitoredApplicationWithProcessIdentifier:(int)pid;
46
47
 
@@ -37,12 +37,12 @@ static id FBAXClient = nil;
37
37
 
38
38
  - (id<FBXCElementSnapshot>)snapshotForElement:(id<FBXCAccessibilityElement>)element
39
39
  attributes:(NSArray<NSString *> *)attributes
40
- maxDepth:(nullable NSNumber *)maxDepth
40
+ inDepth:(BOOL)inDepth
41
41
  error:(NSError **)error
42
42
  {
43
43
  NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithDictionary:self.defaultParameters];
44
- if (nil != maxDepth) {
45
- parameters[FBSnapshotMaxDepthKey] = maxDepth;
44
+ if (!inDepth) {
45
+ parameters[FBSnapshotMaxDepthKey] = @1;
46
46
  }
47
47
 
48
48
  id result = [FBAXClient requestSnapshotForElement:element
@@ -76,15 +76,11 @@ static id FBAXClient = nil;
76
76
 
77
77
  - (NSDictionary *)attributesForElement:(id<FBXCAccessibilityElement>)element
78
78
  attributes:(NSArray *)attributes
79
+ error:(NSError**)error;
79
80
  {
80
- NSError *error = nil;
81
- NSDictionary* result = [FBAXClient attributesForElement:element
82
- attributes:attributes
83
- error:&error];
84
- if (error) {
85
- [FBLogger logFmt:@"Cannot retrieve element attribute(s) %@. Original error: %@", attributes, error.description];
86
- }
87
- return result;
81
+ return [FBAXClient attributesForElement:element
82
+ attributes:attributes
83
+ error:error];
88
84
  }
89
85
 
90
86
  - (XCUIApplication *)monitoredApplicationWithProcessIdentifier:(int)pid