appium-webdriveragent 4.7.0 → 4.8.2
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/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 +17 -14
- package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h +2 -3
- package/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m +3 -3
- package/WebDriverAgentLib/Commands/FBElementCommands.m +17 -15
- 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/FBPasteboard.m +91 -3
- 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/FBPasteboardTests.m +1 -5
- 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
|
@@ -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
|
|
@@ -13,12 +13,11 @@
|
|
|
13
13
|
#import "FBLogger.h"
|
|
14
14
|
#import "FBMacros.h"
|
|
15
15
|
#import "FBMathUtils.h"
|
|
16
|
-
#import "FBPredicate.h"
|
|
17
16
|
#import "FBXCodeCompatibility.h"
|
|
17
|
+
#import "FBXCElementSnapshotWrapper.h"
|
|
18
|
+
#import "FBXCElementSnapshotWrapper+Helpers.h"
|
|
18
19
|
#import "XCUIApplication+FBTouchAction.h"
|
|
19
20
|
#import "XCUIElement+FBCaching.h"
|
|
20
|
-
#import "XCElementSnapshot+FBHelpers.h"
|
|
21
|
-
#import "XCElementSnapshot.h"
|
|
22
21
|
#import "XCUIApplication.h"
|
|
23
22
|
#import "XCUICoordinate.h"
|
|
24
23
|
#import "XCUICoordinate+FBFix.h"
|
|
@@ -34,7 +33,7 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
34
33
|
|
|
35
34
|
#if !TARGET_OS_TV
|
|
36
35
|
|
|
37
|
-
@interface
|
|
36
|
+
@interface FBXCElementSnapshotWrapper (FBScrolling)
|
|
38
37
|
|
|
39
38
|
- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application;
|
|
40
39
|
- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application;
|
|
@@ -49,7 +48,7 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
49
48
|
|
|
50
49
|
- (BOOL)fb_nativeScrollToVisibleWithError:(NSError **)error
|
|
51
50
|
{
|
|
52
|
-
|
|
51
|
+
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
|
|
53
52
|
? self.lastSnapshot
|
|
54
53
|
: self.fb_takeSnapshot;
|
|
55
54
|
return nil != [self _hitPointByAttemptingToScrollToVisibleSnapshot:snapshot
|
|
@@ -58,34 +57,38 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
58
57
|
|
|
59
58
|
- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance
|
|
60
59
|
{
|
|
61
|
-
|
|
60
|
+
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
|
|
62
61
|
? self.lastSnapshot
|
|
63
62
|
: self.fb_takeSnapshot;
|
|
64
|
-
[snapshot fb_scrollUpByNormalizedDistance:distance
|
|
63
|
+
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollUpByNormalizedDistance:distance
|
|
64
|
+
inApplication:self.application];
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance
|
|
68
68
|
{
|
|
69
|
-
|
|
69
|
+
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
|
|
70
70
|
? self.lastSnapshot
|
|
71
71
|
: self.fb_takeSnapshot;
|
|
72
|
-
[snapshot fb_scrollDownByNormalizedDistance:distance
|
|
72
|
+
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollDownByNormalizedDistance:distance
|
|
73
|
+
inApplication:self.application];
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance
|
|
76
77
|
{
|
|
77
|
-
|
|
78
|
+
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
|
|
78
79
|
? self.lastSnapshot
|
|
79
80
|
: self.fb_takeSnapshot;
|
|
80
|
-
[snapshot fb_scrollLeftByNormalizedDistance:distance
|
|
81
|
+
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollLeftByNormalizedDistance:distance
|
|
82
|
+
inApplication:self.application];
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance
|
|
84
86
|
{
|
|
85
|
-
|
|
87
|
+
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
|
|
86
88
|
? self.lastSnapshot
|
|
87
89
|
: self.fb_takeSnapshot;
|
|
88
|
-
[snapshot fb_scrollRightByNormalizedDistance:distance
|
|
90
|
+
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollRightByNormalizedDistance:distance
|
|
91
|
+
inApplication:self.application];
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
- (BOOL)fb_scrollToVisibleWithError:(NSError **)error
|
|
@@ -100,9 +103,11 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
100
103
|
error:error];
|
|
101
104
|
}
|
|
102
105
|
|
|
103
|
-
- (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance
|
|
106
|
+
- (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance
|
|
107
|
+
scrollDirection:(FBXCUIElementScrollDirection)scrollDirection
|
|
108
|
+
error:(NSError **)error
|
|
104
109
|
{
|
|
105
|
-
|
|
110
|
+
FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]];
|
|
106
111
|
if (prescrollSnapshot.isWDVisible) {
|
|
107
112
|
return YES;
|
|
108
113
|
}
|
|
@@ -118,23 +123,30 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
118
123
|
];
|
|
119
124
|
});
|
|
120
125
|
|
|
121
|
-
__block NSArray<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
__block NSArray<id<FBXCElementSnapshot>> *cellSnapshots;
|
|
127
|
+
__block NSMutableArray<id<FBXCElementSnapshot>> *visibleCellSnapshots = [NSMutableArray new];
|
|
128
|
+
id<FBXCElementSnapshot> scrollView = [prescrollSnapshot fb_parentMatchingOneOfTypes:acceptedParents
|
|
129
|
+
filter:^(id<FBXCElementSnapshot> snapshot) {
|
|
130
|
+
FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
|
|
131
|
+
|
|
132
|
+
if (![wrappedSnapshot isWDVisible]) {
|
|
133
|
+
return NO;
|
|
134
|
+
}
|
|
130
135
|
|
|
131
|
-
|
|
136
|
+
cellSnapshots = [wrappedSnapshot fb_descendantsCellSnapshots];
|
|
137
|
+
|
|
138
|
+
for (id<FBXCElementSnapshot> cellSnapshot in cellSnapshots) {
|
|
139
|
+
FBXCElementSnapshotWrapper *wrappedCellSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:cellSnapshot];
|
|
140
|
+
if (wrappedCellSnapshot.wdVisible) {
|
|
141
|
+
[visibleCellSnapshots addObject:cellSnapshot];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
132
144
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
if (visibleCellSnapshots.count > 1) {
|
|
146
|
+
return YES;
|
|
147
|
+
}
|
|
148
|
+
return NO;
|
|
149
|
+
}];
|
|
138
150
|
|
|
139
151
|
if (scrollView == nil) {
|
|
140
152
|
return
|
|
@@ -143,20 +155,21 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
143
155
|
buildError:error];
|
|
144
156
|
}
|
|
145
157
|
|
|
146
|
-
|
|
147
|
-
|
|
158
|
+
id<FBXCElementSnapshot> targetCellSnapshot = [prescrollSnapshot fb_parentCellSnapshot];
|
|
159
|
+
id<FBXCElementSnapshot> lastSnapshot = visibleCellSnapshots.lastObject;
|
|
148
160
|
// Can't just do indexOfObject, because targetCellSnapshot may represent the same object represented by a member of cellSnapshots, yet be a different object
|
|
149
161
|
// than that member. This reflects the fact that targetCellSnapshot came out of self.fb_parentCellSnapshot, not out of cellSnapshots directly.
|
|
150
162
|
// If the result is NSNotFound, we'll just proceed by scrolling downward/rightward, since NSNotFound will always be larger than the current index.
|
|
151
|
-
NSUInteger targetCellIndex = [cellSnapshots indexOfObjectPassingTest:^BOOL(
|
|
163
|
+
NSUInteger targetCellIndex = [cellSnapshots indexOfObjectPassingTest:^BOOL(id<FBXCElementSnapshot> _Nonnull obj,
|
|
164
|
+
NSUInteger idx, BOOL *_Nonnull stop) {
|
|
152
165
|
return [obj _matchesElement:targetCellSnapshot];
|
|
153
166
|
}];
|
|
154
167
|
NSUInteger visibleCellIndex = [cellSnapshots indexOfObject:lastSnapshot];
|
|
155
168
|
|
|
156
169
|
if (scrollDirection == FBXCUIElementScrollDirectionUnknown) {
|
|
157
170
|
// Try to determine the scroll direction by determining the vector between the first and last visible cells
|
|
158
|
-
|
|
159
|
-
|
|
171
|
+
id<FBXCElementSnapshot> firstVisibleCell = visibleCellSnapshots.firstObject;
|
|
172
|
+
id<FBXCElementSnapshot> lastVisibleCell = visibleCellSnapshots.lastObject;
|
|
160
173
|
CGVector cellGrowthVector = CGVectorMake(firstVisibleCell.frame.origin.x - lastVisibleCell.frame.origin.x,
|
|
161
174
|
firstVisibleCell.frame.origin.y - lastVisibleCell.frame.origin.y
|
|
162
175
|
);
|
|
@@ -169,17 +182,22 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
169
182
|
|
|
170
183
|
const NSUInteger maxScrollCount = 25;
|
|
171
184
|
NSUInteger scrollCount = 0;
|
|
185
|
+
FBXCElementSnapshotWrapper *scrollViewWrapped = [FBXCElementSnapshotWrapper ensureWrapped:scrollView];
|
|
172
186
|
// Scrolling till cell is visible and get current value of frames
|
|
173
187
|
while (![self fb_isEquivalentElementSnapshotVisible:prescrollSnapshot] && scrollCount < maxScrollCount) {
|
|
174
188
|
if (targetCellIndex < visibleCellIndex) {
|
|
175
189
|
scrollDirection == FBXCUIElementScrollDirectionVertical ?
|
|
176
|
-
[
|
|
177
|
-
|
|
190
|
+
[scrollViewWrapped fb_scrollUpByNormalizedDistance:normalizedScrollDistance
|
|
191
|
+
inApplication:self.application] :
|
|
192
|
+
[scrollViewWrapped fb_scrollLeftByNormalizedDistance:normalizedScrollDistance
|
|
193
|
+
inApplication:self.application];
|
|
178
194
|
}
|
|
179
195
|
else {
|
|
180
196
|
scrollDirection == FBXCUIElementScrollDirectionVertical ?
|
|
181
|
-
[
|
|
182
|
-
|
|
197
|
+
[scrollViewWrapped fb_scrollDownByNormalizedDistance:normalizedScrollDistance
|
|
198
|
+
inApplication:self.application] :
|
|
199
|
+
[scrollViewWrapped fb_scrollRightByNormalizedDistance:normalizedScrollDistance
|
|
200
|
+
inApplication:self.application];
|
|
183
201
|
}
|
|
184
202
|
scrollCount++;
|
|
185
203
|
// Wait for scroll animation
|
|
@@ -196,28 +214,32 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
196
214
|
// Cell is now visible, but it might be only partialy visible, scrolling till whole frame is visible.
|
|
197
215
|
// Sometimes, attempting to grab the parent snapshot of the target cell after scrolling is complete causes a stale element reference exception.
|
|
198
216
|
// Trying fb_cachedSnapshot first
|
|
199
|
-
|
|
200
|
-
|
|
217
|
+
FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:([self fb_cachedSnapshot] ?: [self fb_takeSnapshot])];
|
|
218
|
+
targetCellSnapshot = [targetCellSnapshotWrapped fb_parentCellSnapshot];
|
|
219
|
+
CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].fb_visibleFrameWithFallback;
|
|
201
220
|
|
|
202
221
|
CGVector scrollVector = CGVectorMake(visibleFrame.size.width - targetCellSnapshot.frame.size.width,
|
|
203
222
|
visibleFrame.size.height - targetCellSnapshot.frame.size.height
|
|
204
223
|
);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
return YES;
|
|
224
|
+
return [scrollViewWrapped fb_scrollByVector:scrollVector
|
|
225
|
+
inApplication:self.application
|
|
226
|
+
error:error];
|
|
209
227
|
}
|
|
210
228
|
|
|
211
|
-
- (BOOL)fb_isEquivalentElementSnapshotVisible:(
|
|
229
|
+
- (BOOL)fb_isEquivalentElementSnapshotVisible:(id<FBXCElementSnapshot>)snapshot
|
|
212
230
|
{
|
|
213
|
-
|
|
231
|
+
FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
|
|
232
|
+
|
|
233
|
+
if (wrappedSnapshot.isWDVisible) {
|
|
214
234
|
return YES;
|
|
215
235
|
}
|
|
216
236
|
|
|
217
|
-
|
|
218
|
-
for (
|
|
237
|
+
id<FBXCElementSnapshot> appSnapshot = [self.application fb_takeSnapshot];
|
|
238
|
+
for (id<FBXCElementSnapshot> elementSnapshot in appSnapshot._allDescendants.copy) {
|
|
239
|
+
FBXCElementSnapshotWrapper *wrappedElementSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:elementSnapshot];
|
|
219
240
|
// We are comparing pre-scroll snapshot so frames are irrelevant.
|
|
220
|
-
if ([
|
|
241
|
+
if ([wrappedSnapshot fb_framelessFuzzyMatchesElement:elementSnapshot]
|
|
242
|
+
&& wrappedElementSnapshot.isWDVisible) {
|
|
221
243
|
return YES;
|
|
222
244
|
}
|
|
223
245
|
}
|
|
@@ -227,7 +249,7 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
227
249
|
@end
|
|
228
250
|
|
|
229
251
|
|
|
230
|
-
@implementation
|
|
252
|
+
@implementation FBXCElementSnapshotWrapper (FBScrolling)
|
|
231
253
|
|
|
232
254
|
- (CGRect)scrollingFrame
|
|
233
255
|
{
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
#import "FBErrorBuilder.h"
|
|
14
14
|
#import "FBKeyboard.h"
|
|
15
15
|
#import "NSString+FBVisualLength.h"
|
|
16
|
-
#import "
|
|
16
|
+
#import "FBXCElementSnapshotWrapper.h"
|
|
17
|
+
#import "FBXCElementSnapshotWrapper+Helpers.h"
|
|
17
18
|
#import "XCUIElement+FBCaching.h"
|
|
18
19
|
#import "XCUIElement+FBTap.h"
|
|
19
20
|
#import "XCUIElement+FBUtilities.h"
|
|
@@ -39,19 +40,19 @@
|
|
|
39
40
|
@end
|
|
40
41
|
|
|
41
42
|
|
|
42
|
-
@interface
|
|
43
|
+
@interface FBXCElementSnapshotWrapper (FBKeyboardFocus)
|
|
43
44
|
|
|
44
45
|
- (BOOL)fb_hasKeyboardFocus;
|
|
45
46
|
|
|
46
47
|
@end
|
|
47
48
|
|
|
48
|
-
@implementation
|
|
49
|
+
@implementation FBXCElementSnapshotWrapper (FBKeyboardFocus)
|
|
49
50
|
|
|
50
51
|
- (BOOL)fb_hasKeyboardFocus
|
|
51
52
|
{
|
|
52
53
|
// https://developer.apple.com/documentation/xctest/xcuielement/1500968-typetext?language=objc
|
|
53
54
|
// > The element or a descendant must have keyboard focus; otherwise an error is raised.
|
|
54
|
-
return self.hasKeyboardFocus || [self descendantsByFilteringWithBlock:^BOOL(
|
|
55
|
+
return self.hasKeyboardFocus || [self descendantsByFilteringWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot) {
|
|
55
56
|
return snapshot.hasKeyboardFocus;
|
|
56
57
|
}].count > 0;
|
|
57
58
|
}
|
|
@@ -61,7 +62,7 @@
|
|
|
61
62
|
|
|
62
63
|
@implementation XCUIElement (FBTyping)
|
|
63
64
|
|
|
64
|
-
- (void)fb_prepareForTextInputWithSnapshot:(
|
|
65
|
+
- (void)fb_prepareForTextInputWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot
|
|
65
66
|
{
|
|
66
67
|
if (snapshot.fb_hasKeyboardFocus) {
|
|
67
68
|
return;
|
|
@@ -92,10 +93,10 @@
|
|
|
92
93
|
frequency:(NSUInteger)frequency
|
|
93
94
|
error:(NSError **)error
|
|
94
95
|
{
|
|
95
|
-
|
|
96
|
+
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
|
|
96
97
|
? self.lastSnapshot
|
|
97
98
|
: self.fb_takeSnapshot;
|
|
98
|
-
[self fb_prepareForTextInputWithSnapshot:snapshot];
|
|
99
|
+
[self fb_prepareForTextInputWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot]];
|
|
99
100
|
if (shouldClear && ![self fb_clearTextWithSnapshot:self.lastSnapshot
|
|
100
101
|
shouldPrepareForInput:NO
|
|
101
102
|
error:error]) {
|
|
@@ -106,15 +107,15 @@
|
|
|
106
107
|
|
|
107
108
|
- (BOOL)fb_clearTextWithError:(NSError **)error
|
|
108
109
|
{
|
|
109
|
-
|
|
110
|
+
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
|
|
110
111
|
? self.lastSnapshot
|
|
111
112
|
: self.fb_takeSnapshot;
|
|
112
|
-
return [self fb_clearTextWithSnapshot:snapshot
|
|
113
|
+
return [self fb_clearTextWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot]
|
|
113
114
|
shouldPrepareForInput:YES
|
|
114
115
|
error:error];
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
- (BOOL)fb_clearTextWithSnapshot:(
|
|
118
|
+
- (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot
|
|
118
119
|
shouldPrepareForInput:(BOOL)shouldPrepareForInput
|
|
119
120
|
error:(NSError **)error
|
|
120
121
|
{
|