appium-webdriveragent 8.12.2 → 9.0.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 (56) hide show
  1. package/CHANGELOG.md +10 -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 +1 -1
  12. package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +28 -173
  13. package/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +1 -3
  14. package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +33 -30
  15. package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +4 -8
  16. package/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +2 -2
  17. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +3 -36
  18. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +10 -68
  19. package/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h +36 -0
  20. package/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m +53 -0
  21. package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +7 -20
  22. package/WebDriverAgentLib/Commands/FBCustomCommands.m +2 -1
  23. package/WebDriverAgentLib/Commands/FBElementCommands.m +25 -47
  24. package/WebDriverAgentLib/Commands/FBFindElementCommands.m +10 -9
  25. package/WebDriverAgentLib/Commands/FBSessionCommands.m +0 -8
  26. package/WebDriverAgentLib/FBAlert.m +6 -5
  27. package/WebDriverAgentLib/Info.plist +2 -2
  28. package/WebDriverAgentLib/Routing/FBElementCache.h +4 -10
  29. package/WebDriverAgentLib/Routing/FBElementCache.m +4 -33
  30. package/WebDriverAgentLib/Routing/FBResponsePayload.m +1 -7
  31. package/WebDriverAgentLib/Utilities/FBConfiguration.h +0 -8
  32. package/WebDriverAgentLib/Utilities/FBConfiguration.m +0 -12
  33. package/WebDriverAgentLib/Utilities/FBSettings.h +0 -3
  34. package/WebDriverAgentLib/Utilities/FBSettings.m +0 -2
  35. package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +1 -3
  36. package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +1 -1
  37. package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +4 -3
  38. package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +7 -11
  39. package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +3 -1
  40. package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +2 -2
  41. package/WebDriverAgentLib/Utilities/FBXPath.m +1 -4
  42. package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h +3 -0
  43. package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +1 -0
  44. package/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +2 -1
  45. package/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m +1 -1
  46. package/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +1 -1
  47. package/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +2 -2
  48. package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m +21 -10
  49. package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m +1 -1
  50. package/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +5 -3
  51. package/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +10 -0
  52. package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +1 -2
  53. package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +1 -1
  54. package/WebDriverAgentTests/UnitTests/FBElementCacheTests.m +0 -2
  55. package/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h +0 -1
  56. package/package.json +1 -1
@@ -126,38 +126,22 @@
126
126
  {
127
127
  FBElementCache *elementCache = request.session.elementCache;
128
128
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
129
- BOOL isEnabled = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDEnabled;
130
- return FBResponseWithObject(isEnabled ? @YES : @NO);
129
+ return FBResponseWithObject(@(element.isWDEnabled));
131
130
  }
132
131
 
133
132
  + (id<FBResponsePayload>)handleGetRect:(FBRouteRequest *)request
134
133
  {
135
134
  FBElementCache *elementCache = request.session.elementCache;
136
135
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
137
- return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdRect);
136
+ return FBResponseWithObject(element.wdRect);
138
137
  }
139
138
 
140
139
  + (id<FBResponsePayload>)handleGetAttribute:(FBRouteRequest *)request
141
140
  {
142
141
  FBElementCache *elementCache = request.session.elementCache;
143
142
  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];
143
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
144
+ id attributeValue = [element fb_valueForWDAttributeName:attributeName];
161
145
  return FBResponseWithObject(attributeValue ?: [NSNull null]);
162
146
  }
163
147
 
@@ -165,7 +149,7 @@
165
149
  {
166
150
  FBElementCache *elementCache = request.session.elementCache;
167
151
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
168
- FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot];
152
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[element fb_takeSnapshot:NO]];
169
153
  id text = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel);
170
154
  return FBResponseWithObject(text ?: @"");
171
155
  }
@@ -173,48 +157,43 @@
173
157
  + (id<FBResponsePayload>)handleGetDisplayed:(FBRouteRequest *)request
174
158
  {
175
159
  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));
160
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
161
+ return FBResponseWithObject(@(element.isWDVisible));
180
162
  }
181
163
 
182
164
  + (id<FBResponsePayload>)handleGetAccessible:(FBRouteRequest *)request
183
165
  {
184
166
  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));
167
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
168
+ return FBResponseWithObject(@(element.isWDAccessible));
189
169
  }
190
170
 
191
171
  + (id<FBResponsePayload>)handleGetIsAccessibilityContainer:(FBRouteRequest *)request
192
172
  {
193
173
  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));
174
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
175
+ return FBResponseWithObject(@(element.isWDAccessibilityContainer));
198
176
  }
199
177
 
200
178
  + (id<FBResponsePayload>)handleGetName:(FBRouteRequest *)request
201
179
  {
202
180
  FBElementCache *elementCache = request.session.elementCache;
203
181
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
204
- return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdType);
182
+ return FBResponseWithObject(element.wdType);
205
183
  }
206
184
 
207
185
  + (id<FBResponsePayload>)handleGetSelected:(FBRouteRequest *)request
208
186
  {
209
187
  FBElementCache *elementCache = request.session.elementCache;
210
188
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
211
- return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdSelected));
189
+ return FBResponseWithObject(@(element.wdSelected));
212
190
  }
213
191
 
214
192
  + (id<FBResponsePayload>)handleSetValue:(FBRouteRequest *)request
215
193
  {
216
194
  FBElementCache *elementCache = request.session.elementCache;
217
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
195
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
196
+ checkStaleness:YES];
218
197
  id value = request.arguments[@"value"] ?: request.arguments[@"text"];
219
198
  if (!value) {
220
199
  return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"Neither 'value' nor 'text' parameter is provided" traceback:nil]);
@@ -222,7 +201,7 @@
222
201
  NSString *textToType = [value isKindOfClass:NSArray.class]
223
202
  ? [value componentsJoinedByString:@""]
224
203
  : value;
225
- XCUIElementType elementType = [(id<FBXCElementSnapshot>)element.lastSnapshot elementType];
204
+ XCUIElementType elementType = [element elementType];
226
205
  #if !TARGET_OS_TV
227
206
  if (elementType == XCUIElementTypePickerWheel) {
228
207
  [element adjustToPickerWheelValue:textToType];
@@ -251,7 +230,7 @@
251
230
  + (id<FBResponsePayload>)handleClick:(FBRouteRequest *)request
252
231
  {
253
232
  FBElementCache *elementCache = request.session.elementCache;
254
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
233
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] checkStaleness:YES];
255
234
  #if TARGET_OS_IOS
256
235
  [element tap];
257
236
  #elif TARGET_OS_TV
@@ -353,7 +332,7 @@
353
332
  FBElementCache *elementCache = request.session.elementCache;
354
333
  XCUIElement *element = [self targetFromRequest:request];
355
334
  [element pressForDuration:[request.arguments[@"pressDuration"] doubleValue]
356
- thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"]]
335
+ thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"] checkStaleness:YES]
357
336
  withVelocity:[request.arguments[@"velocity"] doubleValue]
358
337
  thenHoldForDuration:[request.arguments[@"holdDuration"] doubleValue]];
359
338
  return FBResponseWithOK();
@@ -441,10 +420,7 @@
441
420
 
442
421
  + (id<FBResponsePayload>)handleDrag:(FBRouteRequest *)request
443
422
  {
444
- NSString *elementUdid = (NSString *)request.parameters[@"uuid"];
445
- XCUIElement *target = nil == elementUdid
446
- ? request.session.activeApplication
447
- : [request.session.elementCache elementForUUID:elementUdid];
423
+ XCUIElement *target = [self targetFromRequest:request];
448
424
  CGVector startOffset = CGVectorMake([request.arguments[@"fromX"] doubleValue],
449
425
  [request.arguments[@"fromY"] doubleValue]);
450
426
  XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset element:target];
@@ -561,7 +537,8 @@
561
537
  + (id<FBResponsePayload>)handleElementScreenshot:(FBRouteRequest *)request
562
538
  {
563
539
  FBElementCache *elementCache = request.session.elementCache;
564
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
540
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
541
+ checkStaleness:YES];
565
542
  NSData *screenshotData = [element.screenshot PNGRepresentation];
566
543
  if (nil == screenshotData) {
567
544
  NSString *errMsg = [NSString stringWithFormat:@"Cannot take a screenshot of %@", element.description];
@@ -581,8 +558,9 @@ static const NSInteger DEFAULT_MAX_PICKER_ATTEMPTS = 25;
581
558
  + (id<FBResponsePayload>)handleWheelSelect:(FBRouteRequest *)request
582
559
  {
583
560
  FBElementCache *elementCache = request.session.elementCache;
584
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
585
- if ([element.lastSnapshot elementType] != XCUIElementTypePickerWheel) {
561
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
562
+ checkStaleness:YES];
563
+ if ([element elementType] != XCUIElementTypePickerWheel) {
586
564
  NSString *errMsg = [NSString stringWithFormat:@"The element is expected to be a valid Picker Wheel control. '%@' was given instead", element.wdType];
587
565
  return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg
588
566
  traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
@@ -688,7 +666,7 @@ static const NSInteger DEFAULT_MAX_PICKER_ATTEMPTS = 25;
688
666
  NSString *elementUuid = (NSString *)request.parameters[@"uuid"];
689
667
  return nil == elementUuid
690
668
  ? request.session.activeApplication
691
- : [elementCache elementForUUID:elementUuid];
669
+ : [elementCache elementForUUID:elementUuid checkStaleness:YES];
692
670
  }
693
671
 
694
672
  #endif
@@ -80,15 +80,14 @@ 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]
90
+ selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]
92
91
  onlyChildren:NO];
93
92
  return FBResponseWithCachedElements(cells, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
94
93
  }
@@ -96,7 +95,8 @@ static id<FBResponsePayload> FBNoSuchElementErrorResponseForRequest(FBRouteReque
96
95
  + (id<FBResponsePayload>)handleFindSubElement:(FBRouteRequest *)request
97
96
  {
98
97
  FBElementCache *elementCache = request.session.elementCache;
99
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
98
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
99
+ checkStaleness:YES];
100
100
  XCUIElement *foundElement = [self.class elementUsing:request.arguments[@"using"]
101
101
  withValue:request.arguments[@"value"]
102
102
  under:element];
@@ -109,7 +109,8 @@ static id<FBResponsePayload> FBNoSuchElementErrorResponseForRequest(FBRouteReque
109
109
  + (id<FBResponsePayload>)handleFindSubElements:(FBRouteRequest *)request
110
110
  {
111
111
  FBElementCache *elementCache = request.session.elementCache;
112
- XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
112
+ XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
113
+ checkStaleness:YES];
113
114
  NSArray *foundElements = [self.class elementsUsing:request.arguments[@"using"]
114
115
  withValue:request.arguments[@"value"]
115
116
  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.0</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.0</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
@@ -91,13 +91,7 @@ id<FBResponsePayload> FBResponseWithStatus(FBCommandStatus *status)
91
91
 
92
92
  inline NSDictionary *FBDictionaryResponseWithElement(XCUIElement *element, BOOL compact)
93
93
  {
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
- }
94
+ id<FBXCElementSnapshot> snapshot = element.lastSnapshot ?: element.fb_cachedSnapshot ?: [element fb_takeSnapshot:YES];
101
95
  NSDictionary *compactResult = FBToElementDict((NSString *)[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]);
102
96
  if (compact) {
103
97
  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
@@ -10,6 +10,8 @@
10
10
  #import <WebDriverAgentLib/WebDriverAgentLib.h>
11
11
  #import "XCPointerEvent.h"
12
12
 
13
+ @class FBXCElementSnapshot;
14
+
13
15
  /**
14
16
  The version of testmanagerd process which is running on the device.
15
17
 
@@ -46,7 +48,7 @@ NS_ASSUME_NONNULL_BEGIN
46
48
  @param error The error instance if there was a failure while retrieveing the snapshot
47
49
  @returns The cached unqiue snapshot or nil if the element is stale
48
50
  */
49
- - (nullable XCElementSnapshot *)fb_uniqueSnapshotWithError:(NSError **)error;
51
+ - (nullable id<FBXCElementSnapshot>)fb_uniqueSnapshotWithError:(NSError **)error;
50
52
 
51
53
  @end
52
54
 
@@ -20,9 +20,9 @@
20
20
 
21
21
  @implementation XCUIElementQuery (FBCompatibility)
22
22
 
23
- - (XCElementSnapshot *)fb_uniqueSnapshotWithError:(NSError **)error
23
+ - (id<FBXCElementSnapshot>)fb_uniqueSnapshotWithError:(NSError **)error
24
24
  {
25
- return [self uniqueMatchingSnapshotWithError:error];
25
+ return (id<FBXCElementSnapshot>)[self uniqueMatchingSnapshotWithError:error];
26
26
  }
27
27
 
28
28
  - (XCUIElement *)fb_firstMatch
@@ -368,15 +368,12 @@ static NSString *const topNodeIndexPath = @"top";
368
368
  NSArray<id<FBXCElementSnapshot>> *children;
369
369
  if ([root isKindOfClass:XCUIElement.class]) {
370
370
  XCUIElement *element = (XCUIElement *)root;
371
- NSMutableArray<NSString *> *snapshotAttributes = [NSMutableArray arrayWithArray:FBStandardAttributeNames()];
372
371
  if (nil == includedAttributes || [includedAttributes containsObject:FBVisibleAttribute.class]) {
373
- [snapshotAttributes addObject:FB_XCAXAIsVisibleAttributeName];
374
372
  // If the app is not idle state while we retrieve the visiblity state
375
373
  // then the snapshot retrieval operation might freeze and time out
376
374
  [element.application fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout];
377
375
  }
378
- currentSnapshot = [element fb_snapshotWithAttributes:snapshotAttributes.copy
379
- maxDepth:nil];
376
+ currentSnapshot = [element fb_takeSnapshot:YES];
380
377
  children = currentSnapshot.children;
381
378
  } else {
382
379
  currentSnapshot = (id<FBXCElementSnapshot>)root;
@@ -19,6 +19,9 @@ extern NSString *FB_XCAXAIsVisibleAttributeName;
19
19
  extern NSNumber *FB_XCAXAIsElementAttribute;
20
20
  extern NSString *FB_XCAXAIsElementAttributeName;
21
21
 
22
+ /*! Accessibility identifier for visible frame attribute */
23
+ extern NSString *FB_XCAXAVisibleFrameAttributeName;
24
+
22
25
  /*! Getter for XCTest logger */
23
26
  extern id<XCDebugLogDelegate> (*XCDebugLogger)(void);
24
27