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 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, FBMinimumAppSwitchWait)]];
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 (XCUIElement *)[query matchingPredicate:predicate].fb_firstMatch;
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 = YES;
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: FBDictionaryResponseWithElement(element, compact)]);
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 traceback:nil]);
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
- NSMutableDictionary* value = [NSMutableDictionary dictionary];
81
- value[@"error"] = status.error;
82
- value[@"message"] = status.message ?: @"";
83
- value[@"traceback"] = status.traceback ?: @"";
84
- response[@"value"] = value.copy;
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
- NSMutableDictionary *dictionary = FBInsertElement(@{}, (NSString *)wrappedSnapshot.wdUID).mutableCopy;
102
- if (!compact) {
103
- NSArray *fields = [FBConfiguration.elementResponseAttributes componentsSeparatedByString:@","];
104
- for (NSString *field in fields) {
105
- // 'name' here is the w3c-approved identifier for what we mean by 'type'
106
- if ([field isEqualToString:@"name"] || [field isEqualToString:@"type"]) {
107
- dictionary[field] = wrappedSnapshot.wdType;
108
- } else if ([field isEqualToString:@"text"]) {
109
- dictionary[field] = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel) ?: [NSNull null];
110
- } else if ([field isEqualToString:@"rect"]) {
111
- dictionary[field] = wrappedSnapshot.wdRect;
112
- } else if ([field isEqualToString:@"enabled"]) {
113
- dictionary[field] = @(wrappedSnapshot.wdEnabled);
114
- } else if ([field isEqualToString:@"displayed"]) {
115
- dictionary[field] = @(wrappedSnapshot.wdVisible);
116
- } else if ([field isEqualToString:@"selected"]) {
117
- dictionary[field] = @(wrappedSnapshot.wdSelected);
118
- } else if ([field isEqualToString:@"label"]) {
119
- dictionary[field] = wrappedSnapshot.wdLabel ?: [NSNull null];
120
- } else if ([field hasPrefix:arbitraryAttrPrefix]) {
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 dictionary.copy;
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
- [processedItem setObject:FBInsertElement(FBCleanupElements(options), element)
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 = mach_absolute_time() - timeStarted;
62
- int64_t nextTickDelta = timerInterval - timeElapsed * self.timebaseInfo.numer / self.timebaseInfo.denom;
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 = mach_absolute_time();
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 = mach_absolute_time();
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 = mach_absolute_time() - timeStarted;
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
- Inserts element uuid into the response dictionary
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 changed dictionary
18
+ @returns The resulting dictionary
20
19
  */
21
- NSDictionary *FBInsertElement(NSDictionary *dst, id element);
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 *FBInsertElement(NSDictionary *dst, id element)
23
+ NSDictionary<NSString *, id> *FBToElementDict(id element)
24
24
  {
25
- NSMutableDictionary *result = dst.mutableCopy;
26
- result[W3C_ELEMENT_KEY] = element;
27
- result[JSONWP_ELEMENT_KEY] = element;
28
- return result.copy;
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 = mach_absolute_time();
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 = (mach_absolute_time() - timeStarted) / NSEC_PER_SEC;
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "4.10.7",
3
+ "version": "4.10.9",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {