Skip to content

Commit 73c5cf1

Browse files
feat: Split custom and standard snapshotting methods
1 parent ba61975 commit 73c5cf1

27 files changed

Lines changed: 157 additions & 66 deletions

WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ - (nullable XCUIElement *)fb_alertElementFromSafariWithScrollView:(XCUIElement *
5252
// and conatins at least one text view
5353
__block NSUInteger buttonsCount = 0;
5454
__block NSUInteger textViewsCount = 0;
55-
id<FBXCElementSnapshot> snapshot = candidate.fb_cachedSnapshot ?: [candidate fb_takeSnapshot:YES];
55+
id<FBXCElementSnapshot> snapshot = candidate.fb_cachedSnapshot ?: [candidate fb_customSnapshot];
5656
[snapshot enumerateDescendantsUsingBlock:^(id<FBXCElementSnapshot> descendant) {
5757
XCUIElementType curType = descendant.elementType;
5858
if (curType == XCUIElementTypeButton) {
@@ -73,7 +73,7 @@ - (XCUIElement *)fb_alertElement
7373
if (nil == alert) {
7474
return nil;
7575
}
76-
id<FBXCElementSnapshot> alertSnapshot = alert.fb_cachedSnapshot ?: [alert fb_takeSnapshot:YES];
76+
id<FBXCElementSnapshot> alertSnapshot = alert.fb_cachedSnapshot ?: [alert fb_customSnapshot];
7777

7878
if (alertSnapshot.elementType == XCUIElementTypeAlert) {
7979
return alert;

WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,15 @@ - (NSDictionary *)fb_tree
176176

177177
- (NSDictionary *)fb_tree:(nullable NSSet<NSString *> *)excludedAttributes
178178
{
179-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
179+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
180180
return [self.class dictionaryForElement:snapshot
181181
recursive:YES
182182
excludedAttributes:excludedAttributes];
183183
}
184184

185185
- (NSDictionary *)fb_accessibilityTree
186186
{
187-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
187+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
188188
return [self.class accessibilityInfoForElement:snapshot];
189189
}
190190

@@ -434,7 +434,7 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray<NSString *> *)keyNames
434434

435435
id extractedElement = extractIssueProperty(issue, @"element");
436436

437-
id<FBXCElementSnapshot> elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_takeSnapshot:NO];
437+
id<FBXCElementSnapshot> elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_standardSnapshot];
438438
NSDictionary *elementAttributes = elementSnapshot
439439
? [self.class dictionaryForElement:elementSnapshot
440440
recursive:NO

WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ @implementation XCUIElement (FBAccessibility)
1818

1919
- (BOOL)fb_isAccessibilityElement
2020
{
21-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:NO];
21+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
2222
return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isAccessibilityElement;
2323
}
2424

WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ @implementation XCUIElement (FBIsVisible)
2626
- (BOOL)fb_isVisible
2727
{
2828
@autoreleasepool {
29-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:NO];
29+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
3030
return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isVisible;
3131
}
3232
}

WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ @implementation XCUIElement (FBPickerWheel)
2424

2525
- (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)error
2626
{
27-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:NO];
27+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
2828
NSString *previousValue = snapshot.value;
2929
XCUICoordinate *startCoord = [self coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)];
3030
XCUICoordinate *endCoord = [startCoord coordinateWithOffset:CGVectorMake(0.0, relativeHeightOffset * snapshot.frame.size.height)];

WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,35 +49,35 @@ @implementation XCUIElement (FBScrolling)
4949

5050
- (BOOL)fb_nativeScrollToVisibleWithError:(NSError **)error
5151
{
52-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
52+
id<FBXCElementSnapshot> snapshot = [self fb_customSnapshot];
5353
return nil != [self _hitPointByAttemptingToScrollToVisibleSnapshot:snapshot
5454
error:error];
5555
}
5656

5757
- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance
5858
{
59-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
59+
id<FBXCElementSnapshot> snapshot = [self fb_customSnapshot];
6060
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollUpByNormalizedDistance:distance
6161
inApplication:self.application];
6262
}
6363

6464
- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance
6565
{
66-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
66+
id<FBXCElementSnapshot> snapshot = [self fb_customSnapshot];
6767
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollDownByNormalizedDistance:distance
6868
inApplication:self.application];
6969
}
7070

7171
- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance
7272
{
73-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
73+
id<FBXCElementSnapshot> snapshot = [self fb_customSnapshot];
7474
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollLeftByNormalizedDistance:distance
7575
inApplication:self.application];
7676
}
7777

7878
- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance
7979
{
80-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
80+
id<FBXCElementSnapshot> snapshot = [self fb_customSnapshot];
8181
[[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollRightByNormalizedDistance:distance
8282
inApplication:self.application];
8383
}
@@ -99,7 +99,7 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll
9999
scrollDirection:(FBXCUIElementScrollDirection)scrollDirection
100100
error:(NSError **)error
101101
{
102-
FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:YES]];
102+
FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_customSnapshot]];
103103

104104
if (prescrollSnapshot.isWDVisible) {
105105
return YES;
@@ -209,7 +209,7 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll
209209
// Cell is now visible, but it might be only partialy visible, scrolling till whole frame is visible.
210210
// Sometimes, attempting to grab the parent snapshot of the target cell after scrolling is complete causes a stale element reference exception.
211211
// Trying fb_cachedSnapshot first
212-
FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:YES]];
212+
FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_customSnapshot]];
213213
targetCellSnapshot = [targetCellSnapshotWrapped fb_parentCellSnapshot];
214214
CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].fb_visibleFrame;
215215

@@ -229,7 +229,7 @@ - (BOOL)fb_isEquivalentElementSnapshotVisible:(id<FBXCElementSnapshot>)snapshot
229229
return YES;
230230
}
231231

232-
id<FBXCElementSnapshot> appSnapshot = [self.application fb_takeSnapshot:YES];
232+
id<FBXCElementSnapshot> appSnapshot = [self.application fb_standardSnapshot];
233233
for (id<FBXCElementSnapshot> elementSnapshot in appSnapshot._allDescendants.copy) {
234234
FBXCElementSnapshotWrapper *wrappedElementSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:elementSnapshot];
235235
// We are comparing pre-scroll snapshot so frames are irrelevant.

WebDriverAgentLib/Categories/XCUIElement+FBTyping.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ - (void)fb_prepareForTextInputWithSnapshot:(FBXCElementSnapshotWrapper *)snapsho
9191
[FBLogger logFmt:@"Trying to tap the \"%@\" element to have it focused", snapshot.fb_description];
9292
[self tap];
9393
// It might take some time to update the UI
94-
[self fb_takeSnapshot:NO];
94+
[self fb_standardSnapshot];
9595
#endif
9696
}
9797

@@ -110,7 +110,7 @@ - (BOOL)fb_typeText:(NSString *)text
110110
frequency:(NSUInteger)frequency
111111
error:(NSError **)error
112112
{
113-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:NO];
113+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
114114
FBXCElementSnapshotWrapper *wrapped = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
115115
[self fb_prepareForTextInputWithSnapshot:wrapped];
116116
if (shouldClear && ![self fb_clearTextWithSnapshot:wrapped shouldPrepareForInput:NO error:error]) {
@@ -121,7 +121,7 @@ - (BOOL)fb_typeText:(NSString *)text
121121

122122
- (BOOL)fb_clearTextWithError:(NSError **)error
123123
{
124-
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:NO];
124+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
125125
return [self fb_clearTextWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot]
126126
shouldPrepareForInput:YES
127127
error:error];
@@ -178,7 +178,7 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot
178178
return NO;
179179
}
180180

181-
currentValue = [self fb_takeSnapshot:NO].value;
181+
currentValue = [self fb_standardSnapshot].value;
182182
if (nil != placeholderValue && [currentValue isEqualToString:placeholderValue]) {
183183
// Short circuit if only the placeholder value left
184184
return YES;

WebDriverAgentLib/Categories/XCUIElement+FBUID.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ - (unsigned long long)fb_accessibiltyId
2222
{
2323
return [FBElementUtils idWithAccessibilityElement:([self isKindOfClass:XCUIApplication.class]
2424
? [(XCUIApplication *)self accessibilityElement]
25-
: [self fb_takeSnapshot:NO].accessibilityElement)];
25+
: [self fb_standardSnapshot].accessibilityElement)];
2626
}
2727

2828
- (NSString *)fb_uid
2929
{
3030
return [self isKindOfClass:XCUIApplication.class]
3131
? [FBElementUtils uidWithAccessibilityElement:[(XCUIApplication *)self accessibilityElement]]
32-
: [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot:NO]].fb_uid;
32+
: [FBXCElementSnapshotWrapper ensureWrapped:[self fb_standardSnapshot]].fb_uid;
3333
}
3434

3535
@end

WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,50 @@ NS_ASSUME_NONNULL_BEGIN
1515

1616
@interface XCUIElement (FBUtilities)
1717

18+
/**
19+
Gets the most recent snapshot of the current element. The element will be
20+
automatically resolved if the snapshot is not available yet.
21+
Calls to this method mutate the `lastSnapshot` instance property.
22+
The snapshot is taken by the native API provided by XCTest.
23+
The maximum snapshot tree depth is set by `FBConfiguration.snapshotMaxDepth`
24+
25+
Snapshot specifics:
26+
- Most performant
27+
- Memory-friedly
28+
- `children` property is set to `nil` if not taken from XCUIApplication
29+
- `value` property is cut off to max 512 bytes
30+
31+
@return The recent snapshot of the element
32+
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
33+
*/
34+
- (id<FBXCElementSnapshot>)fb_standardSnapshot;
35+
36+
/**
37+
Gets the most recent snapshot of the current element. The element will be
38+
automatically resolved if the snapshot is not available yet.
39+
Calls to this method mutate the `lastSnapshot` instance property..
40+
The maximum snapshot tree depth is set by `FBConfiguration.snapshotMaxDepth`
41+
42+
Snapshot specifics:
43+
- Less performant in comparison to the standard one
44+
- `children` property is always defined
45+
- `value` property is not cut off
46+
47+
@return The recent snapshot of the element
48+
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
49+
*/
50+
- (id<FBXCElementSnapshot>)fb_customSnapshot;
51+
1852
/**
1953
Gets the most recent snapshot of the current element. The element will be
2054
automatically resolved if the snapshot is not available yet.
2155
Calls to this method mutate the `lastSnapshot` instance property..
2256
23-
@param inDepth Whether to resolve snapshot parents and children. Setting it to NO
24-
would improve the snapshotting performance
57+
@param maxDepth Allows to customize the maximum depth of the snapshot tree
2558
@return The recent snapshot of the element
2659
@throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made
2760
*/
28-
- (id<FBXCElementSnapshot>)fb_takeSnapshot:(BOOL)inDepth;
61+
- (id<FBXCElementSnapshot>)fb_customSnapshotWithMaxDepth:(NSUInteger)maxDepth;
2962

3063
/**
3164
Extracts the cached element snapshot from its query.

WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,23 @@
4444

4545
@implementation XCUIElement (FBUtilities)
4646

47-
- (id<FBXCElementSnapshot>)fb_takeSnapshot:(BOOL)inDepth
47+
- (id<FBXCElementSnapshot>)fb_takeSnapshot:(BOOL)isCustom maxDepth:(nullable NSNumber *)maxDepth
4848
{
4949
__block id<FBXCElementSnapshot> snapshot = nil;
5050
@autoreleasepool {
5151
NSError *error = nil;
52-
snapshot = inDepth && ![self isKindOfClass:XCUIApplication.class]
53-
? [self.fb_query fb_uniqueSnapshotWithError:&error]
54-
: (id<FBXCElementSnapshot>)[self snapshotWithError:&error];
52+
if (isCustom) {
53+
int previousMaxDepth = FBConfiguration.snapshotMaxDepth;
54+
if (nil != maxDepth) {
55+
FBConfiguration.snapshotMaxDepth = maxDepth.unsignedIntValue;
56+
}
57+
snapshot = [self.fb_query fb_uniqueSnapshotWithError:&error];
58+
if (nil != maxDepth) {
59+
FBConfiguration.snapshotMaxDepth = previousMaxDepth;
60+
}
61+
} else {
62+
snapshot = (id<FBXCElementSnapshot>)[self snapshotWithError:&error];
63+
}
5564
if (nil == snapshot) {
5665
NSString *hintText = @"Make sure the application UI has the expected state";
5766
if (nil != error && [error.localizedDescription containsString:@"Identity Binding"]) {
@@ -69,6 +78,21 @@ @implementation XCUIElement (FBUtilities)
6978
return self.lastSnapshot;
7079
}
7180

81+
- (id<FBXCElementSnapshot>)fb_standardSnapshot
82+
{
83+
return [self fb_takeSnapshot:NO maxDepth:nil];
84+
}
85+
86+
- (id<FBXCElementSnapshot>)fb_customSnapshot
87+
{
88+
return [self fb_takeSnapshot:YES maxDepth:nil];
89+
}
90+
91+
- (id<FBXCElementSnapshot>)fb_customSnapshotWithMaxDepth:(NSUInteger)maxDepth
92+
{
93+
return [self fb_takeSnapshot:YES maxDepth:@(maxDepth)];
94+
}
95+
7296
- (id<FBXCElementSnapshot>)fb_cachedSnapshot
7397
{
7498
return [self.query fb_cachedSnapshot];

0 commit comments

Comments
 (0)