appium-webdriveragent 4.10.5 → 4.10.7
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 +4 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +1 -1
- package/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +7 -36
- package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +10 -10
- package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +4 -3
- package/WebDriverAgentLib/Categories/XCUIElement+FBUID.h +8 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +6 -1
- package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +6 -3
- package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h +8 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +9 -4
- package/WebDriverAgentLib/Commands/FBFindElementCommands.m +2 -1
- package/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m +4 -0
- package/WebDriverAgentRunner-Runner.app.zip +0 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## [4.10.7](https://github.com/appium/WebDriverAgent/compare/v4.10.6...v4.10.7) (2022-11-24)
|
|
2
|
+
|
|
3
|
+
## [4.10.6](https://github.com/appium/WebDriverAgent/compare/v4.10.5...v4.10.6) (2022-11-23)
|
|
4
|
+
|
|
1
5
|
## [4.10.5](https://github.com/appium/WebDriverAgent/compare/v4.10.4...v4.10.5) (2022-11-22)
|
|
2
6
|
|
|
3
7
|
## [4.10.4](https://github.com/appium/WebDriverAgent/compare/v4.10.3...v4.10.4) (2022-11-22)
|
|
@@ -48,7 +48,7 @@ static char XCUIELEMENT_CACHE_ID_KEY;
|
|
|
48
48
|
uid = self.fb_uid;
|
|
49
49
|
} else {
|
|
50
50
|
id<FBXCElementSnapshot> snapshot = self.fb_cachedSnapshot ?: self.fb_takeSnapshot;
|
|
51
|
-
uid = [FBXCElementSnapshotWrapper
|
|
51
|
+
uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot];
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
objc_setAssociatedObject(self, &XCUIELEMENT_CACHE_ID_KEY, uid, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
#import "FBXCElementSnapshotWrapper+Helpers.h"
|
|
17
17
|
#import "FBXCodeCompatibility.h"
|
|
18
18
|
#import "XCUIElement+FBCaching.h"
|
|
19
|
+
#import "XCUIElement+FBUID.h"
|
|
19
20
|
#import "XCUIElement+FBUtilities.h"
|
|
20
21
|
#import "XCUIElement+FBWebDriverAttributes.h"
|
|
21
22
|
#import "XCUIElementQuery.h"
|
|
@@ -48,7 +49,8 @@
|
|
|
48
49
|
XCUIElementType type = [FBElementTypeTransformer elementTypeWithTypeName:className];
|
|
49
50
|
XCUIElementQuery *query = [self.fb_query descendantsMatchingType:type];
|
|
50
51
|
NSMutableArray *result = [NSMutableArray array];
|
|
51
|
-
[result addObjectsFromArray:[self.class fb_extractMatchingElementsFromQuery:query
|
|
52
|
+
[result addObjectsFromArray:[self.class fb_extractMatchingElementsFromQuery:query
|
|
53
|
+
shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch]];
|
|
52
54
|
id<FBXCElementSnapshot> cachedSnapshot = [self fb_cachedSnapshotWithQuery:query];
|
|
53
55
|
if (type == XCUIElementTypeAny || cachedSnapshot.elementType == type) {
|
|
54
56
|
if (shouldReturnAfterFirstMatch || result.count == 0) {
|
|
@@ -66,40 +68,10 @@
|
|
|
66
68
|
value:(NSString *)value
|
|
67
69
|
partialSearch:(BOOL)partialSearch
|
|
68
70
|
{
|
|
69
|
-
|
|
70
|
-
[self
|
|
71
|
-
return elements;
|
|
71
|
+
NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:(partialSearch ? @"%K CONTAINS %@" : @"%K == %@"), property, value];
|
|
72
|
+
return [self fb_descendantsMatchingPredicate:searchPredicate shouldReturnAfterFirstMatch:NO];
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
- (void)descendantsWithProperty:(NSString *)property value:(NSString *)value
|
|
75
|
-
partial:(BOOL)partialSearch
|
|
76
|
-
results:(NSMutableArray<XCUIElement *> *)results
|
|
77
|
-
{
|
|
78
|
-
if (partialSearch) {
|
|
79
|
-
NSString *text = [self fb_valueForWDAttributeName:property];
|
|
80
|
-
BOOL isString = [text isKindOfClass:[NSString class]];
|
|
81
|
-
if (isString && [text rangeOfString:value].location != NSNotFound) {
|
|
82
|
-
[results addObject:self];
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
85
|
-
if ([[self fb_valueForWDAttributeName:property] isEqual:value]) {
|
|
86
|
-
[results addObject:self];
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
property = [FBElementUtils wdAttributeNameForAttributeName:property];
|
|
91
|
-
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot,
|
|
92
|
-
NSDictionary<NSString *,id> * _Nullable bindings) {
|
|
93
|
-
FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
|
|
94
|
-
NSString *propertyValue = [NSString stringWithFormat:@"%@", [wrappedSnapshot fb_valueForWDAttributeName:property]];
|
|
95
|
-
return partialSearch ? [value containsString:propertyValue] : [value isEqualToString:propertyValue];
|
|
96
|
-
}];
|
|
97
|
-
XCUIElementQuery *query = [[self.fb_query descendantsMatchingType:XCUIElementTypeAny] matchingPredicate:predicate];
|
|
98
|
-
NSArray *childElements = query.fb_allMatches;
|
|
99
|
-
[results addObjectsFromArray:childElements];
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
75
|
#pragma mark - Search by Predicate String
|
|
104
76
|
|
|
105
77
|
- (NSArray<XCUIElement *> *)fb_descendantsMatchingPredicate:(NSPredicate *)predicate
|
|
@@ -138,7 +110,7 @@
|
|
|
138
110
|
matchingSnapshots = @[snapshot];
|
|
139
111
|
}
|
|
140
112
|
return [self fb_filterDescendantsWithSnapshots:matchingSnapshots
|
|
141
|
-
selfUID:[FBXCElementSnapshotWrapper
|
|
113
|
+
selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot]
|
|
142
114
|
onlyChildren:NO];
|
|
143
115
|
}
|
|
144
116
|
|
|
@@ -150,8 +122,7 @@
|
|
|
150
122
|
{
|
|
151
123
|
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot,
|
|
152
124
|
NSDictionary<NSString *,id> * _Nullable bindings) {
|
|
153
|
-
|
|
154
|
-
return [wrappedSnapshot.wdName isEqualToString:accessibilityId];
|
|
125
|
+
return [[FBXCElementSnapshotWrapper wdNameWithSnapshot:snapshot] isEqualToString:accessibilityId];
|
|
155
126
|
}];
|
|
156
127
|
return [self fb_descendantsMatchingPredicate:predicate
|
|
157
128
|
shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch];
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
|
|
35
35
|
@implementation FBXCElementSnapshotWrapper (FBIsVisible)
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
+ (NSString *)fb_uniqIdWithSnapshot:(id<FBXCElementSnapshot>)snapshot
|
|
38
38
|
{
|
|
39
|
-
return
|
|
39
|
+
return [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot] ?: [NSString stringWithFormat:@"%p", (void *)snapshot];
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
- (nullable NSNumber *)fb_cachedVisibilityValue
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
return nil;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
NSDictionary<NSString *, NSNumber *> *result = [
|
|
49
|
+
NSDictionary<NSString *, NSNumber *> *result = cache[@(self.generation)];
|
|
50
50
|
if (nil == result) {
|
|
51
51
|
// There is no need to keep the cached data for the previous generations
|
|
52
52
|
[cache removeAllObjects];
|
|
53
|
-
|
|
53
|
+
cache[@(self.generation)] = [NSMutableDictionary dictionary];
|
|
54
54
|
return nil;
|
|
55
55
|
}
|
|
56
|
-
return [
|
|
56
|
+
return result[[self.class fb_uniqIdWithSnapshot:self.snapshot]];
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
- (BOOL)fb_cacheVisibilityWithValue:(BOOL)isVisible
|
|
@@ -63,19 +63,19 @@
|
|
|
63
63
|
if (nil == cache) {
|
|
64
64
|
return isVisible;
|
|
65
65
|
}
|
|
66
|
-
NSMutableDictionary<NSString *, NSNumber *> *destination = [
|
|
66
|
+
NSMutableDictionary<NSString *, NSNumber *> *destination = cache[@(self.generation)];
|
|
67
67
|
if (nil == destination) {
|
|
68
68
|
return isVisible;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
NSNumber *visibleObj = [NSNumber numberWithBool:isVisible];
|
|
72
|
-
[
|
|
72
|
+
destination[[self.class fb_uniqIdWithSnapshot:self.snapshot]] = visibleObj;
|
|
73
73
|
if (isVisible && nil != ancestors) {
|
|
74
74
|
// if an element is visible then all its ancestors must be visible as well
|
|
75
75
|
for (id<FBXCElementSnapshot> ancestor in ancestors) {
|
|
76
|
-
NSString *ancestorId = [
|
|
77
|
-
if (nil == [
|
|
78
|
-
[
|
|
76
|
+
NSString *ancestorId = [self.class fb_uniqIdWithSnapshot:ancestor];
|
|
77
|
+
if (nil == destination[ancestorId]) {
|
|
78
|
+
destination[ancestorId] = visibleObj;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -41,13 +41,14 @@ static char XCUIELEMENT_IS_RESOLVED_NATIVELY_KEY;
|
|
|
41
41
|
XCUIElementQuery *query = [self isKindOfClass:XCUIApplication.class]
|
|
42
42
|
? self.application.fb_query
|
|
43
43
|
: [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny];
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
NSString *uid = nil == self.fb_cachedSnapshot
|
|
45
|
+
? self.fb_uid
|
|
46
|
+
: [FBXCElementSnapshotWrapper wdUIDWithSnapshot:(id)self.fb_cachedSnapshot];
|
|
46
47
|
if (nil == uid) {
|
|
47
48
|
return self;
|
|
48
49
|
}
|
|
49
50
|
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot, NSDictionary *bindings) {
|
|
50
|
-
return [[FBXCElementSnapshotWrapper
|
|
51
|
+
return [[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot] isEqualToString:uid];
|
|
51
52
|
}];
|
|
52
53
|
return (XCUIElement *)[query matchingPredicate:predicate].fb_firstMatch;
|
|
53
54
|
}
|
|
@@ -30,6 +30,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
30
30
|
/*! Represents unique internal element identifier, which is the same for an element and its snapshot */
|
|
31
31
|
@property (nonatomic, readonly) unsigned long long fb_accessibiltyId;
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
Fetches wdUID attribute value for the given snapshot instance
|
|
35
|
+
|
|
36
|
+
@param snapshot snapshot instance
|
|
37
|
+
@return UID attribute value
|
|
38
|
+
*/
|
|
39
|
+
+ (nullable NSString *)wdUIDWithSnapshot:(id<FBXCElementSnapshot>)snapshot;
|
|
40
|
+
|
|
33
41
|
@end
|
|
34
42
|
|
|
35
43
|
NS_ASSUME_NONNULL_END
|
|
@@ -38,9 +38,14 @@
|
|
|
38
38
|
return [FBElementUtils idWithAccessibilityElement:self.accessibilityElement];
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
+ (nullable NSString *)wdUIDWithSnapshot:(id<FBXCElementSnapshot>)snapshot
|
|
42
|
+
{
|
|
43
|
+
return [FBElementUtils uidWithAccessibilityElement:[snapshot accessibilityElement]];
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
- (NSString *)fb_uid
|
|
42
47
|
{
|
|
43
|
-
return [
|
|
48
|
+
return [self.class wdUIDWithSnapshot:self.snapshot];
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
@end
|
|
@@ -134,13 +134,16 @@
|
|
|
134
134
|
}
|
|
135
135
|
NSMutableArray<NSString *> *sortedIds = [NSMutableArray new];
|
|
136
136
|
for (id<FBXCElementSnapshot> snapshot in snapshots) {
|
|
137
|
-
|
|
137
|
+
NSString *uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot];
|
|
138
|
+
if (nil != uid) {
|
|
139
|
+
[sortedIds addObject:uid];
|
|
140
|
+
}
|
|
138
141
|
}
|
|
139
142
|
NSMutableArray<XCUIElement *> *matchedElements = [NSMutableArray array];
|
|
140
143
|
NSString *uid = selfUID;
|
|
141
144
|
if (nil == uid) {
|
|
142
145
|
uid = self.fb_isResolvedFromCache.boolValue
|
|
143
|
-
? [FBXCElementSnapshotWrapper
|
|
146
|
+
? [FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot]
|
|
144
147
|
: self.fb_uid;
|
|
145
148
|
}
|
|
146
149
|
if ([sortedIds containsObject:uid]) {
|
|
@@ -158,7 +161,7 @@
|
|
|
158
161
|
? [self.fb_query childrenMatchingType:type]
|
|
159
162
|
: [self.fb_query descendantsMatchingType:type];
|
|
160
163
|
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot, NSDictionary *bindings) {
|
|
161
|
-
return [sortedIds containsObject:
|
|
164
|
+
return [sortedIds containsObject:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot] ?: @""];
|
|
162
165
|
}];
|
|
163
166
|
query = [query matchingPredicate:predicate];
|
|
164
167
|
if (1 == snapshots.count) {
|
|
@@ -20,6 +20,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
20
20
|
|
|
21
21
|
@interface FBXCElementSnapshotWrapper (WebDriverAttributes) <FBElement>
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
Fetches wdName attribute value for the given snapshot instance
|
|
25
|
+
|
|
26
|
+
@param snapshot snapshot instance
|
|
27
|
+
@return wdName attribute value or nil
|
|
28
|
+
*/
|
|
29
|
+
+ (nullable NSString *)wdNameWithSnapshot:(id<FBXCElementSnapshot>)snapshot;
|
|
30
|
+
|
|
23
31
|
@end
|
|
24
32
|
|
|
25
33
|
NS_ASSUME_NONNULL_END
|
|
@@ -100,18 +100,23 @@
|
|
|
100
100
|
value = [NSString stringWithFormat:@"%@", value];
|
|
101
101
|
}
|
|
102
102
|
return value;
|
|
103
|
-
|
|
103
|
+
}
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
+ (NSString *)wdNameWithSnapshot:(id<FBXCElementSnapshot>)snapshot
|
|
106
106
|
{
|
|
107
|
-
NSString *identifier =
|
|
107
|
+
NSString *identifier = snapshot.identifier;
|
|
108
108
|
if (nil != identifier && identifier.length != 0) {
|
|
109
109
|
return identifier;
|
|
110
110
|
}
|
|
111
|
-
NSString *label =
|
|
111
|
+
NSString *label = snapshot.label;
|
|
112
112
|
return FBTransferEmptyStringToNil(label);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
- (NSString *)wdName
|
|
116
|
+
{
|
|
117
|
+
return [self.class wdNameWithSnapshot:self.snapshot];
|
|
118
|
+
}
|
|
119
|
+
|
|
115
120
|
- (NSString *)wdLabel
|
|
116
121
|
{
|
|
117
122
|
NSString *label = self.label;
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
#import "XCUIElement+FBClassChain.h"
|
|
23
23
|
#import "XCUIElement+FBFind.h"
|
|
24
24
|
#import "XCUIElement+FBIsVisible.h"
|
|
25
|
+
#import "XCUIElement+FBUID.h"
|
|
25
26
|
#import "XCUIElement+FBUtilities.h"
|
|
26
27
|
#import "XCUIElement+FBWebDriverAttributes.h"
|
|
27
28
|
|
|
@@ -88,7 +89,7 @@ static id<FBResponsePayload> FBNoSuchElementErrorResponseForRequest(FBRouteReque
|
|
|
88
89
|
&& [FBXCElementSnapshotWrapper ensureWrapped:snapshot].wdVisible;
|
|
89
90
|
}];
|
|
90
91
|
NSArray *cells = [element fb_filterDescendantsWithSnapshots:visibleCellSnapshots
|
|
91
|
-
selfUID:[FBXCElementSnapshotWrapper
|
|
92
|
+
selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:element.lastSnapshot]
|
|
92
93
|
onlyChildren:NO];
|
|
93
94
|
return FBResponseWithCachedElements(cells, request.session.elementCache, FBConfiguration.shouldUseCompactResponses);
|
|
94
95
|
}
|
|
@@ -52,6 +52,10 @@
|
|
|
52
52
|
|
|
53
53
|
+ (instancetype)fb_snapshotBlockPredicateWithPredicate:(NSPredicate *)input
|
|
54
54
|
{
|
|
55
|
+
if ([NSStringFromClass(input.class) isEqualToString:@"NSBlockPredicate"]) {
|
|
56
|
+
return input;
|
|
57
|
+
}
|
|
58
|
+
|
|
55
59
|
NSPredicate *wdPredicate = [self.class fb_formatSearchPredicate:input];
|
|
56
60
|
return [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject,
|
|
57
61
|
NSDictionary<NSString *,id> * _Nullable bindings) {
|
|
Binary file
|