Skip to content

Commit 696feee

Browse files
committed
update
1 parent e674560 commit 696feee

File tree

68 files changed

+1126
-1606
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1126
-1606
lines changed

CHANGELOG.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1+
## [9.0.3](https://github.com/appium/WebDriverAgent/compare/v9.0.2...v9.0.3) (2025-02-05)
2+
3+
### Bug Fixes
4+
5+
* add nullable signature ([#979](https://github.com/appium/WebDriverAgent/issues/979)) ([34b303c](https://github.com/appium/WebDriverAgent/commit/34b303c4e226d6a75a45a14eee7ca5e253e67737))
6+
7+
## [9.0.2](https://github.com/appium/WebDriverAgent/compare/v9.0.1...v9.0.2) (2025-02-03)
8+
9+
### Bug Fixes
10+
11+
* update docs link in xcodebuild error message ([#978](https://github.com/appium/WebDriverAgent/issues/978)) ([ea3863a](https://github.com/appium/WebDriverAgent/commit/ea3863a67d5cfa8bc2e48a1dc2c59052acd47937))
12+
13+
## [9.0.1](https://github.com/appium/WebDriverAgent/compare/v9.0.0...v9.0.1) (2025-01-17)
14+
15+
### Miscellaneous Chores
16+
17+
* Optimize stable instance retrieval ([#973](https://github.com/appium/WebDriverAgent/issues/973)) ([f2c752d](https://github.com/appium/WebDriverAgent/commit/f2c752db4707b3864efb62b95b64abb487d28e4b))
18+
19+
## [9.0.0](https://github.com/appium/WebDriverAgent/compare/v8.12.2...v9.0.0) (2025-01-16)
20+
21+
### ⚠ BREAKING CHANGES
22+
23+
* snapshotTimeout and customSnapshotTimeout settings have been removed as a result of the custom snapshotting logic removal
24+
25+
### Features
26+
27+
* Refactor snapshotting mechanism ([#970](https://github.com/appium/WebDriverAgent/issues/970)) ([08f1306](https://github.com/appium/WebDriverAgent/commit/08f13060119c710f53b34a98c95683287c0365a0))
28+
29+
## [8.12.2](https://github.com/appium/WebDriverAgent/compare/v8.12.1...v8.12.2) (2025-01-13)
30+
31+
### Miscellaneous Chores
32+
33+
* Exclude element visibility and accessibility info from the accessibility audit details ([#968](https://github.com/appium/WebDriverAgent/issues/968)) ([f62afc3](https://github.com/appium/WebDriverAgent/commit/f62afc372c123bdd8dd7bb493f653bb128144d24))
34+
135
## [8.12.1](https://github.com/appium/WebDriverAgent/compare/v8.12.0...v8.12.1) (2025-01-03)
236

337
### Miscellaneous Chores

PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
- (void)_XCT_requestElementAtPoint:(CGPoint)arg1 reply:(void (^)(id/*XCAccessibilityElement*/, NSError *))arg2;
2828
- (void)_XCT_fetchParameterizedAttributeForElement:(id/*XCAccessibilityElement*/)arg1 attributes:(NSNumber *)arg2 parameter:(id)arg3 reply:(void (^)(id, NSError *))arg4;
2929
- (void)_XCT_setAttribute:(NSNumber *)arg1 value:(id)arg2 element:(id/*XCAccessibilityElement*/)arg3 reply:(void (^)(BOOL, NSError *))arg4;
30+
- (void)_XCT_fetchAttributes:(id)attributes forElement:(id)element reply:(void (^)(NSDictionary *, NSError *))reply;
3031
- (void)_XCT_fetchAttributesForElement:(id/*XCAccessibilityElement*/)arg1 attributes:(NSArray *)arg2 reply:(void (^)(NSDictionary *, NSError *))arg3;
3132
- (void)_XCT_terminateApplicationWithBundleID:(NSString *)arg1 completion:(void (^)(NSError *))arg2;
3233
- (void)_XCT_performAccessibilityAction:(int)arg1 onElement:(id/*XCAccessibilityElement*/)arg2 withValue:(id)arg3 reply:(void (^)(NSError *))arg4;

PrivateHeaders/XCTest/XCUIScreen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@
2424
- (id)initWithDisplayID:(long long)arg1 isMainScreen:(_Bool)arg2 device:(id)arg3 screenDataSource:(id)arg4;
2525

2626
@end
27+

WebDriverAgent.xcodeproj/project.pbxproj

Lines changed: 135 additions & 183 deletions
Large diffs are not rendered by default.

WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ NS_ASSUME_NONNULL_BEGIN
5858
5959
@param attribute attribute's accessibility identifier. Can be one of
6060
`XC_kAXXCAttribute`-prefixed attribute names.
61-
@return value for given accessibility property identifier
61+
@param error Error instance in case of a failure
62+
@return value for given accessibility property identifier or nil in case of failure
6263
*/
63-
- (nullable id)fb_attributeValue:(NSString *)attribute;
64+
- (nullable id)fb_attributeValue:(NSString *)attribute
65+
error:(NSError **)error;
6466

6567
/**
6668
Method used to determine whether given element matches receiver by comparing it's parameters except frame.
@@ -87,13 +89,6 @@ NS_ASSUME_NONNULL_BEGIN
8789
/**! Human-readable snapshot description */
8890
- (NSString *)fb_description;
8991

90-
/**
91-
Returns the snapshot visibleFrame with a fallback to direct attribute retrieval from FBXCAXClient in case of a snapshot fault (nil visibleFrame)
92-
93-
@return the snapshot visibleFrame
94-
*/
95-
- (CGRect)fb_visibleFrameWithFallback;
96-
9792
/**
9893
Wrapper for Apple's hitpoint, thats resolves few known issues
9994

WebDriverAgentLib/Categories/FBXCElementSnapshotWrapper+Helpers.m

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,20 @@
1010
#import "FBXCElementSnapshotWrapper+Helpers.h"
1111

1212
#import "FBFindElementCommands.h"
13+
#import "FBErrorBuilder.h"
1314
#import "FBRunLoopSpinner.h"
1415
#import "FBLogger.h"
1516
#import "FBXCElementSnapshot.h"
17+
#import "FBXCTestDaemonsProxy.h"
1618
#import "FBXCAXClientProxy.h"
1719
#import "XCTestDriver.h"
1820
#import "XCTestPrivateSymbols.h"
1921
#import "XCUIElement.h"
2022
#import "XCUIElement+FBWebDriverAttributes.h"
2123
#import "XCUIHitPointResult.h"
2224

25+
#define ATTRIBUTE_FETCH_WARN_TIME_LIMIT 0.05
26+
2327
inline static BOOL isSnapshotTypeAmongstGivenTypes(id<FBXCElementSnapshot> snapshot,
2428
NSArray<NSNumber *> *types);
2529

@@ -65,10 +69,17 @@ - (NSString *)fb_description
6569
}
6670

6771
- (id)fb_attributeValue:(NSString *)attribute
72+
error:(NSError **)error
6873
{
74+
NSDate *start = [NSDate date];
6975
NSDictionary *result = [FBXCAXClientProxy.sharedClient attributesForElement:[self accessibilityElement]
70-
attributes:@[attribute]];
71-
return result[attribute];
76+
attributes:@[attribute]
77+
error:error];
78+
NSTimeInterval elapsed = ABS([start timeIntervalSinceNow]);
79+
if (elapsed > ATTRIBUTE_FETCH_WARN_TIME_LIMIT) {
80+
NSLog(@"! Fetching of %@ value for %@ took %@s", attribute, self.fb_description, @(elapsed));
81+
}
82+
return [result objectForKey:attribute];
7283
}
7384

7485
inline static BOOL areValuesEqual(id value1, id value2);
@@ -140,29 +151,6 @@ - (BOOL)fb_framelessFuzzyMatchesElement:(id<FBXCElementSnapshot>)snapshot
140151
return targetCellSnapshot;
141152
}
142153

143-
- (CGRect)fb_visibleFrameWithFallback
144-
{
145-
CGRect thisVisibleFrame = [self visibleFrame];
146-
if (!CGRectIsEmpty(thisVisibleFrame)) {
147-
return thisVisibleFrame;
148-
}
149-
150-
NSDictionary *visibleFrameDict = (NSDictionary*)[self fb_attributeValue:@"XC_kAXXCAttributeVisibleFrame"];
151-
if (visibleFrameDict == nil) {
152-
return thisVisibleFrame;
153-
}
154-
155-
id x = [visibleFrameDict objectForKey:@"X"];
156-
id y = [visibleFrameDict objectForKey:@"Y"];
157-
id height = [visibleFrameDict objectForKey:@"Height"];
158-
id width = [visibleFrameDict objectForKey:@"Width"];
159-
if (x != nil && y != nil && height != nil && width != nil) {
160-
return CGRectMake([x doubleValue], [y doubleValue], [width doubleValue], [height doubleValue]);
161-
}
162-
163-
return thisVisibleFrame;
164-
}
165-
166154
- (NSValue *)fb_hitPoint
167155
{
168156
NSError *error;

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;
55+
id<FBXCElementSnapshot> snapshot = candidate.fb_cachedSnapshot ?: [candidate fb_takeSnapshot:YES];
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;
76+
id<FBXCElementSnapshot> alertSnapshot = alert.fb_cachedSnapshot ?: [alert fb_takeSnapshot:YES];
7777

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

WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040

4141
static NSString* const FBUnknownBundleId = @"unknown";
4242

43+
static NSString* const FBExclusionAttributeFrame = @"frame";
44+
static NSString* const FBExclusionAttributeEnabled = @"enabled";
45+
static NSString* const FBExclusionAttributeVisible = @"visible";
46+
static NSString* const FBExclusionAttributeAccessible = @"accessible";
47+
static NSString* const FBExclusionAttributeFocused = @"focused";
48+
49+
4350
_Nullable id extractIssueProperty(id issue, NSString *propertyName) {
4451
SEL selector = NSSelectorFromString(propertyName);
4552
NSMethodSignature *methodSignature = [issue methodSignatureForSelector:selector];
@@ -88,6 +95,17 @@ _Nullable id extractIssueProperty(id issue, NSString *propertyName) {
8895
return result;
8996
}
9097

98+
NSDictionary<NSString *, NSString *> *customExclusionAttributesMap(void) {
99+
static dispatch_once_t onceToken;
100+
static NSDictionary *result;
101+
dispatch_once(&onceToken, ^{
102+
result = @{
103+
FBExclusionAttributeVisible: FB_XCAXAIsVisibleAttributeName,
104+
FBExclusionAttributeAccessible: FB_XCAXAIsElementAttributeName,
105+
};
106+
});
107+
return result;
108+
}
91109

92110
@implementation XCUIApplication (FBHelpers)
93111

@@ -156,25 +174,23 @@ - (NSDictionary *)fb_tree
156174
return [self fb_tree:nil];
157175
}
158176

159-
- (NSDictionary *)fb_tree:(nullable NSSet<NSString *> *) excludedAttributes
177+
- (NSDictionary *)fb_tree:(nullable NSSet<NSString *> *)excludedAttributes
160178
{
161-
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
162-
? self.lastSnapshot
163-
: [self fb_snapshotWithAllAttributesAndMaxDepth:nil];
164-
return [self.class dictionaryForElement:snapshot recursive:YES excludedAttributes:excludedAttributes];
179+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
180+
return [self.class dictionaryForElement:snapshot
181+
recursive:YES
182+
excludedAttributes:excludedAttributes];
165183
}
166184

167185
- (NSDictionary *)fb_accessibilityTree
168186
{
169-
id<FBXCElementSnapshot> snapshot = self.fb_isResolvedFromCache.boolValue
170-
? self.lastSnapshot
171-
: [self fb_snapshotWithAllAttributesAndMaxDepth:nil];
187+
id<FBXCElementSnapshot> snapshot = [self fb_takeSnapshot:YES];
172188
return [self.class accessibilityInfoForElement:snapshot];
173189
}
174190

175191
+ (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot
176192
recursive:(BOOL)recursive
177-
excludedAttributes:(nullable NSSet<NSString *> *) excludedAttributes
193+
excludedAttributes:(nullable NSSet<NSString *> *)excludedAttributes
178194
{
179195
NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
180196
info[@"type"] = [FBElementTypeTransformer shortStringWithElementType:snapshot.elementType];
@@ -186,27 +202,27 @@ + (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot
186202
info[@"rect"] = wrappedSnapshot.wdRect;
187203

188204
NSDictionary<NSString *, NSString * (^)(void)> *attributeBlocks = @{
189-
@"frame": ^{
205+
FBExclusionAttributeFrame: ^{
190206
return NSStringFromCGRect(wrappedSnapshot.wdFrame);
191207
},
192-
@"enabled": ^{
208+
FBExclusionAttributeEnabled: ^{
193209
return [@([wrappedSnapshot isWDEnabled]) stringValue];
194210
},
195-
@"visible": ^{
211+
FBExclusionAttributeVisible: ^{
196212
return [@([wrappedSnapshot isWDVisible]) stringValue];
197213
},
198-
@"accessible": ^{
214+
FBExclusionAttributeAccessible: ^{
199215
return [@([wrappedSnapshot isWDAccessible]) stringValue];
200216
},
201-
@"focused": ^{
217+
FBExclusionAttributeFocused: ^{
202218
return [@([wrappedSnapshot isWDFocused]) stringValue];
203219
}
204220
};
205221

206222
for (NSString *key in attributeBlocks) {
207223
if (excludedAttributes == nil || ![excludedAttributes containsObject:key]) {
208224
NSString *value = ((NSString * (^)(void))attributeBlocks[key])();
209-
if ([key isEqualToString:@"frame"]) {
225+
if ([key isEqualToString:FBExclusionAttributeFrame]) {
210226
info[key] = value;
211227
} else {
212228
info[[NSString stringWithFormat:@"is%@", [key capitalizedString]]] = value;
@@ -396,6 +412,8 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray<NSString *> *)keyNames
396412
return nil;
397413
}
398414

415+
// These custom attributes could take too long to fetch, thus excluded
416+
NSSet *customAttributesToExclude = [NSSet setWithArray:[customExclusionAttributesMap() allKeys]];
399417
NSMutableArray<NSDictionary *> *resultArray = [NSMutableArray array];
400418
NSMethodSignature *methodSignature = [self methodSignatureForSelector:selector];
401419
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
@@ -411,9 +429,11 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray<NSString *> *)keyNames
411429

412430
id extractedElement = extractIssueProperty(issue, @"element");
413431

414-
id<FBXCElementSnapshot> elementSnapshot = [extractedElement fb_takeSnapshot];
415-
NSDictionary *elementAttributes = elementSnapshot
416-
? [self.class dictionaryForElement:elementSnapshot recursive:NO excludedAttributes:nil]
432+
id<FBXCElementSnapshot> elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_takeSnapshot:NO];
433+
NSDictionary *elementAttributes = elementSnapshot
434+
? [self.class dictionaryForElement:elementSnapshot
435+
recursive:NO
436+
excludedAttributes:customAttributesToExclude]
417437
: @{};
418438

419439
[resultArray addObject:@{

WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ typedef NS_ENUM(NSUInteger, FBUIInterfaceAppearance) {
6868
@return Device screenshot as PNG-encoded data or nil in case of failure
6969
*/
7070
- (nullable NSData *)fb_screenshotWithError:(NSError*__autoreleasing*)error;
71-
//- (nullable NSData *)uu_screenshotWithError:(NSError*__autoreleasing*)error;
72-
//- (nullable NSData *)uu_screenshotWithSize:(CGRect)rect andQuality:(NSUInteger)q andError:(NSError*__autoreleasing*)error;
7371

7472
/**
7573
Returns device's current wifi ip4 address

WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -99,68 +99,6 @@ - (BOOL)fb_unlockScreen:(NSError **)error
9999
} error:error];
100100
}
101101

102-
103-
//- (NSData *)uu_screenshotWithSize:(CGRect)rect andQuality:(NSUInteger)q andError:(NSError*__autoreleasing*)error
104-
//{
105-
// Class xcScreenClass = objc_lookUpClass("XCUIScreen");
106-
// XCUIApplication *application = FBApplication.fb_activeApplication;
107-
// if (application) {
108-
//
109-
// }
110-
// NSUInteger quality = 2;
111-
// CGRect screenRect = CGRectZero;
112-
//
113-
// if (rect.origin.x < 0 || rect.origin.y < 0 || (0.0 == rect.size.height && 0.0 == rect.size.width)) {
114-
// XCUIApplication *app = FBApplication.fb_activeApplication;
115-
// CGSize screenSize = FBAdjustDimensionsForApplication(app.frame.size, app.interfaceOrientation);
116-
// screenRect = CGRectMake(0, 0, screenSize.width, screenSize.height);
117-
// } else {
118-
// screenRect = rect;
119-
// }
120-
//
121-
// if (0 < q && q < 3) {
122-
// quality = q;
123-
// }
124-
//
125-
// XCUIScreen *mainScreen = (XCUIScreen *)[xcScreenClass mainScreen];
126-
//
127-
// NSData *result = nil;
128-
// if ( [[UIDevice currentDevice].systemVersion doubleValue] <= 9.5 ) {
129-
// result = [[mainScreen screenshot] PNGRepresentation];
130-
// } else {
131-
// result = [mainScreen screenshotDataForQuality:quality rect:screenRect error:error];
132-
// }
133-
// if (nil == result) {
134-
// return nil;
135-
// }
136-
//
137-
// return result;
138-
//}
139-
140-
//- (NSData *)uu_screenshotWithError:(NSError*__autoreleasing*)error
141-
//{
142-
// XCUIApplication *app = FBApplication.fb_activeApplication;
143-
// Class xcScreenClass = objc_lookUpClass("XCUIScreen");
144-
// NSData *result = nil;
145-
// XCUIScreen *mainScreen = (XCUIScreen *)[xcScreenClass mainScreen];
146-
// if ( [[UIDevice currentDevice].systemVersion doubleValue] <= 11 ) {
147-
// result = [[mainScreen screenshot] PNGRepresentation];
148-
// } else {
149-
// CGSize screenSize = FBAdjustDimensionsForApplication(app.frame.size, app.interfaceOrientation);
150-
// // https://developer.apple.com/documentation/xctest/xctimagequality?language=objc
151-
// // Select lower quality, since XCTest crashes randomly if the maximum quality (zero value) is selected
152-
// // and the resulting screenshot does not fit the memory buffer preallocated for it by the operating system
153-
// NSUInteger quality = 2;
154-
// CGRect screenRect = CGRectMake(0, 0, screenSize.width, screenSize.height);
155-
// result = [mainScreen screenshotDataForQuality:quality rect:screenRect error:error];
156-
// }
157-
// if (nil == result) {
158-
// return nil;
159-
// }
160-
//
161-
// return result;
162-
//}
163-
164102
- (NSData *)fb_screenshotWithError:(NSError*__autoreleasing*)error
165103
{
166104
return [FBScreenshot takeInOriginalResolutionWithQuality:FBConfiguration.screenshotQuality

0 commit comments

Comments
 (0)