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
|
@@ -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
|
{
|
|
@@ -7,24 +7,29 @@
|
|
|
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
|
|
|
15
14
|
@interface XCUIElement (FBUID)
|
|
16
15
|
|
|
17
|
-
/*! Represents unique internal element identifier, which is the same for an element and its snapshot */
|
|
16
|
+
/*! Represents unique internal element identifier, which is the same for an element and its snapshot as UUIDv4 */
|
|
18
17
|
@property (nonatomic, nullable, readonly, copy) NSString *fb_uid;
|
|
19
18
|
|
|
19
|
+
/*! Represents unique internal element identifier, which is the same for an element and its snapshot */
|
|
20
|
+
@property (nonatomic, readonly) unsigned long long fb_accessibiltyId;
|
|
21
|
+
|
|
20
22
|
@end
|
|
21
23
|
|
|
22
24
|
|
|
23
|
-
@interface
|
|
25
|
+
@interface FBXCElementSnapshotWrapper (FBUID)
|
|
24
26
|
|
|
25
|
-
/*! Represents unique internal element identifier, which is the same for an element and its snapshot */
|
|
27
|
+
/*! Represents unique internal element identifier, which is the same for an element and its snapshot as UUIDv4 */
|
|
26
28
|
@property (nonatomic, nullable, readonly, copy) NSString *fb_uid;
|
|
27
29
|
|
|
30
|
+
/*! Represents unique internal element identifier, which is the same for an element and its snapshot */
|
|
31
|
+
@property (nonatomic, readonly) unsigned long long fb_accessibiltyId;
|
|
32
|
+
|
|
28
33
|
@end
|
|
29
34
|
|
|
30
35
|
NS_ASSUME_NONNULL_END
|
|
@@ -15,20 +15,32 @@
|
|
|
15
15
|
|
|
16
16
|
@implementation XCUIElement (FBUID)
|
|
17
17
|
|
|
18
|
+
- (unsigned long long)fb_accessibiltyId
|
|
19
|
+
{
|
|
20
|
+
return [FBElementUtils idWithAccessibilityElement:([self isKindOfClass:XCUIApplication.class]
|
|
21
|
+
? [(XCUIApplication *)self accessibilityElement]
|
|
22
|
+
: [self fb_takeSnapshot].accessibilityElement)];
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
- (NSString *)fb_uid
|
|
19
26
|
{
|
|
20
27
|
return [self isKindOfClass:XCUIApplication.class]
|
|
21
28
|
? [FBElementUtils uidWithAccessibilityElement:[(XCUIApplication *)self accessibilityElement]]
|
|
22
|
-
: [self fb_takeSnapshot].fb_uid;
|
|
29
|
+
: [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]].fb_uid;
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
@end
|
|
26
33
|
|
|
27
|
-
@implementation
|
|
34
|
+
@implementation FBXCElementSnapshotWrapper (FBUID)
|
|
35
|
+
|
|
36
|
+
- (unsigned long long)fb_accessibiltyId
|
|
37
|
+
{
|
|
38
|
+
return [FBElementUtils idWithAccessibilityElement:self.accessibilityElement];
|
|
39
|
+
}
|
|
28
40
|
|
|
29
41
|
- (NSString *)fb_uid
|
|
30
42
|
{
|
|
31
|
-
return [FBElementUtils uidWithAccessibilityElement:self
|
|
43
|
+
return [FBElementUtils uidWithAccessibilityElement:[self accessibilityElement]];
|
|
32
44
|
}
|
|
33
45
|
|
|
34
46
|
@end
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
#import <XCTest/XCTest.h>
|
|
11
|
-
#import <WebDriverAgentLib/XCElementSnapshot.h>
|
|
12
11
|
#import <WebDriverAgentLib/FBElement.h>
|
|
12
|
+
#import "FBXCElementSnapshot.h"
|
|
13
13
|
|
|
14
14
|
NS_ASSUME_NONNULL_BEGIN
|
|
15
15
|
|
|
@@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
24
24
|
@return The recent snapshot of the element
|
|
25
25
|
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
|
|
26
26
|
*/
|
|
27
|
-
- (
|
|
27
|
+
- (id<FBXCElementSnapshot>)fb_takeSnapshot;
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
Extracts the cached element snapshot from its query.
|
|
@@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
34
34
|
|
|
35
35
|
@return Either the cached snapshot or nil
|
|
36
36
|
*/
|
|
37
|
-
- (nullable
|
|
37
|
+
- (nullable id<FBXCElementSnapshot>)fb_cachedSnapshot;
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
Gets the most recent snapshot of the current element and already resolves the accessibility attributes
|
|
@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
50
50
|
attributes resolved if there was a failure while resolving additional attributes
|
|
51
51
|
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
|
|
52
52
|
*/
|
|
53
|
-
- (nullable
|
|
53
|
+
- (nullable id<FBXCElementSnapshot>)fb_snapshotWithAllAttributesAndMaxDepth:(nullable NSNumber *)maxDepth;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
Gets the most recent snapshot of the current element with given attributes resolved.
|
|
@@ -67,8 +67,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
67
67
|
attributes resolved if there was a failure while resolving additional attributes
|
|
68
68
|
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
|
|
69
69
|
*/
|
|
70
|
-
- (nullable
|
|
71
|
-
|
|
70
|
+
- (nullable id<FBXCElementSnapshot>)fb_snapshotWithAttributes:(nullable NSArray<NSString *> *)attributeNames
|
|
71
|
+
maxDepth:(nullable NSNumber *)maxDepth;
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
74
|
Filters elements by matching them to snapshots from the corresponding array
|
|
@@ -80,7 +80,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
80
80
|
|
|
81
81
|
@return Array of filtered elements, which have matches in snapshots array
|
|
82
82
|
*/
|
|
83
|
-
- (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<
|
|
83
|
+
- (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<id<FBXCElementSnapshot>> *)snapshots
|
|
84
84
|
selfUID:(nullable NSString *)selfUID
|
|
85
85
|
onlyChildren:(BOOL)onlyChildren;
|
|
86
86
|
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
#import "FBScreenshot.h"
|
|
23
23
|
#import "FBXCAXClientProxy.h"
|
|
24
24
|
#import "FBXCodeCompatibility.h"
|
|
25
|
+
#import "FBXCElementSnapshot.h"
|
|
26
|
+
#import "FBXCElementSnapshotWrapper+Helpers.h"
|
|
25
27
|
#import "XCUIApplication.h"
|
|
26
28
|
#import "XCUIApplication+FBQuiescence.h"
|
|
27
29
|
#import "XCUIApplicationImpl.h"
|
|
@@ -41,7 +43,7 @@
|
|
|
41
43
|
|
|
42
44
|
@implementation XCUIElement (FBUtilities)
|
|
43
45
|
|
|
44
|
-
- (
|
|
46
|
+
- (id<FBXCElementSnapshot>)fb_takeSnapshot
|
|
45
47
|
{
|
|
46
48
|
NSError *error = nil;
|
|
47
49
|
self.fb_isResolvedFromCache = @(NO);
|
|
@@ -61,12 +63,12 @@
|
|
|
61
63
|
return self.lastSnapshot;
|
|
62
64
|
}
|
|
63
65
|
|
|
64
|
-
- (
|
|
66
|
+
- (id<FBXCElementSnapshot>)fb_cachedSnapshot
|
|
65
67
|
{
|
|
66
68
|
return [self.query fb_cachedSnapshot];
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
- (nullable
|
|
71
|
+
- (nullable id<FBXCElementSnapshot>)fb_snapshotWithAllAttributesAndMaxDepth:(NSNumber *)maxDepth
|
|
70
72
|
{
|
|
71
73
|
NSMutableArray *allNames = [NSMutableArray arrayWithArray:FBStandardAttributeNames()];
|
|
72
74
|
[allNames addObjectsFromArray:FBCustomAttributeNames()];
|
|
@@ -74,11 +76,11 @@
|
|
|
74
76
|
maxDepth:maxDepth];
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
- (nullable
|
|
78
|
-
|
|
79
|
+
- (nullable id<FBXCElementSnapshot>)fb_snapshotWithAttributes:(NSArray<NSString *> *)attributeNames
|
|
80
|
+
maxDepth:(NSNumber *)maxDepth
|
|
79
81
|
{
|
|
80
82
|
NSSet<NSString *> *standardAttributes = [NSSet setWithArray:FBStandardAttributeNames()];
|
|
81
|
-
|
|
83
|
+
id<FBXCElementSnapshot> snapshot = self.fb_takeSnapshot;
|
|
82
84
|
NSTimeInterval axTimeout = FBConfiguration.customSnapshotTimeout;
|
|
83
85
|
if (nil == attributeNames
|
|
84
86
|
|| [[NSSet setWithArray:attributeNames] isSubsetOfSet:standardAttributes]
|
|
@@ -87,7 +89,7 @@
|
|
|
87
89
|
return snapshot;
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
id<FBXCAccessibilityElement> axElement = snapshot.accessibilityElement;
|
|
91
93
|
if (nil == axElement) {
|
|
92
94
|
return nil;
|
|
93
95
|
}
|
|
@@ -101,16 +103,17 @@
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
NSError *error;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
id<FBXCElementSnapshot> snapshotWithAttributes = [FBXCAXClientProxy.sharedClient snapshotForElement:axElement
|
|
107
|
+
attributes:attributeNames
|
|
108
|
+
maxDepth:maxDepth
|
|
109
|
+
error:&error];
|
|
108
110
|
if (nil == snapshotWithAttributes) {
|
|
111
|
+
NSString *description = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_description;
|
|
109
112
|
[FBLogger logFmt:@"Cannot take a snapshot with attribute(s) %@ of '%@' after %.2f seconds",
|
|
110
|
-
attributeNames,
|
|
113
|
+
attributeNames, description, axTimeout];
|
|
111
114
|
[FBLogger logFmt:@"This timeout could be customized via '%@' setting", FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT];
|
|
112
115
|
[FBLogger logFmt:@"Internal error: %@", error.localizedDescription];
|
|
113
|
-
[FBLogger logFmt:@"Falling back to the default snapshotting mechanism for the element '%@' (some attribute values, like visibility or accessibility might not be precise though)",
|
|
116
|
+
[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];
|
|
114
117
|
snapshotWithAttributes = self.lastSnapshot;
|
|
115
118
|
} else {
|
|
116
119
|
self.lastSnapshot = snapshotWithAttributes;
|
|
@@ -122,19 +125,22 @@
|
|
|
122
125
|
return snapshotWithAttributes;
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
- (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<
|
|
128
|
+
- (NSArray<XCUIElement *> *)fb_filterDescendantsWithSnapshots:(NSArray<id<FBXCElementSnapshot>> *)snapshots
|
|
126
129
|
selfUID:(NSString *)selfUID
|
|
127
130
|
onlyChildren:(BOOL)onlyChildren
|
|
128
131
|
{
|
|
129
132
|
if (0 == snapshots.count) {
|
|
130
133
|
return @[];
|
|
131
134
|
}
|
|
132
|
-
|
|
135
|
+
NSMutableArray<NSString *> *sortedIds = [NSMutableArray new];
|
|
136
|
+
for (id<FBXCElementSnapshot> snapshot in snapshots) {
|
|
137
|
+
[sortedIds addObject:(NSString *)[FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_uid];
|
|
138
|
+
}
|
|
133
139
|
NSMutableArray<XCUIElement *> *matchedElements = [NSMutableArray array];
|
|
134
140
|
NSString *uid = selfUID;
|
|
135
141
|
if (nil == uid) {
|
|
136
142
|
uid = self.fb_isResolvedFromCache.boolValue
|
|
137
|
-
? self.lastSnapshot.fb_uid
|
|
143
|
+
? [FBXCElementSnapshotWrapper ensureWrapped:self.lastSnapshot].fb_uid
|
|
138
144
|
: self.fb_uid;
|
|
139
145
|
}
|
|
140
146
|
if ([sortedIds containsObject:uid]) {
|
|
@@ -151,7 +157,10 @@
|
|
|
151
157
|
XCUIElementQuery *query = onlyChildren
|
|
152
158
|
? [self.fb_query childrenMatchingType:type]
|
|
153
159
|
: [self.fb_query descendantsMatchingType:type];
|
|
154
|
-
|
|
160
|
+
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot, NSDictionary *bindings) {
|
|
161
|
+
return [sortedIds containsObject:(NSString *)[FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_uid];
|
|
162
|
+
}];
|
|
163
|
+
query = [query matchingPredicate:predicate];
|
|
155
164
|
if (1 == snapshots.count) {
|
|
156
165
|
XCUIElement *result = query.fb_firstMatch;
|
|
157
166
|
result.fb_isResolvedNatively = @NO;
|
|
@@ -206,7 +215,7 @@
|
|
|
206
215
|
|
|
207
216
|
- (NSData *)fb_screenshotWithError:(NSError **)error
|
|
208
217
|
{
|
|
209
|
-
|
|
218
|
+
id<FBXCElementSnapshot> selfSnapshot = self.fb_isResolvedFromCache.boolValue
|
|
210
219
|
? self.lastSnapshot
|
|
211
220
|
: self.fb_takeSnapshot;
|
|
212
221
|
if (CGRectIsEmpty(selfSnapshot.frame)) {
|
|
@@ -221,8 +230,8 @@
|
|
|
221
230
|
UIInterfaceOrientation orientation = self.application.interfaceOrientation;
|
|
222
231
|
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
|
|
223
232
|
// Workaround XCTest bug when element frame is returned as in portrait mode even if the screenshot is rotated
|
|
224
|
-
NSArray<
|
|
225
|
-
|
|
233
|
+
NSArray<id<FBXCElementSnapshot>> *ancestors = [FBXCElementSnapshotWrapper ensureWrapped:selfSnapshot].fb_ancestors;
|
|
234
|
+
id<FBXCElementSnapshot> parentWindow = nil;
|
|
226
235
|
if (1 == ancestors.count) {
|
|
227
236
|
parentWindow = selfSnapshot;
|
|
228
237
|
} else if (ancestors.count > 1) {
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
#import <WebDriverAgentLib/FBElement.h>
|
|
11
|
-
#import <WebDriverAgentLib/XCElementSnapshot.h>
|
|
12
11
|
#import <WebDriverAgentLib/XCUIElement.h>
|
|
12
|
+
#import "FBXCElementSnapshotWrapper.h"
|
|
13
13
|
|
|
14
14
|
NS_ASSUME_NONNULL_BEGIN
|
|
15
15
|
|
|
@@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
18
18
|
@end
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
@interface
|
|
21
|
+
@interface FBXCElementSnapshotWrapper (WebDriverAttributes) <FBElement>
|
|
22
22
|
|
|
23
23
|
@end
|
|
24
24
|
|