appium-webdriveragent 4.10.7 → 4.10.9
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/XCUIApplication+FBHelpers.m +1 -2
- package/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +1 -1
- package/WebDriverAgentLib/Routing/FBElementCache.m +2 -2
- package/WebDriverAgentLib/Routing/FBResponsePayload.m +36 -32
- package/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m +3 -2
- package/WebDriverAgentLib/Utilities/FBMjpegServer.m +3 -5
- package/WebDriverAgentLib/Utilities/FBPasteboard.m +2 -2
- package/WebDriverAgentLib/Utilities/FBProtocolHelpers.h +3 -4
- package/WebDriverAgentLib/Utilities/FBProtocolHelpers.m +5 -5
- package/WebDriverAgentRunner-Runner.app.zip +0 -0
- package/WebDriverAgentTests/IntegrationTests/XCUIApplicationHelperTests.m +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## [4.10.9](https://github.com/appium/WebDriverAgent/compare/v4.10.8...v4.10.9) (2022-11-25)
|
|
2
|
+
|
|
3
|
+
## [4.10.8](https://github.com/appium/WebDriverAgent/compare/v4.10.7...v4.10.8) (2022-11-24)
|
|
4
|
+
|
|
1
5
|
## [4.10.7](https://github.com/appium/WebDriverAgent/compare/v4.10.6...v4.10.7) (2022-11-24)
|
|
2
6
|
|
|
3
7
|
## [4.10.6](https://github.com/appium/WebDriverAgent/compare/v4.10.5...v4.10.6) (2022-11-23)
|
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
#import "XCTestPrivateSymbols.h"
|
|
32
32
|
#import "XCTRunnerDaemonSession.h"
|
|
33
33
|
|
|
34
|
-
const static NSTimeInterval FBMinimumAppSwitchWait = 3.0;
|
|
35
34
|
static NSString* const FBUnknownBundleId = @"unknown";
|
|
36
35
|
|
|
37
36
|
|
|
@@ -92,7 +91,7 @@ static NSString* const FBUnknownBundleId = @"unknown";
|
|
|
92
91
|
if(![[XCUIDevice sharedDevice] fb_goToHomescreenWithError:error]) {
|
|
93
92
|
return NO;
|
|
94
93
|
}
|
|
95
|
-
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:MAX(duration,
|
|
94
|
+
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:MAX(duration, .0)]];
|
|
96
95
|
[self fb_activate];
|
|
97
96
|
return YES;
|
|
98
97
|
}
|
|
@@ -50,7 +50,7 @@ static char XCUIELEMENT_IS_RESOLVED_NATIVELY_KEY;
|
|
|
50
50
|
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id<FBXCElementSnapshot> snapshot, NSDictionary *bindings) {
|
|
51
51
|
return [[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot] isEqualToString:uid];
|
|
52
52
|
}];
|
|
53
|
-
return
|
|
53
|
+
return [query matchingPredicate:predicate].fb_firstMatch ?: self;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
@end
|
|
@@ -38,7 +38,7 @@ const int ELEMENT_CACHE_SIZE = 1024;
|
|
|
38
38
|
return nil;
|
|
39
39
|
}
|
|
40
40
|
_elementCache = [[LRUCache alloc] initWithCapacity:ELEMENT_CACHE_SIZE];
|
|
41
|
-
_elementsNeedReset =
|
|
41
|
+
_elementsNeedReset = NO;
|
|
42
42
|
return self;
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -50,8 +50,8 @@ const int ELEMENT_CACHE_SIZE = 1024;
|
|
|
50
50
|
}
|
|
51
51
|
@synchronized (self.elementCache) {
|
|
52
52
|
[self.elementCache setObject:element forKey:uuid];
|
|
53
|
+
self.elementsNeedReset = YES;
|
|
53
54
|
}
|
|
54
|
-
self.elementsNeedReset = YES;
|
|
55
55
|
return uuid;
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
#import "FBProtocolHelpers.h"
|
|
19
19
|
#import "XCUIElementQuery.h"
|
|
20
20
|
#import "XCUIElement+FBResolve.h"
|
|
21
|
+
#import "XCUIElement+FBUID.h"
|
|
21
22
|
#import "XCUIElement+FBUtilities.h"
|
|
22
23
|
#import "XCUIElement+FBWebDriverAttributes.h"
|
|
23
24
|
|
|
@@ -39,7 +40,7 @@ id<FBResponsePayload> FBResponseWithCachedElement(XCUIElement *element, FBElemen
|
|
|
39
40
|
? YES
|
|
40
41
|
: FBSession.activeSession.useNativeCachingStrategy;
|
|
41
42
|
[elementCache storeElement:(useNativeCachingStrategy ? element : element.fb_stableInstance)];
|
|
42
|
-
return FBResponseWithStatus([FBCommandStatus okWithValue:
|
|
43
|
+
return FBResponseWithStatus([FBCommandStatus okWithValue:FBDictionaryResponseWithElement(element, compact)]);
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
id<FBResponsePayload> FBResponseWithCachedElements(NSArray<XCUIElement *> *elements, FBElementCache *elementCache, BOOL compact)
|
|
@@ -65,7 +66,8 @@ id<FBResponsePayload> FBResponseWithUnknownErrorFormat(NSString *format, ...)
|
|
|
65
66
|
va_list argList;
|
|
66
67
|
va_start(argList, format);
|
|
67
68
|
NSString *errorMessage = [[NSString alloc] initWithFormat:format arguments:argList];
|
|
68
|
-
id<FBResponsePayload> payload = FBResponseWithStatus([FBCommandStatus unknownErrorWithMessage:errorMessage
|
|
69
|
+
id<FBResponsePayload> payload = FBResponseWithStatus([FBCommandStatus unknownErrorWithMessage:errorMessage
|
|
70
|
+
traceback:nil]);
|
|
69
71
|
va_end(argList);
|
|
70
72
|
return payload;
|
|
71
73
|
}
|
|
@@ -77,13 +79,12 @@ id<FBResponsePayload> FBResponseWithStatus(FBCommandStatus *status)
|
|
|
77
79
|
if (nil == status.error) {
|
|
78
80
|
response[@"value"] = status.value ?: NSNull.null;
|
|
79
81
|
} else {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
response[@"value"] = @{
|
|
83
|
+
@"error": (id)status.error,
|
|
84
|
+
@"message": status.message ?: @"",
|
|
85
|
+
@"traceback": status.traceback ?: @""
|
|
86
|
+
};
|
|
85
87
|
}
|
|
86
|
-
|
|
87
88
|
return [[FBResponseJSONPayload alloc] initWithDictionary:response.copy
|
|
88
89
|
httpStatusCode:status.statusCode];
|
|
89
90
|
}
|
|
@@ -97,31 +98,34 @@ inline NSDictionary *FBDictionaryResponseWithElement(XCUIElement *element, BOOL
|
|
|
97
98
|
if (nil == snapshot) {
|
|
98
99
|
snapshot = element.lastSnapshot ?: element.fb_takeSnapshot;
|
|
99
100
|
}
|
|
101
|
+
NSDictionary *compactResult = FBToElementDict((NSString *)[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]);
|
|
102
|
+
if (compact) {
|
|
103
|
+
return compactResult;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
NSMutableDictionary *result = compactResult.mutableCopy;
|
|
100
107
|
FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot];
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
NSString *attributeName = [field substringFromIndex:[arbitraryAttrPrefix length]];
|
|
122
|
-
dictionary[field] = [wrappedSnapshot fb_valueForWDAttributeName:attributeName] ?: [NSNull null];
|
|
123
|
-
}
|
|
108
|
+
NSArray *fields = [FBConfiguration.elementResponseAttributes componentsSeparatedByString:@","];
|
|
109
|
+
for (NSString *field in fields) {
|
|
110
|
+
// 'name' here is the w3c-approved identifier for what we mean by 'type'
|
|
111
|
+
if ([field isEqualToString:@"name"] || [field isEqualToString:@"type"]) {
|
|
112
|
+
result[field] = wrappedSnapshot.wdType;
|
|
113
|
+
} else if ([field isEqualToString:@"text"]) {
|
|
114
|
+
result[field] = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel) ?: [NSNull null];
|
|
115
|
+
} else if ([field isEqualToString:@"rect"]) {
|
|
116
|
+
result[field] = wrappedSnapshot.wdRect;
|
|
117
|
+
} else if ([field isEqualToString:@"enabled"]) {
|
|
118
|
+
result[field] = @(wrappedSnapshot.wdEnabled);
|
|
119
|
+
} else if ([field isEqualToString:@"displayed"]) {
|
|
120
|
+
result[field] = @(wrappedSnapshot.wdVisible);
|
|
121
|
+
} else if ([field isEqualToString:@"selected"]) {
|
|
122
|
+
result[field] = @(wrappedSnapshot.wdSelected);
|
|
123
|
+
} else if ([field isEqualToString:@"label"]) {
|
|
124
|
+
result[field] = wrappedSnapshot.wdLabel ?: [NSNull null];
|
|
125
|
+
} else if ([field hasPrefix:arbitraryAttrPrefix]) {
|
|
126
|
+
NSString *attributeName = [field substringFromIndex:[arbitraryAttrPrefix length]];
|
|
127
|
+
result[field] = [wrappedSnapshot fb_valueForWDAttributeName:attributeName] ?: [NSNull null];
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
|
-
return
|
|
130
|
+
return result.copy;
|
|
127
131
|
}
|
|
@@ -448,9 +448,10 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
|
|
|
448
448
|
[result addObject:touchItem];
|
|
449
449
|
continue;
|
|
450
450
|
}
|
|
451
|
+
NSMutableDictionary *elementDict = FBCleanupElements(options).mutableCopy;
|
|
452
|
+
[elementDict addEntriesFromDictionary:FBToElementDict(element)];
|
|
451
453
|
NSMutableDictionary<NSString *, id> *processedItem = touchItem.mutableCopy;
|
|
452
|
-
[
|
|
453
|
-
forKey:FB_OPTIONS_KEY];
|
|
454
|
+
processedItem[FB_OPTIONS_KEY] = elementDict.copy;
|
|
454
455
|
[result addObject:processedItem.copy];
|
|
455
456
|
}
|
|
456
457
|
return [[result reverseObjectEnumerator] allObjects];
|
|
@@ -31,7 +31,6 @@ static const char *QUEUE_NAME = "JPEG Screenshots Provider Queue";
|
|
|
31
31
|
|
|
32
32
|
@property (nonatomic, readonly) dispatch_queue_t backgroundQueue;
|
|
33
33
|
@property (nonatomic, readonly) NSMutableArray<GCDAsyncSocket *> *listeningClients;
|
|
34
|
-
@property (nonatomic, readonly) mach_timebase_info_data_t timebaseInfo;
|
|
35
34
|
@property (nonatomic, readonly) FBImageIOScaler *imageScaler;
|
|
36
35
|
@property (nonatomic, readonly) long long mainScreenID;
|
|
37
36
|
|
|
@@ -46,7 +45,6 @@ static const char *QUEUE_NAME = "JPEG Screenshots Provider Queue";
|
|
|
46
45
|
_listeningClients = [NSMutableArray array];
|
|
47
46
|
dispatch_queue_attr_t queueAttributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
|
|
48
47
|
_backgroundQueue = dispatch_queue_create(QUEUE_NAME, queueAttributes);
|
|
49
|
-
mach_timebase_info(&_timebaseInfo);
|
|
50
48
|
dispatch_async(_backgroundQueue, ^{
|
|
51
49
|
[self streamScreenshot];
|
|
52
50
|
});
|
|
@@ -58,8 +56,8 @@ static const char *QUEUE_NAME = "JPEG Screenshots Provider Queue";
|
|
|
58
56
|
|
|
59
57
|
- (void)scheduleNextScreenshotWithInterval:(uint64_t)timerInterval timeStarted:(uint64_t)timeStarted
|
|
60
58
|
{
|
|
61
|
-
uint64_t timeElapsed =
|
|
62
|
-
int64_t nextTickDelta = timerInterval - timeElapsed
|
|
59
|
+
uint64_t timeElapsed = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) - timeStarted;
|
|
60
|
+
int64_t nextTickDelta = timerInterval - timeElapsed;
|
|
63
61
|
if (nextTickDelta > 0) {
|
|
64
62
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, nextTickDelta), self.backgroundQueue, ^{
|
|
65
63
|
[self streamScreenshot];
|
|
@@ -81,7 +79,7 @@ static const char *QUEUE_NAME = "JPEG Screenshots Provider Queue";
|
|
|
81
79
|
|
|
82
80
|
NSUInteger framerate = FBConfiguration.mjpegServerFramerate;
|
|
83
81
|
uint64_t timerInterval = (uint64_t)(1.0 / ((0 == framerate || framerate > MAX_FPS) ? MAX_FPS : framerate) * NSEC_PER_SEC);
|
|
84
|
-
uint64_t timeStarted =
|
|
82
|
+
uint64_t timeStarted = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW);
|
|
85
83
|
@synchronized (self.listeningClients) {
|
|
86
84
|
if (0 == self.listeningClients.count) {
|
|
87
85
|
[self scheduleNextScreenshotWithInterval:timerInterval timeStarted:timeStarted];
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
pasteboardContent = result;
|
|
95
95
|
didFinishGetPasteboard = YES;
|
|
96
96
|
});
|
|
97
|
-
uint64_t timeStarted =
|
|
97
|
+
uint64_t timeStarted = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW);
|
|
98
98
|
while (!didFinishGetPasteboard) {
|
|
99
99
|
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:ALERT_CHECK_INTERVAL_SEC]];
|
|
100
100
|
if (didFinishGetPasteboard) {
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
FBAlert *alert = [FBAlert alertWithElement:alertElement];
|
|
107
107
|
[alert acceptWithError:nil];
|
|
108
108
|
}
|
|
109
|
-
uint64_t timeElapsed =
|
|
109
|
+
uint64_t timeElapsed = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) - timeStarted;
|
|
110
110
|
if (timeElapsed / NSEC_PER_SEC > timeout) {
|
|
111
111
|
NSString *description = [NSString stringWithFormat:@"Cannot handle pasteboard alert within %@s timeout", @(timeout)];
|
|
112
112
|
if (error) {
|
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
NS_ASSUME_NONNULL_BEGIN
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
|
|
15
|
+
Prepares an element dictionary, which could be then used in hybrid W3C/JWP responses
|
|
16
16
|
|
|
17
|
-
@param dst The target dictionary. It is NOT mutated
|
|
18
17
|
@param element Either element identifier or element object itself
|
|
19
|
-
@returns The
|
|
18
|
+
@returns The resulting dictionary
|
|
20
19
|
*/
|
|
21
|
-
NSDictionary *
|
|
20
|
+
NSDictionary<NSString *, id> *FBToElementDict(id element);
|
|
22
21
|
|
|
23
22
|
/**
|
|
24
23
|
Extracts element uuid from dictionary
|
|
@@ -20,12 +20,12 @@ static NSString *const ALWAYS_MATCH_KEY = @"alwaysMatch";
|
|
|
20
20
|
static NSString *const FIRST_MATCH_KEY = @"firstMatch";
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
NSDictionary *
|
|
23
|
+
NSDictionary<NSString *, id> *FBToElementDict(id element)
|
|
24
24
|
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
return @{
|
|
26
|
+
W3C_ELEMENT_KEY: element,
|
|
27
|
+
JSONWP_ELEMENT_KEY: element
|
|
28
|
+
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
id FBExtractElement(NSDictionary *src)
|
|
Binary file
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
- (void)testDeactivateApplication
|
|
47
47
|
{
|
|
48
48
|
NSError *error;
|
|
49
|
-
uint64_t timeStarted =
|
|
49
|
+
uint64_t timeStarted = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW);
|
|
50
50
|
NSTimeInterval backgroundDuration = 5.0;
|
|
51
51
|
XCTAssertTrue([self.testedApplication fb_deactivateWithDuration:backgroundDuration error:&error]);
|
|
52
|
-
NSTimeInterval timeElapsed = (
|
|
52
|
+
NSTimeInterval timeElapsed = (clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) - timeStarted) / NSEC_PER_SEC;
|
|
53
53
|
XCTAssertNil(error);
|
|
54
54
|
XCTAssertEqualWithAccuracy(timeElapsed, backgroundDuration, 3.0);
|
|
55
55
|
XCTAssertTrue(self.testedApplication.buttons[@"Alerts"].exists);
|