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.
- package/PrivateHeaders/XCTest/XCAXClient_iOS.h +2 -4
- package/PrivateHeaders/XCTest/XCActivityRecord.h +3 -3
- package/PrivateHeaders/XCTest/XCApplicationQuery.h +3 -3
- package/PrivateHeaders/XCTest/XCTElementSetTransformer-Protocol.h +2 -2
- package/PrivateHeaders/XCTest/XCTRunnerDaemonSession.h +1 -1
- package/PrivateHeaders/XCTest/XCTestManager_IDEInterface-Protocol.h +5 -5
- package/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +8 -8
- package/PrivateHeaders/XCTest/XCUIApplication.h +2 -2
- package/PrivateHeaders/XCTest/XCUIApplicationImpl.h +2 -2
- package/PrivateHeaders/XCTest/XCUIApplicationProcess.h +3 -5
- package/PrivateHeaders/XCTest/XCUIElement.h +3 -3
- package/PrivateHeaders/XCTest/XCUIElementQuery.h +4 -4
- package/PrivateHeaders/XCTest/XCUIRecorderNodeFinder.h +3 -3
- package/PrivateHeaders/XCTest/XCUIRecorderUtilities.h +3 -3
- package/Scripts/build.sh +3 -6
- package/WebDriverAgent.xcodeproj/project.pbxproj +66 -70
- package/WebDriverAgent.xcodeproj/project.xcworkspace/xcuserdata/elf.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +91 -0
- package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcschemes/xcschememanagement.plist +59 -0
- package/WebDriverAgentLib/Categories/{XCElementSnapshot+FBHelpers.h → FBXCElementSnapshotWrapper+Helpers.h} +18 -11
- package/WebDriverAgentLib/Categories/{XCElementSnapshot+FBHelpers.m → FBXCElementSnapshotWrapper+Helpers.m} +57 -39
- package/WebDriverAgentLib/Categories/NSExpression+FBFormat.m +8 -3
- package/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +8 -7
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +2 -2
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +29 -28
- package/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m +5 -0
- package/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m +0 -1
- package/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +8 -5
- package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h +2 -2
- package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m +5 -4
- package/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +3 -2
- package/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +22 -18
- package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h +2 -3
- package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +28 -26
- package/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +2 -1
- package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +8 -4
- package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +73 -51
- package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +11 -10
- package/WebDriverAgentLib/Categories/XCUIElement+FBUID.h +10 -5
- package/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +15 -3
- package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +7 -7
- package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +29 -20
- package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h +2 -2
- package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +16 -13
- package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h +2 -3
- package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m +3 -3
- package/WebDriverAgentLib/Commands/FBElementCommands.m +15 -14
- package/WebDriverAgentLib/Commands/FBFindElementCommands.m +5 -6
- package/WebDriverAgentLib/FBAlert.m +16 -13
- package/WebDriverAgentLib/FBApplication.m +8 -8
- package/WebDriverAgentLib/Routing/FBElementUtils.h +11 -2
- package/WebDriverAgentLib/Routing/FBElementUtils.m +15 -12
- package/WebDriverAgentLib/Routing/FBResponsePayload.m +11 -10
- package/WebDriverAgentLib/Routing/FBSession.m +1 -1
- package/{PrivateHeaders/XCTest/XCAccessibilityElement.h → WebDriverAgentLib/Routing/FBXCAccessibilityElement.h} +19 -18
- package/WebDriverAgentLib/{Categories/XCAccessibilityElement+FBComparison.m → Routing/FBXCAccessibilityElement.m} +5 -11
- package/WebDriverAgentLib/Routing/FBXCDeviceEvent.h +35 -0
- package/WebDriverAgentLib/Routing/FBXCDeviceEvent.m +43 -0
- package/{PrivateHeaders/XCTest/XCElementSnapshot.h → WebDriverAgentLib/Routing/FBXCElementSnapshot.h} +25 -44
- package/WebDriverAgentLib/Routing/FBXCElementSnapshot.m +10 -0
- package/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h +30 -0
- package/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m +45 -0
- package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h +3 -4
- package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m +4 -4
- package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +2 -2
- package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +7 -8
- package/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m +1 -2
- package/WebDriverAgentLib/Utilities/FBConfiguration.m +0 -1
- package/WebDriverAgentLib/Utilities/FBImageIOScaler.m +3 -0
- package/WebDriverAgentLib/Utilities/FBKeyboard.m +1 -2
- package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +1 -1
- package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +3 -3
- package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +10 -9
- package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +14 -8
- package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +0 -1
- package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +6 -0
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +0 -10
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +0 -24
- package/WebDriverAgentLib/Utilities/FBXPath-Private.h +1 -1
- package/WebDriverAgentLib/Utilities/FBXPath.h +3 -3
- package/WebDriverAgentLib/Utilities/FBXPath.m +15 -13
- package/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.h +14 -1
- package/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m +18 -9
- package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +9 -3
- package/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m +7 -1
- package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +7 -1
- package/WebDriverAgentLib/WebDriverAgentLib.h +0 -1
- package/WebDriverAgentRunner-Runner.app.zip +0 -0
- package/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +26 -19
- package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m +24 -29
- package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m +2 -2
- package/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +5 -3
- package/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +2 -1
- package/{WebDriverAgentLib/Categories/XCElementSnapshot+FBHitPoint.h → WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.h} +3 -14
- package/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +99 -0
- package/WebDriverAgentTests/UnitTests/FBXPathTests.m +21 -13
- package/WebDriverAgentTests/UnitTests/NSPredicateFBFormatTests.m +4 -5
- package/package.json +1 -1
- package/WebDriverAgentLib/Categories/XCAccessibilityElement+FBComparison.h +0 -27
- package/WebDriverAgentLib/Categories/XCElementSnapshot+FBHitPoint.m +0 -29
- package/WebDriverAgentLib/Utilities/FBPredicate.h +0 -28
- 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
|
|
43
|
+
int currentProcessIdentifier = [self.accessibilityElement processIdentifier];
|
|
45
44
|
BOOL result = [[[FBRunLoopSpinner new]
|
|
46
45
|
timeout:timeout]
|
|
47
46
|
spinUntilTrue:^BOOL{
|
|
48
|
-
|
|
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<
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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:(
|
|
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
|
-
|
|
123
|
-
info[@"
|
|
124
|
-
info[@"
|
|
125
|
-
info[@"
|
|
126
|
-
info[@"
|
|
127
|
-
info[@"
|
|
128
|
-
info[@"
|
|
129
|
-
info[@"
|
|
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"] = [@([
|
|
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 (
|
|
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:(
|
|
148
|
+
+ (NSDictionary *)accessibilityInfoForElement:(id<FBXCElementSnapshot>)snapshot
|
|
149
149
|
{
|
|
150
|
-
|
|
151
|
-
BOOL
|
|
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(
|
|
158
|
-
info[@"label"] = FBValueOrNull(
|
|
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 (
|
|
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(
|
|
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(
|
|
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;
|
|
@@ -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
|
-
|
|
307
|
-
|
|
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
|
|
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
|
-
|
|
22
|
-
|
|
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
|
|
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
|
-
|
|
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 "
|
|
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
|
-
- (
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
|
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
|
-
|
|
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<
|
|
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
|
-
|
|
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 = [
|
|
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
|
|
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
|
|
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 "
|
|
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
|
-
|
|
30
|
-
|
|
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
|
|
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<
|
|
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 (
|
|
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:(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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<
|
|
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 (
|
|
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<
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
201
|
+
id<FBXCAccessibilityElement> hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint];
|
|
201
202
|
if (nil != hitElement) {
|
|
202
|
-
if (
|
|
203
|
+
if (FBIsAXElementEqualToOther(self.accessibilityElement, hitElement)) {
|
|
203
204
|
return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors];
|
|
204
205
|
}
|
|
205
|
-
for (
|
|
206
|
-
if (
|
|
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 (
|
|
214
|
-
if (
|
|
215
|
-
return [self fb_cacheVisibilityWithValue:YES
|
|
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
|
-
|
|
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
|
-
|
|
44
|
+
FBXCElementSnapshotWrapper *cachedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:self.fb_cachedSnapshot];
|
|
45
45
|
NSString *uid = nil == cachedSnapshot ? self.fb_uid : cachedSnapshot.fb_uid;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|