appium-webdriveragent 8.12.2 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +1 -0
- package/WebDriverAgent.xcodeproj/project.pbxproj +12 -0
- package/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.h +4 -9
- package/WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.m +13 -25
- package/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +2 -2
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +4 -20
- package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m +15 -4
- package/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h +0 -3
- package/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +1 -22
- package/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +1 -1
- package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +28 -173
- package/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +1 -3
- package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +33 -30
- package/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +4 -8
- package/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +2 -2
- package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +3 -36
- package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +10 -68
- package/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h +36 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m +53 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +7 -20
- package/WebDriverAgentLib/Commands/FBCustomCommands.m +2 -1
- package/WebDriverAgentLib/Commands/FBElementCommands.m +25 -47
- package/WebDriverAgentLib/Commands/FBFindElementCommands.m +10 -9
- package/WebDriverAgentLib/Commands/FBSessionCommands.m +0 -8
- package/WebDriverAgentLib/FBAlert.m +6 -5
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/Routing/FBElementCache.h +4 -10
- package/WebDriverAgentLib/Routing/FBElementCache.m +4 -33
- package/WebDriverAgentLib/Routing/FBResponsePayload.m +1 -7
- package/WebDriverAgentLib/Utilities/FBConfiguration.h +0 -8
- package/WebDriverAgentLib/Utilities/FBConfiguration.m +0 -12
- package/WebDriverAgentLib/Utilities/FBSettings.h +0 -3
- package/WebDriverAgentLib/Utilities/FBSettings.m +0 -2
- package/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +1 -3
- package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +1 -1
- package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +4 -3
- package/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +7 -11
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +3 -1
- package/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +2 -2
- package/WebDriverAgentLib/Utilities/FBXPath.m +1 -4
- package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h +3 -0
- package/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +1 -0
- package/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +2 -1
- package/WebDriverAgentTests/IntegrationTests/FBElementSwipingTests.m +1 -1
- package/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +1 -1
- package/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m +2 -2
- package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHelperTests.m +21 -10
- package/WebDriverAgentTests/IntegrationTests/XCElementSnapshotHitPointTests.m +1 -1
- package/WebDriverAgentTests/IntegrationTests/XCUIElementHelperIntegrationTests.m +5 -3
- package/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m +10 -0
- package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +1 -2
- package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +1 -1
- package/WebDriverAgentTests/UnitTests/FBElementCacheTests.m +0 -2
- package/WebDriverAgentTests/UnitTests_tvOS/Doubles/XCUIElementDouble.h +0 -1
- package/package.json +1 -1
|
@@ -20,9 +20,11 @@
|
|
|
20
20
|
#import "XCUIApplication.h"
|
|
21
21
|
#import "XCUICoordinate.h"
|
|
22
22
|
#import "XCUIElement+FBIsVisible.h"
|
|
23
|
+
#import "XCUIElement+FBVisibleFrame.h"
|
|
23
24
|
#import "XCUIElement.h"
|
|
24
25
|
#import "XCUIElement+FBUtilities.h"
|
|
25
26
|
#import "XCUIElement+FBWebDriverAttributes.h"
|
|
27
|
+
#import "XCTestPrivateSymbols.h"
|
|
26
28
|
|
|
27
29
|
const CGFloat FBFuzzyPointThreshold = 20.f; //Smallest determined value that is not interpreted as touch
|
|
28
30
|
const CGFloat FBScrollToVisibleNormalizedDistance = .5f;
|
|
@@ -47,45 +49,35 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
47
49
|
|
|
48
50
|
- (BOOL)fb_nativeScrollToVisibleWithError:(NSError **)error
|
|
49
51
|
{
|
|
50
|
-
id<FBXCElementSnapshot> snapshot = self
|
|
51
|
-
? self.lastSnapshot
|
|
52
|
-
: self.fb_takeSnapshot;
|
|
52
|
+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
|
|
53
53
|
return nil != [self _hitPointByAttemptingToScrollToVisibleSnapshot:snapshot
|
|
54
54
|
error:error];
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance
|
|
58
58
|
{
|
|
59
|
-
id<FBXCElementSnapshot> snapshot = self
|
|
60
|
-
? self.lastSnapshot
|
|
61
|
-
: self.fb_takeSnapshot;
|
|
59
|
+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
|
|
62
60
|
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollUpByNormalizedDistance:distance
|
|
63
61
|
inApplication:self.application];
|
|
64
62
|
}
|
|
65
63
|
|
|
66
64
|
- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance
|
|
67
65
|
{
|
|
68
|
-
id<FBXCElementSnapshot> snapshot = self
|
|
69
|
-
? self.lastSnapshot
|
|
70
|
-
: self.fb_takeSnapshot;
|
|
66
|
+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
|
|
71
67
|
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollDownByNormalizedDistance:distance
|
|
72
68
|
inApplication:self.application];
|
|
73
69
|
}
|
|
74
70
|
|
|
75
71
|
- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance
|
|
76
72
|
{
|
|
77
|
-
id<FBXCElementSnapshot> snapshot = self
|
|
78
|
-
? self.lastSnapshot
|
|
79
|
-
: self.fb_takeSnapshot;
|
|
73
|
+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
|
|
80
74
|
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollLeftByNormalizedDistance:distance
|
|
81
75
|
inApplication:self.application];
|
|
82
76
|
}
|
|
83
77
|
|
|
84
78
|
- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance
|
|
85
79
|
{
|
|
86
|
-
id<FBXCElementSnapshot> snapshot = self
|
|
87
|
-
? self.lastSnapshot
|
|
88
|
-
: self.fb_takeSnapshot;
|
|
80
|
+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
|
|
89
81
|
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollRightByNormalizedDistance:distance
|
|
90
82
|
inApplication:self.application];
|
|
91
83
|
}
|
|
@@ -95,7 +87,8 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
95
87
|
return [self fb_scrollToVisibleWithNormalizedScrollDistance:FBScrollToVisibleNormalizedDistance error:error];
|
|
96
88
|
}
|
|
97
89
|
|
|
98
|
-
- (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance
|
|
90
|
+
- (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance
|
|
91
|
+
error:(NSError **)error
|
|
99
92
|
{
|
|
100
93
|
return [self fb_scrollToVisibleWithNormalizedScrollDistance:normalizedScrollDistance
|
|
101
94
|
scrollDirection:FBXCUIElementScrollDirectionUnknown
|
|
@@ -106,7 +99,8 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
106
99
|
scrollDirection:(FBXCUIElementScrollDirection)scrollDirection
|
|
107
100
|
error:(NSError **)error
|
|
108
101
|
{
|
|
109
|
-
FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]];
|
|
102
|
+
FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:YES]];
|
|
103
|
+
|
|
110
104
|
if (prescrollSnapshot.isWDVisible) {
|
|
111
105
|
return YES;
|
|
112
106
|
}
|
|
@@ -138,12 +132,12 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
138
132
|
FBXCElementSnapshotWrapper *wrappedCellSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:cellSnapshot];
|
|
139
133
|
if (wrappedCellSnapshot.wdVisible) {
|
|
140
134
|
[visibleCellSnapshots addObject:cellSnapshot];
|
|
135
|
+
if (visibleCellSnapshots.count > 1) {
|
|
136
|
+
return YES;
|
|
137
|
+
}
|
|
141
138
|
}
|
|
142
139
|
}
|
|
143
140
|
|
|
144
|
-
if (visibleCellSnapshots.count > 1) {
|
|
145
|
-
return YES;
|
|
146
|
-
}
|
|
147
141
|
return NO;
|
|
148
142
|
}];
|
|
149
143
|
|
|
@@ -213,9 +207,9 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
213
207
|
// Cell is now visible, but it might be only partialy visible, scrolling till whole frame is visible.
|
|
214
208
|
// Sometimes, attempting to grab the parent snapshot of the target cell after scrolling is complete causes a stale element reference exception.
|
|
215
209
|
// Trying fb_cachedSnapshot first
|
|
216
|
-
FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:
|
|
210
|
+
FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:YES]];
|
|
217
211
|
targetCellSnapshot = [targetCellSnapshotWrapped fb_parentCellSnapshot];
|
|
218
|
-
CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].
|
|
212
|
+
CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].fb_visibleFrame;
|
|
219
213
|
|
|
220
214
|
CGVector scrollVector = CGVectorMake(visibleFrame.size.width - targetCellSnapshot.frame.size.width,
|
|
221
215
|
visibleFrame.size.height - targetCellSnapshot.frame.size.height
|
|
@@ -233,7 +227,7 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
233
227
|
return YES;
|
|
234
228
|
}
|
|
235
229
|
|
|
236
|
-
id<FBXCElementSnapshot> appSnapshot = [self.application fb_takeSnapshot];
|
|
230
|
+
id<FBXCElementSnapshot> appSnapshot = [self.application fb_takeSnapshot:YES];
|
|
237
231
|
for (id<FBXCElementSnapshot> elementSnapshot in appSnapshot._allDescendants.copy) {
|
|
238
232
|
FBXCElementSnapshotWrapper *wrappedElementSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:elementSnapshot];
|
|
239
233
|
// We are comparing pre-scroll snapshot so frames are irrelevant.
|
|
@@ -255,27 +249,32 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
255
249
|
return self.visibleFrame;
|
|
256
250
|
}
|
|
257
251
|
|
|
258
|
-
- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance
|
|
252
|
+
- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance
|
|
253
|
+
inApplication:(XCUIApplication *)application
|
|
259
254
|
{
|
|
260
255
|
[self fb_scrollByNormalizedVector:CGVectorMake(0.0, distance) inApplication:application];
|
|
261
256
|
}
|
|
262
257
|
|
|
263
|
-
- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance
|
|
258
|
+
- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance
|
|
259
|
+
inApplication:(XCUIApplication *)application
|
|
264
260
|
{
|
|
265
261
|
[self fb_scrollByNormalizedVector:CGVectorMake(0.0, -distance) inApplication:application];
|
|
266
262
|
}
|
|
267
263
|
|
|
268
|
-
- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance
|
|
264
|
+
- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance
|
|
265
|
+
inApplication:(XCUIApplication *)application
|
|
269
266
|
{
|
|
270
267
|
[self fb_scrollByNormalizedVector:CGVectorMake(distance, 0.0) inApplication:application];
|
|
271
268
|
}
|
|
272
269
|
|
|
273
|
-
- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance
|
|
270
|
+
- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance
|
|
271
|
+
inApplication:(XCUIApplication *)application
|
|
274
272
|
{
|
|
275
273
|
[self fb_scrollByNormalizedVector:CGVectorMake(-distance, 0.0) inApplication:application];
|
|
276
274
|
}
|
|
277
275
|
|
|
278
|
-
- (BOOL)fb_scrollByNormalizedVector:(CGVector)normalizedScrollVector
|
|
276
|
+
- (BOOL)fb_scrollByNormalizedVector:(CGVector)normalizedScrollVector
|
|
277
|
+
inApplication:(XCUIApplication *)application
|
|
279
278
|
{
|
|
280
279
|
CGVector scrollVector = CGVectorMake(CGRectGetWidth(self.scrollingFrame) * normalizedScrollVector.dx,
|
|
281
280
|
CGRectGetHeight(self.scrollingFrame) * normalizedScrollVector.dy
|
|
@@ -283,7 +282,9 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
283
282
|
return [self fb_scrollByVector:scrollVector inApplication:application error:nil];
|
|
284
283
|
}
|
|
285
284
|
|
|
286
|
-
- (BOOL)fb_scrollByVector:(CGVector)vector
|
|
285
|
+
- (BOOL)fb_scrollByVector:(CGVector)vector
|
|
286
|
+
inApplication:(XCUIApplication *)application
|
|
287
|
+
error:(NSError **)error
|
|
287
288
|
{
|
|
288
289
|
CGVector scrollBoundingVector = CGVectorMake(
|
|
289
290
|
CGRectGetWidth(self.scrollingFrame) * FBScrollTouchProportion,
|
|
@@ -314,7 +315,9 @@ const CGFloat FBScrollTouchProportion = 0.75f;
|
|
|
314
315
|
return CGVectorMake((CGFloat)floor(x), (CGFloat)floor(y));
|
|
315
316
|
}
|
|
316
317
|
|
|
317
|
-
- (BOOL)fb_scrollAncestorScrollViewByVectorWithinScrollViewFrame:(CGVector)vector
|
|
318
|
+
- (BOOL)fb_scrollAncestorScrollViewByVectorWithinScrollViewFrame:(CGVector)vector
|
|
319
|
+
inApplication:(XCUIApplication *)application
|
|
320
|
+
error:(NSError **)error
|
|
318
321
|
{
|
|
319
322
|
CGVector hitpointOffset = [self fb_hitPointOffsetForScrollingVector:vector];
|
|
320
323
|
|
|
@@ -91,7 +91,7 @@ BOOL FBTypeText(NSString *text, NSUInteger typingSpeed, NSError **error)
|
|
|
91
91
|
[FBLogger logFmt:@"Trying to tap the \"%@\" element to have it focused", snapshot.fb_description];
|
|
92
92
|
[self tap];
|
|
93
93
|
// It might take some time to update the UI
|
|
94
|
-
[self fb_takeSnapshot];
|
|
94
|
+
[self fb_takeSnapshot:NO];
|
|
95
95
|
#endif
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -110,9 +110,7 @@ BOOL FBTypeText(NSString *text, NSUInteger typingSpeed, NSError **error)
|
|
|
110
110
|
frequency:(NSUInteger)frequency
|
|
111
111
|
error:(NSError **)error
|
|
112
112
|
{
|
|
113
|
-
id<FBXCElementSnapshot> snapshot = self
|
|
114
|
-
? self.lastSnapshot
|
|
115
|
-
: self.fb_takeSnapshot;
|
|
113
|
+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:NO];
|
|
116
114
|
FBXCElementSnapshotWrapper *wrapped = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
|
|
117
115
|
[self fb_prepareForTextInputWithSnapshot:wrapped];
|
|
118
116
|
if (shouldClear && ![self fb_clearTextWithSnapshot:wrapped shouldPrepareForInput:NO error:error]) {
|
|
@@ -123,9 +121,7 @@ BOOL FBTypeText(NSString *text, NSUInteger typingSpeed, NSError **error)
|
|
|
123
121
|
|
|
124
122
|
- (BOOL)fb_clearTextWithError:(NSError **)error
|
|
125
123
|
{
|
|
126
|
-
id<FBXCElementSnapshot> snapshot = self
|
|
127
|
-
? self.lastSnapshot
|
|
128
|
-
: self.fb_takeSnapshot;
|
|
124
|
+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:NO];
|
|
129
125
|
return [self fb_clearTextWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot]
|
|
130
126
|
shouldPrepareForInput:YES
|
|
131
127
|
error:error];
|
|
@@ -182,7 +178,7 @@ BOOL FBTypeText(NSString *text, NSUInteger typingSpeed, NSError **error)
|
|
|
182
178
|
return NO;
|
|
183
179
|
}
|
|
184
180
|
|
|
185
|
-
currentValue = self
|
|
181
|
+
currentValue = [self fb_takeSnapshot:NO].value;
|
|
186
182
|
if (nil != placeholderValue && [currentValue isEqualToString:placeholderValue]) {
|
|
187
183
|
// Short circuit if only the placeholder value left
|
|
188
184
|
return YES;
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
{
|
|
23
23
|
return [FBElementUtils idWithAccessibilityElement:([self isKindOfClass:XCUIApplication.class]
|
|
24
24
|
? [(XCUIApplication *)self accessibilityElement]
|
|
25
|
-
: [self fb_takeSnapshot].accessibilityElement)];
|
|
25
|
+
: [self fb_takeSnapshot:NO].accessibilityElement)];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
- (NSString *)fb_uid
|
|
29
29
|
{
|
|
30
30
|
return [self isKindOfClass:XCUIApplication.class]
|
|
31
31
|
? [FBElementUtils uidWithAccessibilityElement:[(XCUIApplication *)self accessibilityElement]]
|
|
32
|
-
: [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]].fb_uid;
|
|
32
|
+
: [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:NO]].fb_uid;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
@end
|
|
@@ -19,12 +19,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
19
19
|
Gets the most recent snapshot of the current element. The element will be
|
|
20
20
|
automatically resolved if the snapshot is not available yet.
|
|
21
21
|
Calls to this method mutate the `lastSnapshot` instance property..
|
|
22
|
-
Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`.
|
|
23
22
|
|
|
23
|
+
@param inDepth Whether to resolve snapshot parents and children. Setting it to NO
|
|
24
|
+
would improve the snapshotting performance
|
|
24
25
|
@return The recent snapshot of the element
|
|
25
26
|
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
|
|
26
27
|
*/
|
|
27
|
-
- (id<FBXCElementSnapshot>)fb_takeSnapshot;
|
|
28
|
+
- (id<FBXCElementSnapshot>)fb_takeSnapshot:(BOOL)inDepth;
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
Extracts the cached element snapshot from its query.
|
|
@@ -36,40 +37,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
36
37
|
*/
|
|
37
38
|
- (nullable id<FBXCElementSnapshot>)fb_cachedSnapshot;
|
|
38
39
|
|
|
39
|
-
/**
|
|
40
|
-
Gets the most recent snapshot of the current element and already resolves the accessibility attributes
|
|
41
|
-
needed for creating the page source of this element. No additional calls to the accessibility layer
|
|
42
|
-
are required.
|
|
43
|
-
Calls to this method mutate the `lastSnapshot` instance property.
|
|
44
|
-
Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`.
|
|
45
|
-
|
|
46
|
-
@param maxDepth The maximum depth of the snapshot. nil value means to use the default depth.
|
|
47
|
-
with custom attributes cannot be resolved
|
|
48
|
-
|
|
49
|
-
@return The recent snapshot of the element with all attributes resolved or a snapshot with default
|
|
50
|
-
attributes resolved if there was a failure while resolving additional attributes
|
|
51
|
-
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
|
|
52
|
-
*/
|
|
53
|
-
- (nullable id<FBXCElementSnapshot>)fb_snapshotWithAllAttributesAndMaxDepth:(nullable NSNumber *)maxDepth;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
Gets the most recent snapshot of the current element with given attributes resolved.
|
|
57
|
-
No additional calls to the accessibility layer are required.
|
|
58
|
-
Calls to this method mutate the `lastSnapshot` instance property.
|
|
59
|
-
Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`.
|
|
60
|
-
|
|
61
|
-
@param attributeNames The list of attribute names to resolve. Must be one of
|
|
62
|
-
FB_...Name values exported by XCTestPrivateSymbols.h module.
|
|
63
|
-
`nil` value means that only the default attributes must be extracted
|
|
64
|
-
@param maxDepth The maximum depth of the snapshot. nil value means to use the default depth.
|
|
65
|
-
|
|
66
|
-
@return The recent snapshot of the element with the given attributes resolved or a snapshot with default
|
|
67
|
-
attributes resolved if there was a failure while resolving additional attributes
|
|
68
|
-
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
|
|
69
|
-
*/
|
|
70
|
-
- (nullable id<FBXCElementSnapshot>)fb_snapshotWithAttributes:(nullable NSArray<NSString *> *)attributeNames
|
|
71
|
-
maxDepth:(nullable NSNumber *)maxDepth;
|
|
72
|
-
|
|
73
40
|
/**
|
|
74
41
|
Filters elements by matching them to snapshots from the corresponding array
|
|
75
42
|
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#import "FBConfiguration.h"
|
|
15
15
|
#import "FBExceptions.h"
|
|
16
16
|
#import "FBImageUtils.h"
|
|
17
|
+
#import "FBElementUtils.h"
|
|
17
18
|
#import "FBLogger.h"
|
|
18
19
|
#import "FBMacros.h"
|
|
19
20
|
#import "FBMathUtils.h"
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
#import "XCTestPrivateSymbols.h"
|
|
33
34
|
#import "XCTRunnerDaemonSession.h"
|
|
34
35
|
#import "XCUIApplicationProcess+FBQuiescence.h"
|
|
36
|
+
#import "XCUIApplication.h"
|
|
35
37
|
#import "XCUIElement+FBCaching.h"
|
|
36
38
|
#import "XCUIElement+FBWebDriverAttributes.h"
|
|
37
39
|
#import "XCUIElementQuery.h"
|
|
@@ -40,22 +42,21 @@
|
|
|
40
42
|
#import "XCUIScreen.h"
|
|
41
43
|
#import "XCUIElement+FBResolve.h"
|
|
42
44
|
|
|
43
|
-
#define DEFAULT_AX_TIMEOUT 60.
|
|
44
|
-
|
|
45
45
|
@implementation XCUIElement (FBUtilities)
|
|
46
46
|
|
|
47
|
-
- (id<FBXCElementSnapshot>)fb_takeSnapshot
|
|
47
|
+
- (id<FBXCElementSnapshot>)fb_takeSnapshot:(BOOL)inDepth
|
|
48
48
|
{
|
|
49
49
|
NSError *error = nil;
|
|
50
|
-
self.
|
|
51
|
-
|
|
50
|
+
self.lastSnapshot = inDepth
|
|
51
|
+
? [self.fb_query fb_uniqueSnapshotWithError:&error]
|
|
52
|
+
: (id<FBXCElementSnapshot>)[self snapshotWithError:&error];
|
|
52
53
|
if (nil == self.lastSnapshot) {
|
|
53
54
|
NSString *hintText = @"Make sure the application UI has the expected state";
|
|
54
|
-
if (nil != error
|
|
55
|
-
&& [error.localizedDescription containsString:@"Identity Binding"]) {
|
|
55
|
+
if (nil != error && [error.localizedDescription containsString:@"Identity Binding"]) {
|
|
56
56
|
hintText = [NSString stringWithFormat:@"%@. You could also try to switch the binding strategy using the 'boundElementsByIndex' setting for the element lookup", hintText];
|
|
57
57
|
}
|
|
58
|
-
NSString *reason = [NSString stringWithFormat:@"The previously found element \"%@\" is not present in the current view anymore. %@",
|
|
58
|
+
NSString *reason = [NSString stringWithFormat:@"The previously found element \"%@\" is not present in the current view anymore. %@",
|
|
59
|
+
self.description, hintText];
|
|
59
60
|
if (nil != error) {
|
|
60
61
|
reason = [NSString stringWithFormat:@"%@. Original error: %@", reason, error.localizedDescription];
|
|
61
62
|
}
|
|
@@ -69,63 +70,6 @@
|
|
|
69
70
|
return [self.query fb_cachedSnapshot];
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
- (nullable id<FBXCElementSnapshot>)fb_snapshotWithAllAttributesAndMaxDepth:(NSNumber *)maxDepth
|
|
73
|
-
{
|
|
74
|
-
NSMutableArray *allNames = [NSMutableArray arrayWithArray:FBStandardAttributeNames()];
|
|
75
|
-
[allNames addObjectsFromArray:FBCustomAttributeNames()];
|
|
76
|
-
return [self fb_snapshotWithAttributes:allNames.copy
|
|
77
|
-
maxDepth:maxDepth];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
- (nullable id<FBXCElementSnapshot>)fb_snapshotWithAttributes:(NSArray<NSString *> *)attributeNames
|
|
81
|
-
maxDepth:(NSNumber *)maxDepth
|
|
82
|
-
{
|
|
83
|
-
NSSet<NSString *> *standardAttributes = [NSSet setWithArray:FBStandardAttributeNames()];
|
|
84
|
-
id<FBXCElementSnapshot> snapshot = self.fb_takeSnapshot;
|
|
85
|
-
NSTimeInterval axTimeout = FBConfiguration.customSnapshotTimeout;
|
|
86
|
-
if (nil == attributeNames
|
|
87
|
-
|| [[NSSet setWithArray:attributeNames] isSubsetOfSet:standardAttributes]
|
|
88
|
-
|| axTimeout < DBL_EPSILON) {
|
|
89
|
-
// return the "normal" element snapshot if no custom attributes are requested
|
|
90
|
-
return snapshot;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
id<FBXCAccessibilityElement> axElement = snapshot.accessibilityElement;
|
|
94
|
-
if (nil == axElement) {
|
|
95
|
-
return nil;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
NSError *setTimeoutError;
|
|
99
|
-
BOOL isTimeoutSet = [FBXCAXClientProxy.sharedClient setAXTimeout:axTimeout
|
|
100
|
-
error:&setTimeoutError];
|
|
101
|
-
if (!isTimeoutSet) {
|
|
102
|
-
[FBLogger logFmt:@"Cannot set snapshoting timeout to %.1fs. Original error: %@",
|
|
103
|
-
axTimeout, setTimeoutError.localizedDescription];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
NSError *error;
|
|
107
|
-
id<FBXCElementSnapshot> snapshotWithAttributes = [FBXCAXClientProxy.sharedClient snapshotForElement:axElement
|
|
108
|
-
attributes:attributeNames
|
|
109
|
-
maxDepth:maxDepth
|
|
110
|
-
error:&error];
|
|
111
|
-
if (nil == snapshotWithAttributes) {
|
|
112
|
-
NSString *description = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_description;
|
|
113
|
-
[FBLogger logFmt:@"Cannot take a snapshot with attribute(s) %@ of '%@' after %.2f seconds",
|
|
114
|
-
attributeNames, description, axTimeout];
|
|
115
|
-
[FBLogger logFmt:@"This timeout could be customized via '%@' setting", FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT];
|
|
116
|
-
[FBLogger logFmt:@"Internal error: %@", error.localizedDescription];
|
|
117
|
-
[FBLogger logFmt:@"Falling back to the default snapshotting mechanism for the element '%@' (some attribute values, like visibility or accessibility might not be precise though)", description];
|
|
118
|
-
snapshotWithAttributes = self.lastSnapshot;
|
|
119
|
-
} else {
|
|
120
|
-
self.lastSnapshot = snapshotWithAttributes;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (isTimeoutSet) {
|
|
124
|
-
[FBXCAXClientProxy.sharedClient setAXTimeout:DEFAULT_AX_TIMEOUT error:nil];
|
|
125
|
-
}
|
|
126
|
-
return snapshotWithAttributes;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
73
|
- (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<id<FBXCElementSnapshot>> *)snapshots
|
|
130
74
|
selfUID:(NSString *)selfUID
|
|
131
75
|
onlyChildren:(BOOL)onlyChildren
|
|
@@ -143,9 +87,7 @@
|
|
|
143
87
|
NSMutableArray<XCUIElement *> *matchedElements = [NSMutableArray array];
|
|
144
88
|
NSString *uid = selfUID;
|
|
145
89
|
if (nil == uid) {
|
|
146
|
-
uid = self.
|
|
147
|
-
? [FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot]
|
|
148
|
-
: self.fb_uid;
|
|
90
|
+
uid = self.fb_uid;
|
|
149
91
|
}
|
|
150
92
|
if (nil != uid && [matchedIds containsObject:uid]) {
|
|
151
93
|
XCUIElement *stableSelf = self.fb_stableInstance;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#import "FBXCElementSnapshotWrapper.h"
|
|
11
|
+
|
|
12
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
13
|
+
|
|
14
|
+
@interface XCUIElement (FBVisibleFrame)
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
Returns the snapshot visibleFrame with a fallback to direct attribute retrieval from FBXCAXClient in case of a snapshot fault (nil visibleFrame)
|
|
18
|
+
|
|
19
|
+
@return the snapshot visibleFrame
|
|
20
|
+
*/
|
|
21
|
+
- (CGRect)fb_visibleFrame;
|
|
22
|
+
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
@interface FBXCElementSnapshotWrapper (FBVisibleFrame)
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
Returns the snapshot visibleFrame with a fallback to direct attribute retrieval from FBXCAXClient in case of a snapshot fault (nil visibleFrame)
|
|
29
|
+
|
|
30
|
+
@return the snapshot visibleFrame
|
|
31
|
+
*/
|
|
32
|
+
- (CGRect)fb_visibleFrame;
|
|
33
|
+
|
|
34
|
+
@end
|
|
35
|
+
|
|
36
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#import "XCUIElement+FBVisibleFrame.h"
|
|
11
|
+
#import "FBElementUtils.h"
|
|
12
|
+
#import "FBXCodeCompatibility.h"
|
|
13
|
+
#import "FBXCElementSnapshotWrapper+Helpers.h"
|
|
14
|
+
#import "XCUIElement+FBUtilities.h"
|
|
15
|
+
#import "XCTestPrivateSymbols.h"
|
|
16
|
+
|
|
17
|
+
@implementation XCUIElement (FBVisibleFrame)
|
|
18
|
+
|
|
19
|
+
- (CGRect)fb_visibleFrame
|
|
20
|
+
{
|
|
21
|
+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:NO];
|
|
22
|
+
return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_visibleFrame;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@end
|
|
26
|
+
|
|
27
|
+
@implementation FBXCElementSnapshotWrapper (FBVisibleFrame)
|
|
28
|
+
|
|
29
|
+
- (CGRect)fb_visibleFrame
|
|
30
|
+
{
|
|
31
|
+
CGRect thisVisibleFrame = [self visibleFrame];
|
|
32
|
+
if (!CGRectIsEmpty(thisVisibleFrame)) {
|
|
33
|
+
return thisVisibleFrame;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
NSDictionary *visibleFrameDict = [self fb_attributeValue:FB_XCAXAVisibleFrameAttributeName
|
|
37
|
+
error:nil];
|
|
38
|
+
if (nil == visibleFrameDict) {
|
|
39
|
+
return thisVisibleFrame;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
id x = [visibleFrameDict objectForKey:@"X"];
|
|
43
|
+
id y = [visibleFrameDict objectForKey:@"Y"];
|
|
44
|
+
id height = [visibleFrameDict objectForKey:@"Height"];
|
|
45
|
+
id width = [visibleFrameDict objectForKey:@"Width"];
|
|
46
|
+
if (x != nil && y != nil && height != nil && width != nil) {
|
|
47
|
+
return CGRectMake([x doubleValue], [y doubleValue], [width doubleValue], [height doubleValue]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return thisVisibleFrame;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@end
|
|
@@ -28,24 +28,10 @@
|
|
|
28
28
|
|
|
29
29
|
- (id<FBXCElementSnapshot>)fb_snapshotForAttributeName:(NSString *)name
|
|
30
30
|
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if ([name isEqualToString:FBStringify(XCUIElement, isWDVisible)]) {
|
|
36
|
-
return [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName]
|
|
37
|
-
maxDepth:@1];
|
|
38
|
-
}
|
|
39
|
-
if ([name isEqualToString:FBStringify(XCUIElement, isWDAccessible)]) {
|
|
40
|
-
return [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName]
|
|
41
|
-
maxDepth:@1];
|
|
42
|
-
}
|
|
43
|
-
if ([name isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)]) {
|
|
44
|
-
return [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName]
|
|
45
|
-
maxDepth:nil];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return self.fb_takeSnapshot;
|
|
31
|
+
BOOL inDepth = [name isEqualToString:FBStringify(XCUIElement, isWDAccessible)]
|
|
32
|
+
|| [name isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)]
|
|
33
|
+
|| [name isEqualToString:FBStringify(XCUIElement, wdIndex)];
|
|
34
|
+
return [self fb_takeSnapshot:inDepth];
|
|
49
35
|
}
|
|
50
36
|
|
|
51
37
|
- (id)fb_valueForWDAttributeName:(NSString *)name
|
|
@@ -92,6 +78,7 @@
|
|
|
92
78
|
value = @([value boolValue]);
|
|
93
79
|
} else if (elementType == XCUIElementTypeTextView ||
|
|
94
80
|
elementType == XCUIElementTypeTextField ||
|
|
81
|
+
elementType == XCUIElementTypeSearchField ||
|
|
95
82
|
elementType == XCUIElementTypeSecureTextField) {
|
|
96
83
|
NSString *placeholderValue = self.placeholderValue;
|
|
97
84
|
value = FBFirstNonEmptyValue(value, placeholderValue);
|
|
@@ -183,8 +170,8 @@
|
|
|
183
170
|
// In the scenario when table provides Search results controller, table could be marked as accessible element, even though it isn't
|
|
184
171
|
// As it is highly unlikely that table view should ever be an accessibility element itself,
|
|
185
172
|
// for now we work around that by skipping Table View in container checks
|
|
186
|
-
if (
|
|
187
|
-
&& parentSnapshot.
|
|
173
|
+
if (parentSnapshot.elementType != XCUIElementTypeTable
|
|
174
|
+
&& [FBXCElementSnapshotWrapper ensureWrapped:parentSnapshot].fb_isAccessibilityElement) {
|
|
188
175
|
return NO;
|
|
189
176
|
}
|
|
190
177
|
parentSnapshot = parentSnapshot.parent;
|
|
@@ -567,7 +567,8 @@
|
|
|
567
567
|
FBElementCache *elementCache = request.session.elementCache;
|
|
568
568
|
BOOL hasElement = ![request.parameters[@"uuid"] isEqual:@"0"];
|
|
569
569
|
XCUIElement *destination = hasElement
|
|
570
|
-
? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
|
|
570
|
+
? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]
|
|
571
|
+
checkStaleness:YES]
|
|
571
572
|
: request.session.activeApplication;
|
|
572
573
|
id keys = request.arguments[@"keys"];
|
|
573
574
|
|