appium-webdriveragent 5.0.0 → 5.1.1

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/WebDriverAgent.xcodeproj/project.pbxproj +0 -20
  3. package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +0 -12
  4. package/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +1 -15
  5. package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +7 -37
  6. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +0 -7
  7. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +0 -49
  8. package/WebDriverAgentLib/Commands/FBElementCommands.m +37 -19
  9. package/WebDriverAgentLib/FBApplication.h +10 -0
  10. package/WebDriverAgentLib/FBApplication.m +36 -0
  11. package/WebDriverAgentLib/Routing/FBExceptionHandler.m +2 -1
  12. package/WebDriverAgentLib/Routing/FBExceptions.h +3 -0
  13. package/WebDriverAgentLib/Routing/FBExceptions.m +1 -0
  14. package/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m +23 -15
  15. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +4 -13
  16. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +36 -56
  17. package/WebDriverAgentLib/Utilities/FBMathUtils.h +0 -6
  18. package/WebDriverAgentLib/Utilities/FBMathUtils.m +0 -29
  19. package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +23 -29
  20. package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +0 -4
  21. package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +0 -12
  22. package/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m +0 -16
  23. package/WebDriverAgentTests/IntegrationTests/FBSessionIntegrationTests.m +29 -0
  24. package/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +0 -19
  25. package/WebDriverAgentTests/UnitTests/FBMathUtilsTests.m +0 -12
  26. package/package.json +1 -1
  27. package/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.h +0 -18
  28. package/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m +0 -46
  29. package/WebDriverAgentTests/IntegrationTests/FBElementScreenshotTests.m +0 -52
  30. package/WebDriverAgentTests/UnitTests/XCUICoordinateFix.m +0 -63
@@ -80,7 +80,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
80
80
 
81
81
  - (nullable instancetype)initWithActionItem:(NSDictionary<NSString *, id> *)item
82
82
  application:(XCUIApplication *)application
83
- atPosition:(nullable NSValue *)atPosition
83
+ atPosition:(nullable XCUICoordinate *)atPosition
84
84
  offset:(double)offset
85
85
  error:(NSError **)error
86
86
  {
@@ -90,14 +90,14 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
90
90
  self.application = application;
91
91
  self.offset = offset;
92
92
  id options = [item objectForKey:FB_OPTIONS_KEY];
93
- if (atPosition) {
94
- self.atPosition = [atPosition CGPointValue];
93
+ if (nil != atPosition) {
94
+ self.atPosition = (id) atPosition;
95
95
  } else {
96
- NSValue *result = [self coordinatesWithOptions:options error:error];
96
+ XCUICoordinate *result = [self coordinatesWithOptions:options error:error];
97
97
  if (nil == result) {
98
98
  return nil;
99
99
  }
100
- self.atPosition = [result CGPointValue];
100
+ self.atPosition = result;
101
101
  }
102
102
  self.duration = [self durationWithOptions:options];
103
103
  if (self.duration < 0) {
@@ -124,7 +124,8 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
124
124
  0.0;
125
125
  }
126
126
 
127
- - (nullable NSValue *)coordinatesWithOptions:(nullable NSDictionary<NSString *, id> *)options error:(NSError **)error
127
+ - (nullable XCUICoordinate *)coordinatesWithOptions:(nullable NSDictionary<NSString *, id> *)options
128
+ error:(NSError **)error
128
129
  {
129
130
  if (![options isKindOfClass:NSDictionary.class]) {
130
131
  NSString *description = [NSString stringWithFormat:@"'%@' key is mandatory for '%@' action", FB_OPTIONS_KEY, self.class.actionName];
@@ -169,7 +170,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
169
170
  NSTimeInterval currentOffset = FBMillisToSeconds(self.offset);
170
171
  NSMutableArray<XCPointerEventPath *> *result = [NSMutableArray array];
171
172
  XCPointerEventPath *currentPath = [[XCPointerEventPath alloc]
172
- initForTouchAtPoint:self.atPosition
173
+ initForTouchAtPoint:self.atPosition.screenPoint
173
174
  offset:currentOffset];
174
175
  [result addObject:currentPath];
175
176
  currentOffset += FBMillisToSeconds(FB_TAP_DURATION_MS);
@@ -180,7 +181,8 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
180
181
  NSNumber *tapCount = [options objectForKey:FB_OPTION_COUNT] ?: @1;
181
182
  for (NSInteger times = 1; times < tapCount.integerValue; ++times) {
182
183
  currentOffset += FBMillisToSeconds(FB_INTERTAP_MIN_DURATION_MS);
183
- XCPointerEventPath *nextPath = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:currentOffset];
184
+ XCPointerEventPath *nextPath = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
185
+ offset:currentOffset];
184
186
  [result addObject:nextPath];
185
187
  currentOffset += FBMillisToSeconds(FB_TAP_DURATION_MS);
186
188
  [nextPath liftUpAtOffset:currentOffset];
@@ -204,7 +206,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
204
206
 
205
207
  - (nullable instancetype)initWithActionItem:(NSDictionary<NSString *, id> *)item
206
208
  application:(XCUIApplication *)application
207
- atPosition:(nullable NSValue *)atPosition
209
+ atPosition:(nullable XCUICoordinate *)atPosition
208
210
  offset:(double)offset
209
211
  error:(NSError **)error
210
212
  {
@@ -239,7 +241,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
239
241
  error:(NSError **)error
240
242
  {
241
243
  XCPointerEventPath *result = [[XCPointerEventPath alloc]
242
- initForTouchAtPoint:self.atPosition
244
+ initForTouchAtPoint:self.atPosition.screenPoint
243
245
  offset:FBMillisToSeconds(self.offset)];
244
246
  if (nil != self.pressure && nil != result.pointerEvents.lastObject) {
245
247
  XCPointerEvent *pointerEvent = (XCPointerEvent *)result.pointerEvents.lastObject;
@@ -272,7 +274,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
272
274
  currentItemIndex:(NSUInteger)currentItemIndex
273
275
  error:(NSError **)error
274
276
  {
275
- return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition
277
+ return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
276
278
  offset:FBMillisToSeconds(self.offset)]];
277
279
  }
278
280
 
@@ -312,7 +314,8 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
312
314
  }
313
315
  }
314
316
  NSTimeInterval currentOffset = FBMillisToSeconds(self.offset + self.duration);
315
- XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:currentOffset];
317
+ XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
318
+ offset:currentOffset];
316
319
  if (currentItemIndex == allItems.count - 1) {
317
320
  [result liftUpAtOffset:currentOffset];
318
321
  }
@@ -353,7 +356,8 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
353
356
  return nil;
354
357
  }
355
358
 
356
- [eventPath moveToPoint:self.atPosition atOffset:FBMillisToSeconds(self.offset)];
359
+ [eventPath moveToPoint:self.atPosition.screenPoint
360
+ atOffset:FBMillisToSeconds(self.offset)];
357
361
  return @[];
358
362
  }
359
363
 
@@ -509,7 +513,11 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
509
513
  return nil;
510
514
  }
511
515
  FBAppiumGestureItem *lastItem = [chain.items lastObject];
512
- gestureItem = [[gestureItemClass alloc] initWithActionItem:actionItem application:self.application atPosition:[NSValue valueWithCGPoint:lastItem.atPosition] offset:chain.durationOffset error:error];
516
+ gestureItem = [[gestureItemClass alloc] initWithActionItem:actionItem
517
+ application:self.application
518
+ atPosition:lastItem.atPosition
519
+ offset:chain.durationOffset
520
+ error:error];
513
521
  }
514
522
  if (nil == gestureItem) {
515
523
  return nil;
@@ -527,7 +535,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
527
535
  BOOL isMultiTouch = [self.actions.firstObject isKindOfClass:NSArray.class];
528
536
  eventRecord = [[XCSynthesizedEventRecord alloc]
529
537
  initWithName:(isMultiTouch ? @"Multi-Finger Touch Action" : @"Single-Finger Touch Action")
530
- interfaceOrientation:[FBXCTestDaemonsProxy orientationWithApplication:self.application]];
538
+ interfaceOrientation:self.application.interfaceOrientation];
531
539
  for (NSArray<NSDictionary<NSString *, id> *> *action in (isMultiTouch ? self.actions : @[self.actions])) {
532
540
  NSArray<NSDictionary<NSString *, id> *> *preprocessedAction = [self preprocessAction:action];
533
541
  NSArray<XCPointerEventPath *> *eventPaths = [self eventPathsWithAction:preprocessedAction error:error];
@@ -51,19 +51,10 @@ NS_ASSUME_NONNULL_BEGIN
51
51
  @interface FBBaseGestureItem : FBBaseActionItem
52
52
 
53
53
  /*! Absolute position on the screen where the gesure should be performed */
54
- @property (nonatomic) CGPoint atPosition;
54
+ @property (nonatomic) XCUICoordinate *atPosition;
55
55
  /*! Gesture duration in milliseconds */
56
56
  @property (nonatomic) double duration;
57
57
 
58
- /**
59
- Returns fixed hit point coordinates for the case when XCTest fails to transform element snaapshot properly on screen rotation.
60
-
61
- @param hitPoint The initial hitpoint coordinates
62
- @param snapshot Element's snapshot instance
63
- @return The fixed hit point coordinates, if there is a need to fix them, or the unchanged hit point value
64
- */
65
- - (CGPoint)fixedHitPointWith:(CGPoint)hitPoint forSnapshot:(id<FBXCElementSnapshot>)snapshot;
66
-
67
58
  /**
68
59
  Calculate absolute gesture position on the screen based on provided element and positionOffset values.
69
60
 
@@ -72,9 +63,9 @@ NS_ASSUME_NONNULL_BEGIN
72
63
  @param error If there is an error, upon return contains an NSError object that describes the problem
73
64
  @return Adbsolute gesture position on the screen or nil if the calculation fails (for example, the element is invisible)
74
65
  */
75
- - (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element
76
- positionOffset:(nullable NSValue *)positionOffset
77
- error:(NSError **)error;
66
+ - (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element
67
+ positionOffset:(nullable NSValue *)positionOffset
68
+ error:(NSError **)error;
78
69
 
79
70
  @end
80
71
 
@@ -31,7 +31,10 @@
31
31
  return nil;
32
32
  }
33
33
 
34
- - (NSArray<XCPointerEventPath *> *)addToEventPath:(XCPointerEventPath *)eventPath allItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex error:(NSError **)error
34
+ - (NSArray<XCPointerEventPath *> *)addToEventPath:(XCPointerEventPath *)eventPath
35
+ allItems:(NSArray *)allItems
36
+ currentItemIndex:(NSUInteger)currentItemIndex
37
+ error:(NSError **)error
35
38
  {
36
39
  @throw [[FBErrorBuilder.builder withDescription:@"Override this method in subclasses"] build];
37
40
  return nil;
@@ -41,66 +44,40 @@
41
44
 
42
45
  @implementation FBBaseGestureItem
43
46
 
44
- - (CGPoint)fixedHitPointWith:(CGPoint)hitPoint forSnapshot:(id<FBXCElementSnapshot>)snapshot
47
+ - (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element
48
+ positionOffset:(nullable NSValue *)positionOffset
49
+ error:(NSError **)error
45
50
  {
46
- UIInterfaceOrientation interfaceOrientation = self.application.interfaceOrientation;
47
- if (interfaceOrientation == UIInterfaceOrientationPortrait) {
48
- // There is no need to recalculate anything for portrait orientation
49
- return hitPoint;
50
- }
51
- // For Xcode11+ it is always necessary to adjust the tap point coordinates
52
- return FBInvertPointForApplication(hitPoint, self.application.frame.size, interfaceOrientation);
53
- }
54
-
55
- - (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element positionOffset:(nullable NSValue *)positionOffset error:(NSError **)error
56
- {
57
- CGPoint hitPoint;
58
51
  if (nil == element) {
52
+ CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y);
59
53
  // Only absolute offset is defined
60
- hitPoint = [positionOffset CGPointValue];
61
- /*
62
- Since iOS 10.0 XCTest has a bug when it always returns portrait coordinates for UI elements
63
- even if the device is not in portait mode. That is why we need to recalculate them manually
64
- based on the current orientation value
65
- */
66
- hitPoint = FBInvertPointForApplication(hitPoint, self.application.frame.size, self.application.interfaceOrientation);
67
- } else {
68
- // The offset relative to the element is defined
69
-
70
- id<FBXCElementSnapshot> snapshot = element.fb_isResolvedFromCache.boolValue
71
- ? element.lastSnapshot
72
- : element.fb_takeSnapshot;
73
- if (nil == positionOffset) {
74
- NSValue *hitPointValue = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_hitPoint;
75
- if (nil != hitPointValue) {
76
- // short circuit element hitpoint
77
- return hitPointValue;
78
- }
79
- [FBLogger logFmt:@"Will use the frame of '%@' for hit point calculation instead", element.debugDescription];
80
- }
81
- CGRect visibleFrame = snapshot.visibleFrame;
82
- CGRect frame = CGRectIsEmpty(visibleFrame) ? element.frame : visibleFrame;
83
- if (CGRectIsEmpty(frame)) {
84
- [FBLogger log:self.application.fb_descriptionRepresentation];
85
- NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable", element.description];
86
- if (error) {
87
- *error = [[FBErrorBuilder.builder withDescription:description] build];
88
- }
89
- return nil;
54
+ return [[self.application coordinateWithNormalizedOffset:CGVectorMake(0, 0)] coordinateWithOffset:offset];
55
+ }
56
+
57
+ // The offset relative to the element is defined
58
+ if (nil == positionOffset) {
59
+ if (element.hittable) {
60
+ // short circuit element hitpoint
61
+ return element.hitPointCoordinate;
90
62
  }
91
- if (nil == positionOffset) {
92
- hitPoint = CGPointMake(frame.origin.x + frame.size.width / 2,
93
- frame.origin.y + frame.size.height / 2);
94
- } else {
95
- CGPoint origin = frame.origin;
96
- hitPoint = CGPointMake(origin.x, origin.y);
97
- CGPoint offsetValue = [positionOffset CGPointValue];
98
- hitPoint = CGPointMake(hitPoint.x + offsetValue.x, hitPoint.y + offsetValue.y);
99
- // TODO: Shall we throw an exception if hitPoint is out of the element frame?
63
+ [FBLogger logFmt:@"Will use the frame of '%@' for hit point calculation instead", element.debugDescription];
64
+ }
65
+ if (CGRectIsEmpty(element.frame)) {
66
+ [FBLogger log:self.application.fb_descriptionRepresentation];
67
+ NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable",
68
+ element.description];
69
+ if (error) {
70
+ *error = [[FBErrorBuilder.builder withDescription:description] build];
100
71
  }
101
- hitPoint = [self fixedHitPointWith:hitPoint forSnapshot:snapshot];
72
+ return nil;
73
+ }
74
+ if (nil == positionOffset) {
75
+ return [element coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)];
102
76
  }
103
- return [NSValue valueWithCGPoint:hitPoint];
77
+
78
+ CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y);
79
+ // TODO: Shall we throw an exception if hitPoint is out of the element frame?
80
+ return [[element coordinateWithNormalizedOffset:CGVectorMake(0, 0)] coordinateWithOffset:offset];
104
81
  }
105
82
 
106
83
  @end
@@ -161,7 +138,10 @@
161
138
 
162
139
  @implementation FBBaseActionsSynthesizer
163
140
 
164
- - (instancetype)initWithActions:(NSArray *)actions forApplication:(XCUIApplication *)application elementCache:(nullable FBElementCache *)elementCache error:(NSError **)error
141
+ - (instancetype)initWithActions:(NSArray *)actions
142
+ forApplication:(XCUIApplication *)application
143
+ elementCache:(nullable FBElementCache *)elementCache
144
+ error:(NSError **)error
165
145
  {
166
146
  self = [super init];
167
147
  if (self) {
@@ -32,12 +32,6 @@ BOOL FBSizeFuzzyEqualToSize(CGSize size1, CGSize size2, CGFloat threshold);
32
32
  BOOL FBRectFuzzyEqualToRect(CGRect rect1, CGRect rect2, CGFloat threshold);
33
33
 
34
34
  #if !TARGET_OS_TV
35
- /*! Inverts point if necessary to match location on screen */
36
- CGPoint FBInvertPointForApplication(CGPoint point, CGSize screenSize, UIInterfaceOrientation orientation);
37
-
38
- /*! Inverts offset if necessary to match screen orientation */
39
- CGPoint FBInvertOffsetForOrientation(CGPoint offset, UIInterfaceOrientation orientation);
40
-
41
35
  /*! Inverts size if necessary to match current screen orientation */
42
36
  CGSize FBAdjustDimensionsForApplication(CGSize actualSize, UIInterfaceOrientation orientation);
43
37
  #endif
@@ -46,35 +46,6 @@ BOOL FBRectFuzzyEqualToRect(CGRect rect1, CGRect rect2, CGFloat threshold)
46
46
  }
47
47
 
48
48
  #if !TARGET_OS_TV
49
- CGPoint FBInvertPointForApplication(CGPoint point, CGSize screenSize, UIInterfaceOrientation orientation)
50
- {
51
- switch (orientation) {
52
- case UIInterfaceOrientationUnknown:
53
- case UIInterfaceOrientationPortrait:
54
- return point;
55
- case UIInterfaceOrientationPortraitUpsideDown:
56
- return CGPointMake(screenSize.width - point.x, screenSize.height - point.y);
57
- case UIInterfaceOrientationLandscapeLeft:
58
- return CGPointMake(point.y, MAX(screenSize.width, screenSize.height) - point.x);
59
- case UIInterfaceOrientationLandscapeRight:
60
- return CGPointMake(MIN(screenSize.width, screenSize.height) - point.y, point.x);
61
- }
62
- }
63
-
64
- CGPoint FBInvertOffsetForOrientation(CGPoint offset, UIInterfaceOrientation orientation)
65
- {
66
- switch (orientation) {
67
- case UIInterfaceOrientationUnknown:
68
- case UIInterfaceOrientationPortrait:
69
- return offset;
70
- case UIInterfaceOrientationPortraitUpsideDown:
71
- return CGPointMake(-offset.x, -offset.y);
72
- case UIInterfaceOrientationLandscapeLeft:
73
- return CGPointMake(offset.y, -offset.x);
74
- case UIInterfaceOrientationLandscapeRight:
75
- return CGPointMake(-offset.y, offset.x);
76
- }
77
- }
78
49
 
79
50
  CGSize FBAdjustDimensionsForApplication(CGSize actualSize, UIInterfaceOrientation orientation)
80
51
  {
@@ -133,16 +133,16 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
133
133
  return nil;
134
134
  }
135
135
  self.duration = durationObj.doubleValue;
136
- NSValue *position = [self positionWithError:error];
136
+ XCUICoordinate *position = [self positionWithError:error];
137
137
  if (nil == position) {
138
138
  return nil;
139
139
  }
140
- self.atPosition = [position CGPointValue];
140
+ self.atPosition = position;
141
141
  }
142
142
  return self;
143
143
  }
144
144
 
145
- - (nullable NSValue *)positionWithError:(NSError **)error
145
+ - (nullable XCUICoordinate *)positionWithError:(NSError **)error
146
146
  {
147
147
  if (nil == self.previousItem) {
148
148
  NSString *errorDescription = [NSString stringWithFormat:@"The '%@' action item must be preceded by %@ item", self.actionItem, FB_ACTION_ITEM_TYPE_POINTER_MOVE];
@@ -151,39 +151,32 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
151
151
  }
152
152
  return nil;
153
153
  }
154
- return [NSValue valueWithCGPoint:self.previousItem.atPosition];
154
+ return self.previousItem.atPosition;
155
155
  }
156
156
 
157
- - (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element
158
- positionOffset:(nullable NSValue *)positionOffset
159
- error:(NSError **)error
157
+ - (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element
158
+ positionOffset:(nullable NSValue *)positionOffset
159
+ error:(NSError **)error
160
160
  {
161
161
  if (nil == element || nil == positionOffset) {
162
162
  return [super hitpointWithElement:element positionOffset:positionOffset error:error];
163
163
  }
164
164
 
165
165
  // An offset relative to the element is defined
166
- id<FBXCElementSnapshot> snapshot = element.fb_isResolvedFromCache.boolValue
167
- ? element.lastSnapshot
168
- : element.fb_takeSnapshot;
169
- CGRect frame = snapshot.frame;
170
- if (CGRectIsEmpty(frame)) {
166
+ if (CGRectIsEmpty(element.frame)) {
171
167
  [FBLogger log:self.application.fb_descriptionRepresentation];
172
- NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable", [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_description];
168
+ NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable",
169
+ element.description];
173
170
  if (error) {
174
171
  *error = [[FBErrorBuilder.builder withDescription:description] build];
175
172
  }
176
173
  return nil;
177
174
  }
178
- CGRect visibleFrame = snapshot.visibleFrame;
179
- frame = CGRectIsEmpty(visibleFrame) ? frame : visibleFrame;
175
+
180
176
  // W3C standard requires that relative element coordinates start at the center of the element's rectangle
181
- CGPoint hitPoint = CGPointMake(frame.origin.x + frame.size.width / 2, frame.origin.y + frame.size.height / 2);
182
- CGPoint offsetValue = [positionOffset CGPointValue];
183
- hitPoint = CGPointMake(hitPoint.x + offsetValue.x, hitPoint.y + offsetValue.y);
177
+ CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y);
184
178
  // TODO: Shall we throw an exception if hitPoint is out of the element frame?
185
- hitPoint = [self fixedHitPointWith:hitPoint forSnapshot:snapshot];
186
- return [NSValue valueWithCGPoint:hitPoint];
179
+ return [[element coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)] coordinateWithOffset:offset];
187
180
  }
188
181
 
189
182
  @end
@@ -220,7 +213,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
220
213
  }
221
214
  }
222
215
  if (nil == self.pressure) {
223
- XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition
216
+ XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
224
217
  offset:FBMillisToSeconds(self.offset)];
225
218
  return @[result];
226
219
  }
@@ -247,7 +240,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
247
240
 
248
241
  @implementation FBPointerMoveItem
249
242
 
250
- - (nullable NSValue *)positionWithError:(NSError **)error
243
+ - (nullable XCUICoordinate *)positionWithError:(NSError **)error
251
244
  {
252
245
  static NSArray<NSString *> *supportedOriginTypes;
253
246
  static dispatch_once_t onceToken;
@@ -295,10 +288,9 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
295
288
  }
296
289
  return nil;
297
290
  }
298
- CGPoint recentPosition = self.previousItem.atPosition;
299
- CGPoint offsetRelativeToRecentPosition = (nil == x && nil == y) ? CGPointMake(0.0, 0.0) : CGPointMake(x.floatValue, y.floatValue);
300
- offsetRelativeToRecentPosition = FBInvertOffsetForOrientation(offsetRelativeToRecentPosition, self.application.interfaceOrientation);
301
- return [NSValue valueWithCGPoint:CGPointMake(recentPosition.x + offsetRelativeToRecentPosition.x, recentPosition.y + offsetRelativeToRecentPosition.y)];
291
+ XCUICoordinate *recentPosition = self.previousItem.atPosition;
292
+ CGVector offsetRelativeToRecentPosition = (nil == x && nil == y) ? CGVectorMake(0, 0) : CGVectorMake(x.floatValue, y.floatValue);
293
+ return [recentPosition coordinateWithOffset:offsetRelativeToRecentPosition];
302
294
  }
303
295
 
304
296
  + (NSString *)actionName
@@ -312,9 +304,11 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
312
304
  error:(NSError **)error
313
305
  {
314
306
  if (nil == eventPath) {
315
- return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:FBMillisToSeconds(self.offset + self.duration)]];
307
+ return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
308
+ offset:FBMillisToSeconds(self.offset + self.duration)]];
316
309
  }
317
- [eventPath moveToPoint:self.atPosition atOffset:FBMillisToSeconds(self.offset + self.duration)];
310
+ [eventPath moveToPoint:self.atPosition.screenPoint
311
+ atOffset:FBMillisToSeconds(self.offset + self.duration)];
318
312
  return @[];
319
313
  }
320
314
 
@@ -888,7 +882,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
888
882
  {
889
883
  XCSynthesizedEventRecord *eventRecord = [[XCSynthesizedEventRecord alloc]
890
884
  initWithName:@"W3C Touch Action"
891
- interfaceOrientation:[FBXCTestDaemonsProxy orientationWithApplication:self.application]];
885
+ interfaceOrientation:self.application.interfaceOrientation];
892
886
  NSMutableDictionary<NSString *, NSDictionary<NSString *, id> *> *actionsMapping = [NSMutableDictionary new];
893
887
  NSMutableArray<NSString *> *actionIds = [NSMutableArray new];
894
888
  for (NSDictionary<NSString *, id> *action in self.actions) {
@@ -23,10 +23,6 @@ NS_ASSUME_NONNULL_BEGIN
23
23
 
24
24
  + (id<XCTestManager_ManagerInterface>)testRunnerProxy;
25
25
 
26
- #if !TARGET_OS_TV
27
- + (UIInterfaceOrientation)orientationWithApplication:(XCUIApplication *)application;
28
- #endif
29
-
30
26
  + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record
31
27
  error:(NSError *__autoreleasing*)error;
32
28
 
@@ -30,7 +30,6 @@ static dispatch_once_t onceTestRunnerDaemonClass;
30
30
 
31
31
  + (void)load
32
32
  {
33
- // XCTRunnerDaemonSession class is only available since Xcode 8.3
34
33
  dispatch_once(&onceTestRunnerDaemonClass, ^{
35
34
  FBXCTRunnerDaemonSessionClass = objc_lookUpClass("XCTRunnerDaemonSession");
36
35
  });
@@ -60,17 +59,6 @@ static dispatch_once_t onceTestRunnerDaemonClass;
60
59
  return ((XCTRunnerDaemonSession *)[FBXCTRunnerDaemonSessionClass sharedSession]).daemonProxy;
61
60
  }
62
61
 
63
- #if !TARGET_OS_TV
64
- + (UIInterfaceOrientation)orientationWithApplication:(XCUIApplication *)application
65
- {
66
- if (nil == FBXCTRunnerDaemonSessionClass ||
67
- [[FBXCTRunnerDaemonSessionClass sharedSession] useLegacyEventCoordinateTransformationPath]) {
68
- return application.interfaceOrientation;
69
- }
70
- return UIInterfaceOrientationPortrait;
71
- }
72
- #endif
73
-
74
62
  + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSError *__autoreleasing*)error
75
63
  {
76
64
  __block BOOL didSucceed = NO;
@@ -194,14 +194,6 @@
194
194
 
195
195
  - (void)testDoubleTap
196
196
  {
197
- if ([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPad &&
198
- SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
199
- // "tap the element" does not work on iPadOS simulator after change the rotation in iOS 15
200
- // while selecting the element worked. (I confirmed with getting an element screenshot that
201
- // the FBShowAlertButtonName was actually selected after changing the orientation.)
202
- return;
203
- }
204
-
205
197
  NSArray<NSDictionary<NSString *, id> *> *gesture =
206
198
  @[@{
207
199
  @"action": @"tap",
@@ -214,16 +206,8 @@
214
206
  [self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft];
215
207
  }
216
208
 
217
- // TODO: UIDeviceOrientationLandscapeRight is not so good in iOS 16? (Especially simulators)
218
209
  - (void)testPress
219
210
  {
220
- if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
221
- // Does not work on iOS 15.0.
222
- // The same action tap the FBShowAlertButtonName after rotating the screen
223
- // worked with W3C actions. `.click` action did not work.
224
- return;
225
- }
226
-
227
211
  NSArray<NSDictionary<NSString *, id> *> *gesture =
228
212
  @[@{
229
213
  @"action": @"press",
@@ -11,6 +11,7 @@
11
11
 
12
12
  #import "FBIntegrationTestCase.h"
13
13
  #import "FBApplication.h"
14
+ #import "FBExceptions.h"
14
15
  #import "FBMacros.h"
15
16
  #import "FBSession.h"
16
17
  #import "FBXCodeCompatibility.h"
@@ -100,6 +101,34 @@ static NSString *const SETTINGS_BUNDLE_ID = @"com.apple.Preferences";
100
101
  FBAssertWaitTillBecomesTrue([self.session.activeApplication.bundleID isEqualToString:testedApp.bundleID]);
101
102
  }
102
103
 
104
+ - (void)testAppWithInvalidBundleIDCannotBeStarted
105
+ {
106
+ FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"];
107
+ @try {
108
+ [testedApp launch];
109
+ XCTFail(@"An exception is expected to be thrown");
110
+ } @catch (NSException *exception) {
111
+ XCTAssertEqualObjects(FBApplicationMissingException, exception.name);
112
+ }
113
+ }
114
+
115
+ - (void)testAppWithInvalidBundleIDCannotBeActivated
116
+ {
117
+ FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"];
118
+ @try {
119
+ [testedApp activate];
120
+ XCTFail(@"An exception is expected to be thrown");
121
+ } @catch (NSException *exception) {
122
+ XCTAssertEqualObjects(FBApplicationMissingException, exception.name);
123
+ }
124
+ }
125
+
126
+ - (void)testAppWithInvalidBundleIDCannotBeTerminated
127
+ {
128
+ FBApplication *testedApp = [[FBApplication alloc] initWithBundleIdentifier:@"yolo"];
129
+ [testedApp terminate];
130
+ }
131
+
103
132
  - (void)testLaunchUnattachedApp
104
133
  {
105
134
  [FBUnattachedAppLauncher launchAppWithBundleId:SETTINGS_BUNDLE_ID];
@@ -294,18 +294,8 @@
294
294
  [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait];
295
295
  }
296
296
 
297
- // TODO: UIDeviceOrientationLandscapeLeft did not work in iOS 16 simumlator.
298
- // UIDeviceOrientationPortrait was ok.
299
297
  - (void)testDoubleTap
300
298
  {
301
- if ([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPad &&
302
- SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
303
- // "tap the element" does not work on iPadOS simulator after change the rotation in iOS 15
304
- // while selecting the element worked. (I confirmed with getting an element screenshot that
305
- // the FBShowAlertButtonName was actually selected after changing the orientation.)
306
- return;
307
- }
308
-
309
299
  NSArray<NSDictionary<NSString *, id> *> *gesture =
310
300
  @[@{
311
301
  @"type": @"pointer",
@@ -326,17 +316,8 @@
326
316
  [self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft];
327
317
  }
328
318
 
329
- // TODO: UIDeviceOrientationLandscapeRight did not work in iOS 16 simumlator.
330
- // UIDeviceOrientationPortrait was ok.
331
319
  - (void)testLongPressWithCombinedPause
332
320
  {
333
- if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
334
- // Xcode 13 x iOS 14 also does not work while Xcode 12.5 x iOS 14 worked.
335
- // Skip this test for iOS 15 since iOS 15 works with Xcode 13 at least.
336
- return;
337
- }
338
-
339
-
340
321
  NSArray<NSDictionary<NSString *, id> *> *gesture =
341
322
  @[@{
342
323
  @"type": @"pointer",
@@ -98,18 +98,6 @@
98
98
  XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(-1, -1, 1, 1), 1));
99
99
  }
100
100
 
101
-
102
- - (void)testPointInvertion
103
- {
104
- const CGPoint testPoint = CGPointMake(1, 2);
105
- const CGSize screenSize = CGSizeMake(10, 15);
106
- const CGFloat t = FBDefaultFrameFuzzyThreshold;
107
- XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(1, 2), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationPortrait), t));
108
- XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(9, 13), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationPortraitUpsideDown), t));
109
- XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(2, 14), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationLandscapeLeft), t));
110
- XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(8, 1), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationLandscapeRight), t));
111
- }
112
-
113
101
  - (void)testSizeInversion
114
102
  {
115
103
  const CGSize screenSizePortrait = CGSizeMake(10, 15);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "5.0.0",
3
+ "version": "5.1.1",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {
@@ -1,18 +0,0 @@
1
- /**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- */
9
-
10
- #import <XCTest/XCTest.h>
11
-
12
- #if !TARGET_OS_TV
13
- @interface XCUICoordinate (FBFix)
14
-
15
- - (CGPoint)fb_screenPoint;
16
-
17
- @end
18
- #endif