From 29b67467cbfad1122994bd8b0b0e4fa95f2eac7e Mon Sep 17 00:00:00 2001 From: foo Date: Tue, 4 Apr 2023 10:29:50 +0800 Subject: [PATCH 1/5] Add support for swiping from the specified edge of the screen --- KIF Tests/GestureTests.m | 12 ++++ Sources/KIF/Additions/UITouch-KIFAdditions.h | 1 + Sources/KIF/Additions/UITouch-KIFAdditions.m | 7 +++ Sources/KIF/Additions/UIView-KIFAdditions.h | 1 + Sources/KIF/Additions/UIView-KIFAdditions.m | 12 +++- Sources/KIF/Classes/KIFUITestActor.h | 7 +++ Sources/KIF/Classes/KIFUITestActor.m | 56 +++++++++++++++---- .../Base.lproj/MainStoryboard.storyboard | 14 +++++ Test Host/GestureViewController.m | 19 +++++++ 9 files changed, 116 insertions(+), 13 deletions(-) diff --git a/KIF Tests/GestureTests.m b/KIF Tests/GestureTests.m index ecb62b625..6b280f2c3 100644 --- a/KIF Tests/GestureTests.m +++ b/KIF Tests/GestureTests.m @@ -193,6 +193,18 @@ - (void)testSwipingDownWithIdentifier [tester waitForViewWithAccessibilityLabel:@"Down"]; } +- (void)testSwipeFromScreenEdgeLeft +{ + [tester swipeFromEdge:UIRectEdgeLeft atY:300]; + [tester waitForViewWithAccessibilityLabel:@"LeftEdge"]; +} + +- (void)testSwipeFromScreenEdgeRight +{ + [tester swipeFromEdge:UIRectEdgeRight atY:300]; + [tester waitForViewWithAccessibilityLabel:@"RightEdge"]; +} + - (void)testScrolling { // Needs to be offset from the edge to prevent the navigation controller's interactivePopGestureRecognizer from triggering diff --git a/Sources/KIF/Additions/UITouch-KIFAdditions.h b/Sources/KIF/Additions/UITouch-KIFAdditions.h index ea8dc350c..5fedffe42 100644 --- a/Sources/KIF/Additions/UITouch-KIFAdditions.h +++ b/Sources/KIF/Additions/UITouch-KIFAdditions.h @@ -17,5 +17,6 @@ - (void)setLocationInWindow:(CGPoint)location; - (void)setPhaseAndUpdateTimestamp:(UITouchPhase)phase; +- (void)setIsFromEdge:(BOOL)isFromEdge; @end diff --git a/Sources/KIF/Additions/UITouch-KIFAdditions.m b/Sources/KIF/Additions/UITouch-KIFAdditions.m index 59b2e34ea..9cc9880c9 100644 --- a/Sources/KIF/Additions/UITouch-KIFAdditions.m +++ b/Sources/KIF/Additions/UITouch-KIFAdditions.m @@ -37,6 +37,7 @@ - (void)_setIsFirstTouchForView:(BOOL)firstTouchForView; - (void)_setIsTapToClick:(BOOL)tapToClick; - (void)_setHidEvent:(IOHIDEventRef)event; +- (void)_setEdgeType:(NSInteger)edgeType; @end @@ -117,6 +118,12 @@ - (void)setPhaseAndUpdateTimestamp:(UITouchPhase)phase [self setPhase:phase]; } +- (void)setIsFromEdge:(BOOL)isFromEdge +{ + NSInteger edgeType = isFromEdge ? 4 : 0; + [self _setEdgeType:edgeType]; +} + - (void)kif_setHidEvent { IOHIDEventRef event = kif_IOHIDEventWithTouches(@[self]); [self _setHidEvent:event]; diff --git a/Sources/KIF/Additions/UIView-KIFAdditions.h b/Sources/KIF/Additions/UIView-KIFAdditions.h index acb481876..6cbb8d9f8 100644 --- a/Sources/KIF/Additions/UIView-KIFAdditions.h +++ b/Sources/KIF/Additions/UIView-KIFAdditions.h @@ -53,6 +53,7 @@ typedef CGPoint KIFDisplacement; - (void)dragFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint; - (void)dragFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint steps:(NSUInteger)stepCount; - (void)dragFromPoint:(CGPoint)startPoint displacement:(KIFDisplacement)displacement steps:(NSUInteger)stepCount; +- (void)dragFromPoint:(CGPoint)startPoint displacement:(KIFDisplacement)displacement steps:(NSUInteger)stepCount isFromEdge:(BOOL)isFromEdge; - (void)dragAlongPathWithPoints:(CGPoint *)points count:(NSInteger)count; - (void)twoFingerPanFromPoint:(CGPoint)startPoint toPoint:(CGPoint)toPoint steps:(NSUInteger)stepCount; - (void)pinchAtPoint:(CGPoint)centerPoint distance:(CGFloat)distance steps:(NSUInteger)stepCount; diff --git a/Sources/KIF/Additions/UIView-KIFAdditions.m b/Sources/KIF/Additions/UIView-KIFAdditions.m index 4d7b31c3f..0f84798bd 100644 --- a/Sources/KIF/Additions/UIView-KIFAdditions.m +++ b/Sources/KIF/Additions/UIView-KIFAdditions.m @@ -630,10 +630,15 @@ - (void)dragFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint steps:(NSUIn } - (void)dragFromPoint:(CGPoint)startPoint displacement:(KIFDisplacement)displacement steps:(NSUInteger)stepCount; +{ + [self dragFromPoint:startPoint displacement:displacement steps:stepCount isFromEdge:NO]; +} + +- (void)dragFromPoint:(CGPoint)startPoint displacement:(KIFDisplacement)displacement steps:(NSUInteger)stepCount isFromEdge:(BOOL)isFromEdge; { CGPoint endPoint = CGPointMake(startPoint.x + displacement.x, startPoint.y + displacement.y); NSArray *path = [self pointsFromStartPoint:startPoint toPoint:endPoint steps:stepCount]; - [self dragPointsAlongPaths:@[path]]; + [self dragPointsAlongPaths:@[path] isFromEdge:isFromEdge]; } - (void)dragAlongPathWithPoints:(CGPoint *)points count:(NSInteger)count; @@ -648,6 +653,10 @@ - (void)dragAlongPathWithPoints:(CGPoint *)points count:(NSInteger)count; } - (void)dragPointsAlongPaths:(NSArray *> *)arrayOfPaths { + [self dragPointsAlongPaths:arrayOfPaths isFromEdge:NO]; +} + +- (void)dragPointsAlongPaths:(NSArray *> *)arrayOfPaths isFromEdge:(BOOL)isFromEdge { // There must be at least one path with at least one point if (arrayOfPaths.count == 0 || arrayOfPaths.firstObject.count == 0) { @@ -692,6 +701,7 @@ - (void)dragPointsAlongPaths:(NSArray *> *)arrayOfPaths { point = [self convertPoint:point fromView:self.window]; UITouch *touch = [[UITouch alloc] initAtPoint:point inView:self]; [touch setPhaseAndUpdateTimestamp:UITouchPhaseBegan]; + [touch setIsFromEdge:isFromEdge]; [touches addObject:touch]; } UIEvent *eventDown = [self eventWithTouches:[NSArray arrayWithArray:touches]]; diff --git a/Sources/KIF/Classes/KIFUITestActor.h b/Sources/KIF/Classes/KIFUITestActor.h index db346ed02..36d92c3e4 100644 --- a/Sources/KIF/Classes/KIFUITestActor.h +++ b/Sources/KIF/Classes/KIFUITestActor.h @@ -322,6 +322,13 @@ typedef NS_ENUM(NSUInteger, KIFPullToRefreshTiming) { */ - (void)tapScreenAtPoint:(CGPoint)screenPoint; +/*! + @abstract Performs a swipe gesture starting from the specified edge of the screen. + @param edge The edge from which the swipe gesture should start. + @param y The y-coordinate of the starting point for the swipe gesture. + */ +- (void)swipeFromEdge:(UIRectEdge)edge atY:(CGFloat)y; + /*! @abstract Performs a long press on a particular view in the view hierarchy. @discussion The view or accessibility element with the given label is searched for in the view hierarchy. If the element isn't found or isn't currently tappable, then the step will attempt to wait until it is. Once the view is present and tappable, touch events are simulated in the center of the view or element. diff --git a/Sources/KIF/Classes/KIFUITestActor.m b/Sources/KIF/Classes/KIFUITestActor.m index ff8c9ca15..bf72bab3d 100644 --- a/Sources/KIF/Classes/KIFUITestActor.m +++ b/Sources/KIF/Classes/KIFUITestActor.m @@ -366,18 +366,7 @@ - (void)tapAccessibilityElement:(UIAccessibilityElement *)element inView:(UIView - (void)tapScreenAtPoint:(CGPoint)screenPoint { [self runBlock:^KIFTestStepResult(NSError **error) { - - // Try all the windows until we get one back that actually has something in it at the given point - UIView *view = nil; - for (UIWindow *window in [[[UIApplication sharedApplication] windowsWithKeyWindow] reverseObjectEnumerator]) { - CGPoint windowPoint = [window convertPoint:screenPoint fromView:nil]; - view = [window hitTest:windowPoint withEvent:nil]; - - // If we hit the window itself, then skip it. - if (view != window && view != nil) { - break; - } - } + UIView *view = [self viewAtPoint:screenPoint]; KIFTestWaitCondition(view, error, @"No view was found at the point %@", NSStringFromCGPoint(screenPoint)); @@ -389,6 +378,49 @@ - (void)tapScreenAtPoint:(CGPoint)screenPoint }]; } +- (void)swipeFromEdge:(UIRectEdge)edge atY:(CGFloat)y +{ + CGPoint screenPoint; + KIFSwipeDirection direction; + if (edge == UIRectEdgeLeft) { + screenPoint = CGPointMake(0.3, y); + direction = KIFSwipeDirectionRight; + } else if (edge == UIRectEdgeRight) { + screenPoint = CGPointMake(UIScreen.mainScreen.bounds.size.width - 0.3, y); + direction = KIFSwipeDirectionLeft; + } else { + return; + } + [self runBlock:^KIFTestStepResult(NSError **error) { + UIView *view = [self viewAtPoint:screenPoint]; + + KIFTestWaitCondition(view, error, @"No view was found at the point %@", NSStringFromCGPoint(screenPoint)); + + // This is mostly redundant of the test in _accessibilityElementWithLabel: + CGPoint viewPoint = [view convertPoint:screenPoint fromView:nil]; + KIFDisplacement swipeDisplacement = [self _displacementForSwipingInDirection:direction]; + [view dragFromPoint:viewPoint displacement:swipeDisplacement steps:20 isFromEdge:YES]; + + return KIFTestStepResultSuccess; + }]; +} + +- (UIView *)viewAtPoint:(CGPoint)screenPoint +{ + // Try all the windows until we get one back that actually has something in it at the given point + UIView *view = nil; + for (UIWindow *window in [[[UIApplication sharedApplication] windowsWithKeyWindow] reverseObjectEnumerator]) { + CGPoint windowPoint = [window convertPoint:screenPoint fromView:nil]; + view = [window hitTest:windowPoint withEvent:nil]; + + // If we hit the window itself, then skip it. + if (view != window && view != nil) { + break; + } + } + return view; +} + - (void)longPressViewWithAccessibilityLabel:(NSString *)label duration:(NSTimeInterval)duration; { [self longPressViewWithAccessibilityLabel:label value:nil traits:UIAccessibilityTraitNone duration:duration]; diff --git a/Test Host/Base.lproj/MainStoryboard.storyboard b/Test Host/Base.lproj/MainStoryboard.storyboard index 1235360bd..407d1e5dd 100644 --- a/Test Host/Base.lproj/MainStoryboard.storyboard +++ b/Test Host/Base.lproj/MainStoryboard.storyboard @@ -1289,6 +1289,8 @@ + +