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
@@ -9,7 +9,6 @@
9
9
 
10
10
  #import "XCUIApplication+FBHelpers.h"
11
11
 
12
- #import "XCElementSnapshot.h"
13
12
  #import "FBElementTypeTransformer.h"
14
13
  #import "FBKeyboard.h"
15
14
  #import "FBLogger.h"
@@ -18,11 +17,11 @@
18
17
  #import "FBActiveAppDetectionPoint.h"
19
18
  #import "FBXCodeCompatibility.h"
20
19
  #import "FBXPath.h"
20
+ #import "FBXCAccessibilityElement.h"
21
21
  #import "FBXCTestDaemonsProxy.h"
22
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
22
23
  #import "FBXCAXClientProxy.h"
23
24
  #import "FBXMLGenerationOptions.h"
24
- #import "XCAccessibilityElement.h"
25
- #import "XCElementSnapshot+FBHelpers.h"
26
25
  #import "XCUIDevice+FBHelpers.h"
27
26
  #import "XCUIElement+FBCaching.h"
28
27
  #import "XCUIElement+FBIsVisible.h"
@@ -41,11 +40,11 @@ static NSString* const FBUnknownBundleId = @"unknown";
41
40
  - (BOOL)fb_waitForAppElement:(NSTimeInterval)timeout
42
41
  {
43
42
  __block BOOL canDetectAxElement = YES;
44
- int currentProcessIdentifier = self.accessibilityElement.processIdentifier;
43
+ int currentProcessIdentifier = [self.accessibilityElement processIdentifier];
45
44
  BOOL result = [[[FBRunLoopSpinner new]
46
45
  timeout:timeout]
47
46
  spinUntilTrue:^BOOL{
48
- XCAccessibilityElement *currentAppElement = FBActiveAppDetectionPoint.sharedInstance.axElement;
47
+ id<FBXCAccessibilityElement> currentAppElement = FBActiveAppDetectionPoint.sharedInstance.axElement;
49
48
  canDetectAxElement = nil != currentAppElement;
50
49
  if (!canDetectAxElement) {
51
50
  return YES;
@@ -57,11 +56,11 @@ static NSString* const FBUnknownBundleId = @"unknown";
57
56
  : [self waitForExistenceWithTimeout:timeout];
58
57
  }
59
58
 
60
- + (NSArray<NSDictionary<NSString *, id> *> *)fb_appsInfoWithAxElements:(NSArray<XCAccessibilityElement *> *)axElements
59
+ + (NSArray<NSDictionary<NSString *, id> *> *)fb_appsInfoWithAxElements:(NSArray<id<FBXCAccessibilityElement>> *)axElements
61
60
  {
62
61
  NSMutableArray<NSDictionary<NSString *, id> *> *result = [NSMutableArray array];
63
62
  id<XCTestManager_ManagerInterface> proxy = [FBXCTestDaemonsProxy testRunnerProxy];
64
- for (XCAccessibilityElement *axElement in axElements) {
63
+ for (id<FBXCAccessibilityElement> axElement in axElements) {
65
64
  NSMutableDictionary<NSString *, id> *appInfo = [NSMutableDictionary dictionary];
66
65
  pid_t pid = axElement.processIdentifier;
67
66
  appInfo[@"pid"] = @(pid);
@@ -100,7 +99,7 @@ static NSString* const FBUnknownBundleId = @"unknown";
100
99
 
101
100
  - (NSDictionary *)fb_tree
102
101
  {
103
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
102
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
104
103
  ? self.lastSnapshot
105
104
  : [self fb_snapshotWithAllAttributesAndMaxDepth:nil];
106
105
  return [self.class dictionaryForElement:snapshot recursive:YES];
@@ -108,27 +107,28 @@ static NSString* const FBUnknownBundleId = @"unknown";
108
107
 
109
108
  - (NSDictionary *)fb_accessibilityTree
110
109
  {
111
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
110
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
112
111
  ? self.lastSnapshot
113
112
  : [self fb_snapshotWithAllAttributesAndMaxDepth:nil];
114
113
  return [self.class accessibilityInfoForElement:snapshot];
115
114
  }
116
115
 
117
- + (NSDictionary *)dictionaryForElement:(XCElementSnapshot *)snapshot recursive:(BOOL)recursive
116
+ + (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot recursive:(BOOL)recursive
118
117
  {
119
118
  NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
120
119
  info[@"type"] = [FBElementTypeTransformer shortStringWithElementType:snapshot.elementType];
121
120
  info[@"rawIdentifier"] = FBValueOrNull([snapshot.identifier isEqual:@""] ? nil : snapshot.identifier);
122
- info[@"name"] = FBValueOrNull(snapshot.wdName);
123
- info[@"value"] = FBValueOrNull(snapshot.wdValue);
124
- info[@"label"] = FBValueOrNull(snapshot.wdLabel);
125
- info[@"rect"] = snapshot.wdRect;
126
- info[@"frame"] = NSStringFromCGRect(snapshot.wdFrame);
127
- info[@"isEnabled"] = [@([snapshot isWDEnabled]) stringValue];
128
- info[@"isVisible"] = [@([snapshot isWDVisible]) stringValue];
129
- info[@"isAccessible"] = [@([snapshot isWDAccessible]) stringValue];
121
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
122
+ info[@"name"] = FBValueOrNull(wrappedSnapshot.wdName);
123
+ info[@"value"] = FBValueOrNull(wrappedSnapshot.wdValue);
124
+ info[@"label"] = FBValueOrNull(wrappedSnapshot.wdLabel);
125
+ info[@"rect"] = wrappedSnapshot.wdRect;
126
+ info[@"frame"] = NSStringFromCGRect(wrappedSnapshot.wdFrame);
127
+ info[@"isEnabled"] = [@([wrappedSnapshot isWDEnabled]) stringValue];
128
+ info[@"isVisible"] = [@([wrappedSnapshot isWDVisible]) stringValue];
129
+ info[@"isAccessible"] = [@([wrappedSnapshot isWDAccessible]) stringValue];
130
130
  #if TARGET_OS_TV
131
- info[@"isFocused"] = [@([snapshot isWDFocused]) stringValue];
131
+ info[@"isFocused"] = [@([wrappedSnapshot isWDFocused]) stringValue];
132
132
  #endif
133
133
 
134
134
  if (!recursive) {
@@ -138,28 +138,29 @@ static NSString* const FBUnknownBundleId = @"unknown";
138
138
  NSArray *childElements = snapshot.children;
139
139
  if ([childElements count]) {
140
140
  info[@"children"] = [[NSMutableArray alloc] init];
141
- for (XCElementSnapshot *childSnapshot in childElements) {
141
+ for (id<FBXCElementSnapshot> childSnapshot in childElements) {
142
142
  [info[@"children"] addObject:[self dictionaryForElement:childSnapshot recursive:YES]];
143
143
  }
144
144
  }
145
145
  return info;
146
146
  }
147
147
 
148
- + (NSDictionary *)accessibilityInfoForElement:(XCElementSnapshot *)snapshot
148
+ + (NSDictionary *)accessibilityInfoForElement:(id<FBXCElementSnapshot>)snapshot
149
149
  {
150
- BOOL isAccessible = [snapshot isWDAccessible];
151
- BOOL isVisible = [snapshot isWDVisible];
150
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
151
+ BOOL isAccessible = [wrappedSnapshot isWDAccessible];
152
+ BOOL isVisible = [wrappedSnapshot isWDVisible];
152
153
 
153
154
  NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
154
155
 
155
156
  if (isAccessible) {
156
157
  if (isVisible) {
157
- info[@"value"] = FBValueOrNull(snapshot.wdValue);
158
- info[@"label"] = FBValueOrNull(snapshot.wdLabel);
158
+ info[@"value"] = FBValueOrNull(wrappedSnapshot.wdValue);
159
+ info[@"label"] = FBValueOrNull(wrappedSnapshot.wdLabel);
159
160
  }
160
161
  } else {
161
162
  NSMutableArray *children = [[NSMutableArray alloc] init];
162
- for (XCElementSnapshot *childSnapshot in snapshot.children) {
163
+ for (id<FBXCElementSnapshot> childSnapshot in snapshot.children) {
163
164
  NSDictionary *childInfo = [self accessibilityInfoForElement:childSnapshot];
164
165
  if ([childInfo count]) {
165
166
  [children addObject: childInfo];
@@ -172,7 +173,7 @@ static NSString* const FBUnknownBundleId = @"unknown";
172
173
  if ([info count]) {
173
174
  info[@"type"] = [FBElementTypeTransformer shortStringWithElementType:snapshot.elementType];
174
175
  info[@"rawIdentifier"] = FBValueOrNull([snapshot.identifier isEqual:@""] ? nil : snapshot.identifier);
175
- info[@"name"] = FBValueOrNull(snapshot.wdName);
176
+ info[@"name"] = FBValueOrNull(wrappedSnapshot.wdName);
176
177
  } else {
177
178
  return nil;
178
179
  }
@@ -243,7 +244,7 @@ static NSString* const FBUnknownBundleId = @"unknown";
243
244
  };
244
245
 
245
246
  if (nil != keyNames && keyNames.count > 0) {
246
- NSPredicate *searchPredicate = [NSPredicate predicateWithBlock:^BOOL(XCElementSnapshot *snapshot, NSDictionary *bindings) {
247
+ NSPredicate *searchPredicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot, NSDictionary *bindings) {
247
248
  if (snapshot.elementType != XCUIElementTypeKey && snapshot.elementType != XCUIElementTypeButton) {
248
249
  return NO;
249
250
  }
@@ -40,6 +40,9 @@ static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd,
40
40
 
41
41
  @implementation XCUIApplicationProcess (FBQuiescence)
42
42
 
43
+ #pragma clang diagnostic push
44
+ #pragma clang diagnostic ignored "-Wobjc-load-method"
45
+
43
46
  + (void)load
44
47
  {
45
48
  Method waitForQuiescenceIncludingAnimationsIdleMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:));
@@ -51,6 +54,8 @@ static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd,
51
54
  }
52
55
  }
53
56
 
57
+ #pragma clang diagnostic pop
58
+
54
59
  static char XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE;
55
60
 
56
61
  @dynamic fb_shouldWaitForQuiescence;
@@ -11,7 +11,6 @@
11
11
 
12
12
  #import "XCUICoordinate.h"
13
13
  #import "XCUIElement+FBUtilities.h"
14
- #import "XCElementSnapshot+FBHitPoint.h"
15
14
 
16
15
  # if !TARGET_OS_TV
17
16
  @implementation XCUICoordinate (FBFix)
@@ -19,9 +19,9 @@
19
19
  #import "FBMacros.h"
20
20
  #import "FBMathUtils.h"
21
21
  #import "FBScreenshot.h"
22
+ #import "FBXCDeviceEvent.h"
22
23
  #import "FBXCodeCompatibility.h"
23
24
  #import "XCUIDevice.h"
24
- #import "XCDeviceEvent.h"
25
25
 
26
26
  static const NSTimeInterval FBHomeButtonCoolOffTime = 1.;
27
27
  static const NSTimeInterval FBScreenLockTimeout = 5.;
@@ -30,11 +30,16 @@ static const NSTimeInterval FBScreenLockTimeout = 5.;
30
30
 
31
31
  static bool fb_isLocked;
32
32
 
33
+ #pragma clang diagnostic push
34
+ #pragma clang diagnostic ignored "-Wobjc-load-method"
35
+
33
36
  + (void)load
34
37
  {
35
38
  [self fb_registerAppforDetectLockState];
36
39
  }
37
40
 
41
+ #pragma clang diagnostic pop
42
+
38
43
  + (void)fb_registerAppforDetectLockState
39
44
  {
40
45
  int notify_token;
@@ -303,10 +308,8 @@ static bool fb_isLocked;
303
308
  duration:(NSTimeInterval)duration
304
309
  error:(NSError **)error
305
310
  {
306
- XCDeviceEvent *event = [XCDeviceEvent deviceEventWithPage:page
307
- usage:usage
308
- duration:duration];
309
- return [self performDeviceEvent:event error:error];
311
+ id<FBXCDeviceEvent> event = FBCreateXCDeviceEvent(page, usage, duration, error);
312
+ return nil == event ? NO : [self performDeviceEvent:event error:error];
310
313
  }
311
314
 
312
315
  - (BOOL)fb_setAppearance:(FBUIInterfaceAppearance)appearance error:(NSError **)error
@@ -7,8 +7,8 @@
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
10
  #import <WebDriverAgentLib/XCUIElement.h>
11
+ #import "FBXCElementSnapshotWrapper.h"
12
12
 
13
13
  NS_ASSUME_NONNULL_BEGIN
14
14
 
@@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
20
20
  @end
21
21
 
22
22
 
23
- @interface XCElementSnapshot (FBAccessibility)
23
+ @interface FBXCElementSnapshotWrapper (FBAccessibility)
24
24
 
25
25
  /*! Whether or not the element in snapshot is accessible */
26
26
  @property (atomic, readonly) BOOL fb_isAccessibilityElement;
@@ -10,21 +10,22 @@
10
10
  #import "XCUIElement+FBAccessibility.h"
11
11
 
12
12
  #import "FBConfiguration.h"
13
- #import "XCElementSnapshot+FBHelpers.h"
14
13
  #import "XCTestPrivateSymbols.h"
15
14
  #import "XCUIElement+FBUtilities.h"
15
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
16
16
 
17
17
  @implementation XCUIElement (FBAccessibility)
18
18
 
19
19
  - (BOOL)fb_isAccessibilityElement
20
20
  {
21
- return [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName]
22
- maxDepth:@1].fb_isAccessibilityElement;
21
+ id<FBXCElementSnapshot> snapshot = [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName]
22
+ maxDepth:@1];
23
+ return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isAccessibilityElement;
23
24
  }
24
25
 
25
26
  @end
26
27
 
27
- @implementation XCElementSnapshot (FBAccessibility)
28
+ @implementation FBXCElementSnapshotWrapper (FBAccessibility)
28
29
 
29
30
  - (BOOL)fb_isAccessibilityElement
30
31
  {
@@ -11,6 +11,7 @@
11
11
 
12
12
  #import <objc/runtime.h>
13
13
 
14
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
14
15
  #import "XCUIElement+FBWebDriverAttributes.h"
15
16
  #import "XCUIElement+FBUtilities.h"
16
17
  #import "XCUIElement+FBUID.h"
@@ -46,8 +47,8 @@ static char XCUIELEMENT_CACHE_ID_KEY;
46
47
  if ([self isKindOfClass:XCUIApplication.class]) {
47
48
  uid = self.fb_uid;
48
49
  } else {
49
- XCElementSnapshot *snapshot = self.fb_cachedSnapshot ?: self.fb_takeSnapshot;
50
- uid = snapshot.wdUID;
50
+ id<FBXCElementSnapshot> snapshot = self.fb_cachedSnapshot ?: self.fb_takeSnapshot;
51
+ uid = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].wdUID;
51
52
  }
52
53
 
53
54
  objc_setAssociatedObject(self, &XCUIELEMENT_CACHE_ID_KEY, uid, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
@@ -12,10 +12,8 @@
12
12
 
13
13
  #import "FBMacros.h"
14
14
  #import "FBElementTypeTransformer.h"
15
- #import "FBPredicate.h"
16
15
  #import "NSPredicate+FBFormat.h"
17
- #import "XCElementSnapshot.h"
18
- #import "XCElementSnapshot+FBHelpers.h"
16
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
19
17
  #import "FBXCodeCompatibility.h"
20
18
  #import "XCUIElement+FBCaching.h"
21
19
  #import "XCUIElement+FBUtilities.h"
@@ -37,7 +35,7 @@
37
35
  return matchedElement ? @[matchedElement] : @[];
38
36
  }
39
37
 
40
- - (XCElementSnapshot *)fb_cachedSnapshotWithQuery:(XCUIElementQuery *)query
38
+ - (id<FBXCElementSnapshot>)fb_cachedSnapshotWithQuery:(XCUIElementQuery *)query
41
39
  {
42
40
  return [self isKindOfClass:XCUIApplication.class] ? query.rootElementSnapshot : self.fb_cachedSnapshot;
43
41
  }
@@ -51,7 +49,7 @@
51
49
  XCUIElementQuery *query = [self.fb_query descendantsMatchingType:type];
52
50
  NSMutableArray *result = [NSMutableArray array];
53
51
  [result addObjectsFromArray:[self.class fb_extractMatchingElementsFromQuery:query shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch]];
54
- XCElementSnapshot *cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
52
+ id<FBXCElementSnapshot> cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
55
53
  if (type == XCUIElementTypeAny || cachedSnapshot.elementType == type) {
56
54
  if (shouldReturnAfterFirstMatch || result.count == 0) {
57
55
  return @[self];
@@ -73,7 +71,9 @@
73
71
  return elements;
74
72
  }
75
73
 
76
- - (void)descendantsWithProperty:(NSString *)property value:(NSString *)value partial:(BOOL)partialSearch results:(NSMutableArray<XCUIElement *> *)results
74
+ - (void)descendantsWithProperty:(NSString *)property value:(NSString *)value
75
+ partial:(BOOL)partialSearch
76
+ results:(NSMutableArray<XCUIElement *> *)results
77
77
  {
78
78
  if (partialSearch) {
79
79
  NSString *text = [self fb_valueForWDAttributeName:property];
@@ -88,12 +88,12 @@
88
88
  }
89
89
 
90
90
  property = [FBElementUtils wdAttributeNameForAttributeName:property];
91
- value = [value stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
92
- NSString *operation = partialSearch ?
93
- [NSString stringWithFormat:@"%@ like '*%@*'", property, value] :
94
- [NSString stringWithFormat:@"%@ == '%@'", property, value];
95
-
96
- NSPredicate *predicate = [FBPredicate predicateWithFormat:operation];
91
+ NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot,
92
+ NSDictionary<NSString *,id> * _Nullable bindings) {
93
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
94
+ NSString *propertyValue = [NSString stringWithFormat:@"%@", [wrappedSnapshot fb_valueForWDAttributeName:property]];
95
+ return partialSearch ? [value containsString:propertyValue] : [value isEqualToString:propertyValue];
96
+ }];
97
97
  XCUIElementQuery *query = [[self.fb_query descendantsMatchingType:XCUIElementTypeAny] matchingPredicate:predicate];
98
98
  NSArray *childElements = query.fb_allMatches;
99
99
  [results addObjectsFromArray:childElements];
@@ -105,12 +105,12 @@
105
105
  - (NSArray<XCUIElement *> *)fb_descendantsMatchingPredicate:(NSPredicate *)predicate
106
106
  shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch
107
107
  {
108
- NSPredicate *formattedPredicate = [NSPredicate fb_formatSearchPredicate:predicate];
108
+ NSPredicate *formattedPredicate = [NSPredicate fb_snapshotBlockPredicateWithPredicate:predicate];
109
109
  XCUIElementQuery *query = [[self.fb_query descendantsMatchingType:XCUIElementTypeAny] matchingPredicate:formattedPredicate];
110
110
  NSMutableArray<XCUIElement *> *result = [NSMutableArray array];
111
111
  [result addObjectsFromArray:[self.class fb_extractMatchingElementsFromQuery:query
112
112
  shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch]];
113
- XCElementSnapshot *cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
113
+ id<FBXCElementSnapshot> cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
114
114
  // Include self element into predicate search
115
115
  if ([formattedPredicate evaluateWithObject:cachedSnapshot]) {
116
116
  if (shouldReturnAfterFirstMatch || result.count == 0) {
@@ -129,16 +129,16 @@
129
129
  {
130
130
  // XPath will try to match elements only class name, so requesting elements by XCUIElementTypeAny will not work. We should use '*' instead.
131
131
  xpathQuery = [xpathQuery stringByReplacingOccurrencesOfString:@"XCUIElementTypeAny" withString:@"*"];
132
- NSArray<XCElementSnapshot *> *matchingSnapshots = [FBXPath matchesWithRootElement:self forQuery:xpathQuery];
132
+ NSArray<id<FBXCElementSnapshot>> *matchingSnapshots = [FBXPath matchesWithRootElement:self forQuery:xpathQuery];
133
133
  if (0 == [matchingSnapshots count]) {
134
134
  return @[];
135
135
  }
136
136
  if (shouldReturnAfterFirstMatch) {
137
- XCElementSnapshot *snapshot = matchingSnapshots.firstObject;
137
+ id<FBXCElementSnapshot> snapshot = matchingSnapshots.firstObject;
138
138
  matchingSnapshots = @[snapshot];
139
139
  }
140
140
  return [self fb_filterDescendantsWithSnapshots:matchingSnapshots
141
- selfUID:self.lastSnapshot.wdUID
141
+ selfUID:[FBXCElementSnapshotWrapper ensureWrapped:self.lastSnapshot].wdUID
142
142
  onlyChildren:NO];
143
143
  }
144
144
 
@@ -148,7 +148,11 @@
148
148
  - (NSArray<XCUIElement *> *)fb_descendantsMatchingIdentifier:(NSString *)accessibilityId
149
149
  shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch
150
150
  {
151
- NSPredicate *predicate = [FBPredicate predicateWithFormat:@"name == %@", accessibilityId];
151
+ NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot,
152
+ NSDictionary<NSString *,id> * _Nullable bindings) {
153
+ FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
154
+ return [wrappedSnapshot.wdName isEqualToString:accessibilityId];
155
+ }];
152
156
  return [self fb_descendantsMatchingPredicate:predicate
153
157
  shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
154
158
  }
@@ -7,8 +7,7 @@
7
7
  * of patent rights can be found in the PATENTS file in the same directory.
8
8
  */
9
9
 
10
- #import <WebDriverAgentLib/XCElementSnapshot.h>
11
- #import <WebDriverAgentLib/XCUIElement.h>
10
+ #import "FBXCElementSnapshotWrapper.h"
12
11
 
13
12
  NS_ASSUME_NONNULL_BEGIN
14
13
 
@@ -20,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
20
19
  @end
21
20
 
22
21
 
23
- @interface XCElementSnapshot (FBIsVisible)
22
+ @interface FBXCElementSnapshotWrapper (FBIsVisible)
24
23
 
25
24
  /*! Whether or not the element is visible */
26
25
  @property (atomic, readonly) BOOL fb_isVisible;
@@ -14,10 +14,9 @@
14
14
  #import "FBMathUtils.h"
15
15
  #import "FBActiveAppDetectionPoint.h"
16
16
  #import "FBSession.h"
17
+ #import "FBXCAccessibilityElement.h"
17
18
  #import "FBXCodeCompatibility.h"
18
- #import "XCAccessibilityElement+FBComparison.h"
19
- #import "XCElementSnapshot+FBHelpers.h"
20
- #import "XCElementSnapshot+FBHitPoint.h"
19
+ #import "FBXCElementSnapshotWrapper+Helpers.h"
21
20
  #import "XCUIElement+FBUtilities.h"
22
21
  #import "XCUIElement+FBUID.h"
23
22
  #import "XCTestPrivateSymbols.h"
@@ -26,13 +25,14 @@
26
25
 
27
26
  - (BOOL)fb_isVisible
28
27
  {
29
- return [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName]
30
- maxDepth:@1].fb_isVisible;
28
+ id<FBXCElementSnapshot> snapshot = [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName]
29
+ maxDepth:@1];
30
+ return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isVisible;
31
31
  }
32
32
 
33
33
  @end
34
34
 
35
- @implementation XCElementSnapshot (FBIsVisible)
35
+ @implementation FBXCElementSnapshotWrapper (FBIsVisible)
36
36
 
37
37
  - (NSString *)fb_uniqId
38
38
  {
@@ -57,7 +57,7 @@
57
57
  }
58
58
 
59
59
  - (BOOL)fb_cacheVisibilityWithValue:(BOOL)isVisible
60
- forAncestors:(nullable NSArray<XCElementSnapshot *> *)ancestors
60
+ forAncestors:(nullable NSArray<id<FBXCElementSnapshot>> *)ancestors
61
61
  {
62
62
  NSMutableDictionary *cache = FBSession.activeSession.elementsVisibilityCache;
63
63
  if (nil == cache) {
@@ -72,8 +72,8 @@
72
72
  [destination setObject:visibleObj forKey:self.fb_uniqId];
73
73
  if (isVisible && nil != ancestors) {
74
74
  // if an element is visible then all its ancestors must be visible as well
75
- for (XCElementSnapshot *ancestor in ancestors) {
76
- NSString *ancestorId = ancestor.fb_uniqId;
75
+ for (id<FBXCElementSnapshot> ancestor in ancestors) {
76
+ NSString *ancestorId = [FBXCElementSnapshotWrapper ensureWrapped:ancestor].fb_uniqId;
77
77
  if (nil == [destination objectForKey:ancestorId]) {
78
78
  [destination setObject:visibleObj forKey:ancestorId];
79
79
  }
@@ -82,17 +82,17 @@
82
82
  return isVisible;
83
83
  }
84
84
 
85
- - (CGRect)fb_frameInContainer:(XCElementSnapshot *)container
85
+ - (CGRect)fb_frameInContainer:(id<FBXCElementSnapshot>)container
86
86
  hierarchyIntersection:(nullable NSValue *)intersectionRectange
87
87
  {
88
88
  CGRect currentRectangle = nil == intersectionRectange ? self.frame : [intersectionRectange CGRectValue];
89
- XCElementSnapshot *parent = self.parent;
89
+ id<FBXCElementSnapshot> parent = self.parent;
90
90
  CGRect parentFrame = parent.frame;
91
91
  CGRect containerFrame = container.frame;
92
92
  if (CGSizeEqualToSize(parentFrame.size, CGSizeZero) &&
93
93
  CGPointEqualToPoint(parentFrame.origin, CGPointZero)) {
94
94
  // Special case (or XCTest bug). Shift the origin and return immediately after shift
95
- XCElementSnapshot *nextParent = parent.parent;
95
+ id<FBXCElementSnapshot> nextParent = parent.parent;
96
96
  BOOL isGrandparent = YES;
97
97
  while (nextParent && nextParent != container) {
98
98
  CGRect nextParentFrame = nextParent.frame;
@@ -133,18 +133,19 @@
133
133
  if (CGRectIsEmpty(intersectionWithParent) || parent == container) {
134
134
  return intersectionWithParent;
135
135
  }
136
- return [parent fb_frameInContainer:container hierarchyIntersection:[NSValue valueWithCGRect:intersectionWithParent]];
136
+ return [[FBXCElementSnapshotWrapper ensureWrapped:parent] fb_frameInContainer:container
137
+ hierarchyIntersection:[NSValue valueWithCGRect:intersectionWithParent]];
137
138
  }
138
139
 
139
140
  - (BOOL)fb_hasAnyVisibleLeafs
140
141
  {
141
- NSArray<XCElementSnapshot *> *children = self.children;
142
+ NSArray<id<FBXCElementSnapshot>> *children = self.children;
142
143
  if (0 == children.count) {
143
144
  return self.fb_isVisible;
144
145
  }
145
146
 
146
- for (XCElementSnapshot *child in children) {
147
- if (child.fb_hasAnyVisibleLeafs) {
147
+ for (id<FBXCElementSnapshot> child in children) {
148
+ if ([FBXCElementSnapshotWrapper ensureWrapped:child].fb_hasAnyVisibleLeafs) {
148
149
  return YES;
149
150
  }
150
151
  }
@@ -169,13 +170,13 @@
169
170
  return [self fb_cacheVisibilityWithValue:NO forAncestors:nil];
170
171
  }
171
172
 
172
- NSArray<XCElementSnapshot *> *ancestors = self.fb_ancestors;
173
+ NSArray<id<FBXCElementSnapshot>> *ancestors = self.fb_ancestors;
173
174
  if ([FBConfiguration shouldUseTestManagerForVisibilityDetection]) {
174
175
  BOOL visibleAttrValue = [(NSNumber *)[self fb_attributeValue:FB_XCAXAIsVisibleAttributeName] boolValue];
175
176
  return [self fb_cacheVisibilityWithValue:visibleAttrValue forAncestors:ancestors];
176
177
  }
177
178
 
178
- XCElementSnapshot *parentWindow = ancestors.count > 1 ? [ancestors objectAtIndex:ancestors.count - 2] : nil;
179
+ id<FBXCElementSnapshot> parentWindow = ancestors.count > 1 ? [ancestors objectAtIndex:ancestors.count - 2] : nil;
179
180
  CGRect visibleRect = selfFrame;
180
181
  if (nil != parentWindow) {
181
182
  visibleRect = [self fb_frameInContainer:parentWindow hierarchyIntersection:nil];
@@ -186,7 +187,7 @@
186
187
  CGPoint midPoint = CGPointMake(visibleRect.origin.x + visibleRect.size.width / 2,
187
188
  visibleRect.origin.y + visibleRect.size.height / 2);
188
189
  #if !TARGET_OS_TV // TV has no orientation, so it does not need to coordinate
189
- XCElementSnapshot *appElement = ancestors.count > 0 ? [ancestors lastObject] : self;
190
+ id<FBXCElementSnapshot> appElement = ancestors.count > 0 ? [ancestors lastObject] : self;
190
191
  CGRect appFrame = appElement.frame;
191
192
  CGRect windowFrame = nil == parentWindow ? selfFrame : parentWindow.frame;
192
193
  if ((appFrame.size.height > appFrame.size.width && windowFrame.size.height < windowFrame.size.width) ||
@@ -197,22 +198,23 @@
197
198
  midPoint = FBInvertPointForApplication(midPoint, appFrame.size, FBApplication.fb_activeApplication.interfaceOrientation);
198
199
  }
199
200
  #endif
200
- XCAccessibilityElement *hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint];
201
+ id<FBXCAccessibilityElement> hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint];
201
202
  if (nil != hitElement) {
202
- if ([self.accessibilityElement fb_isEqualToElement:hitElement]) {
203
+ if (FBIsAXElementEqualToOther(self.accessibilityElement, hitElement)) {
203
204
  return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors];
204
205
  }
205
- for (XCElementSnapshot *ancestor in ancestors) {
206
- if ([hitElement fb_isEqualToElement:ancestor.accessibilityElement]) {
206
+ for (id<FBXCElementSnapshot> ancestor in ancestors) {
207
+ if (FBIsAXElementEqualToOther(hitElement, ancestor.accessibilityElement)) {
207
208
  return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors];
208
209
  }
209
210
  }
210
211
  }
211
212
  if (self.children.count > 0) {
212
213
  if (nil != hitElement) {
213
- for (XCElementSnapshot *descendant in self._allDescendants) {
214
- if ([hitElement fb_isEqualToElement:descendant.accessibilityElement]) {
215
- return [self fb_cacheVisibilityWithValue:YES forAncestors:descendant.fb_ancestors];
214
+ for (id<FBXCElementSnapshot> descendant in self._allDescendants) {
215
+ if (FBIsAXElementEqualToOther(hitElement, descendant.accessibilityElement)) {
216
+ return [self fb_cacheVisibilityWithValue:YES
217
+ forAncestors:[FBXCElementSnapshotWrapper ensureWrapped:descendant].fb_ancestors];
216
218
  }
217
219
  }
218
220
  }
@@ -10,6 +10,7 @@
10
10
  #import "XCUIElement+FBPickerWheel.h"
11
11
 
12
12
  #import "FBRunLoopSpinner.h"
13
+ #import "FBXCElementSnapshot.h"
13
14
  #import "FBXCodeCompatibility.h"
14
15
  #import "XCUIApplication+FBTouchAction.h"
15
16
  #import "XCUICoordinate.h"
@@ -23,7 +24,7 @@ static const NSTimeInterval VALUE_CHANGE_TIMEOUT = 2;
23
24
 
24
25
  - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)error
25
26
  {
26
- XCElementSnapshot *snapshot = self.fb_isResolvedFromCache.boolValue
27
+ id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
27
28
  ? self.lastSnapshot
28
29
  : self.fb_takeSnapshot;
29
30
  NSString *previousValue = snapshot.value;
@@ -41,11 +41,15 @@ static char XCUIELEMENT_IS_RESOLVED_NATIVELY_KEY;
41
41
  XCUIElementQuery *query = [self isKindOfClass:XCUIApplication.class]
42
42
  ? self.application.fb_query
43
43
  : [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny];
44
- XCElementSnapshot *cachedSnapshot = self.fb_cachedSnapshot;
44
+ FBXCElementSnapshotWrapper *cachedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:self.fb_cachedSnapshot];
45
45
  NSString *uid = nil == cachedSnapshot ? self.fb_uid : cachedSnapshot.fb_uid;
46
- return nil == uid
47
- ? self
48
- : [query matchingPredicate:[NSPredicate predicateWithFormat:@"%K = %@", FBStringify(XCUIElement, wdUID), uid]].fb_firstMatch;
46
+ if (nil == uid) {
47
+ return self;
48
+ }
49
+ NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot, NSDictionary *bindings) {
50
+ return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_uid isEqualToString:uid];
51
+ }];
52
+ return (XCUIElement *)[query matchingPredicate:predicate].fb_firstMatch;
49
53
  }
50
54
 
51
55
  @end