Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add a step to perform a long press #166

Merged
merged 2 commits into from

2 participants

@percysnoodle

This adds stepToLongPressViewWithAccessibilityLabel:duration: and variations for value and traits.

@percysnoodle

Done.

@puls puls merged commit bbde27b into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 29, 2012
  1. @percysnoodle
Commits on Dec 7, 2012
  1. @percysnoodle

    Merge master

    percysnoodle authored
This page is out of date. Refresh to see the latest.
View
1  Additions/UIView-KIFAdditions.h
@@ -35,6 +35,7 @@
- (void)flash;
- (void)tap;
- (void)tapAtPoint:(CGPoint)point;
+- (void)longPressAtPoint:(CGPoint)point duration:(NSTimeInterval)duration;
/*!
@method dragFromPoint:toPoint:
View
35 Additions/UIView-KIFAdditions.m
@@ -301,6 +301,39 @@ - (void)tapAtPoint:(CGPoint)point;
[touch release];
}
+#define DRAG_TOUCH_DELAY 0.01
+
+- (void)longPressAtPoint:(CGPoint)point duration:(NSTimeInterval)duration
+{
+ UITouch *touch = [[UITouch alloc] initAtPoint:point inView:self];
+ [touch setPhase:UITouchPhaseBegan];
+
+ UIEvent *eventDown = [self _eventWithTouch:touch];
+ [[UIApplication sharedApplication] sendEvent:eventDown];
+
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, DRAG_TOUCH_DELAY, false);
+
+ for (NSTimeInterval timeSpent = DRAG_TOUCH_DELAY; timeSpent < duration; timeSpent += DRAG_TOUCH_DELAY)
+ {
+ [touch setPhase:UITouchPhaseStationary];
+
+ UIEvent *eventStillDown = [self _eventWithTouch:touch];
+ [[UIApplication sharedApplication] sendEvent:eventStillDown];
+
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, DRAG_TOUCH_DELAY, false);
+ }
+
+ [touch setPhase:UITouchPhaseEnded];
+ UIEvent *eventUp = [self _eventWithTouch:touch];
+ [[UIApplication sharedApplication] sendEvent:eventUp];
+
+ // Dispatching the event doesn't actually update the first responder, so fake it
+ if ([touch.view isDescendantOfView:self] && [self canBecomeFirstResponder]) {
+ [self becomeFirstResponder];
+ }
+
+ [touch release];
+}
- (void)dragFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint;
{
@@ -309,8 +342,6 @@ - (void)dragFromPoint:(CGPoint)startPoint toPoint:(CGPoint)endPoint;
[self dragAlongPathWithPoints:points count:sizeof(points) / sizeof(CGPoint)];
}
-#define DRAG_TOUCH_DELAY 0.01
-
- (void)dragAlongPathWithPoints:(CGPoint *)points count:(NSInteger)count;
{
// we need at least two points in order to make segments
View
38 Classes/KIFTestStep.h
@@ -328,6 +328,44 @@ typedef KIFTestStepResult (^KIFTestStepExecutionBlock)(KIFTestStep *step, NSErro
+ (id)stepToTapScreenAtPoint:(CGPoint)screenPoint;
/*!
+ @method stepToLongPressViewWithAccessibilityLabel:duration:
+ @abstract A step that 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.
+
+ @param label The accessibility label of the element to tap.
+ @param duration The length of time to long press the element.
+ @result A configured test step.
+ */
++ (id)stepToLongPressViewWithAccessibilityLabel:(NSString *)label duration:(NSTimeInterval)duration;
+
+/*!
+ @method stepToLongPressViewWithAccessibilityLabel:value:duration:
+ @abstract A step that 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.
+
+ This variation allows finding a particular instance of an accessibility element. For example, a table view might have multiple elements with the accessibility label of "Employee", but only one that also has the accessibility value of "Bob".
+ @param label The accessibility label of the element to tap.
+ @param value The accessibility value of the element to tap.
+ @param duration The length of time to long press the element.
+ @result A configured test step.
+ */
++ (id)stepToLongPressViewWithAccessibilityLabel:(NSString *)label value:(NSString *)value duration:(NSTimeInterval)duration;
+
+/*!
+ @method stepToLongPressViewWithAccessibilityLabel:value:traits:duration:
+ @abstract A step that 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.
+
+ This variation allows finding a particular instance of an accessibility element. For example, a table view might have multiple elements with the accessibility label of "Employee", but only one that also has the accessibility value of "Bob".
+ @param label The accessibility label of the element to tap.
+ @param value The accessibility value of the element to tap.
+ @param traits The accessibility traits of the element to tap. Elements that do not include at least these traits are ignored.
+ @param duration The length of time to long press the element.
+ @result A configured test step.
+ */
++ (id)stepToLongPressViewWithAccessibilityLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits duration:(NSTimeInterval)duration;
+
+/*!
@method stepToEnterTextIntoCurrentFirstResponder:
@abstract A step that enters text into a the current first responder.
@discussion Text is entered into the view by simulating taps on the appropriate keyboard keys if the keyboard is already displayed. Useful to enter text in UIWebViews or components with no accessibility labels.
View
62 Classes/KIFTestStep.m
@@ -354,6 +354,68 @@ + (id)stepToTapScreenAtPoint:(CGPoint)screenPoint;
}];
}
++ (id)stepToLongPressViewWithAccessibilityLabel:(NSString *)label duration:(NSTimeInterval)duration
+{
+ return [self stepToLongPressViewWithAccessibilityLabel:label value:nil duration:duration];
+}
+
++ (id)stepToLongPressViewWithAccessibilityLabel:(NSString *)label value:(NSString *)value duration:(NSTimeInterval)duration
+{
+ return [self stepToLongPressViewWithAccessibilityLabel:label value:value traits:UIAccessibilityTraitNone duration:duration];
+}
+
++ (id)stepToLongPressViewWithAccessibilityLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits duration:(NSTimeInterval)duration
+{
+ NSString *description = nil;
+ if (value.length) {
+ description = [NSString stringWithFormat:@"Long press view with accessibility label \"%@\" and accessibility value \"%@\"", label, value];
+ } else {
+ description = [NSString stringWithFormat:@"Long press view with accessibility label \"%@\"", label];
+ }
+ // After tapping the view we want to wait a short period to allow things to settle (animations and such). We can't do this using CFRunLoopRunInMode() because certain things, such as the built-in media picker, do things with the run loop that are not compatible with this kind of wait. Instead we leverage the way KIF hooks into the existing run loop by returning "wait" results for the desired period.
+ const NSTimeInterval quiesceWaitInterval = 0.5;
+ __block NSTimeInterval quiesceStartTime = 0.0;
+
+ __block UIView *view = nil;
+
+ return [self stepWithDescription:description executionBlock:^(KIFTestStep *step, NSError **error) {
+
+ // If we've already tapped the view and stored it to a variable, and we've waited for the quiesce time to elapse, then we're done.
+ if (view) {
+ KIFTestWaitCondition(([NSDate timeIntervalSinceReferenceDate] - quiesceStartTime) >= quiesceWaitInterval, error, @"Waiting for view to become the first responder.");
+ return KIFTestStepResultSuccess;
+ }
+
+ UIAccessibilityElement *element = [self _accessibilityElementWithLabel:label accessibilityValue:value tappable:YES traits:traits error:error];
+ if (!element) {
+ return KIFTestStepResultWait;
+ }
+
+ view = [UIAccessibilityElement viewContainingAccessibilityElement:element];
+ KIFTestWaitCondition(view, error, @"Failed to find view for accessibility element with label \"%@\"", label);
+
+ if (![self _isUserInteractionEnabledForView:view]) {
+ if (error) {
+ *error = [[[NSError alloc] initWithDomain:@"KIFTest" code:KIFTestStepResultFailure userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"View with accessibility label \"%@\" is not enabled for interaction", label], NSLocalizedDescriptionKey, nil]] autorelease];
+ }
+ return KIFTestStepResultWait;
+ }
+
+ CGRect elementFrame = [view.window convertRect:element.accessibilityFrame toView:view];
+ CGPoint tappablePointInElement = [view tappablePointInRect:elementFrame];
+
+ // This is mostly redundant of the test in _accessibilityElementWithLabel:
+ KIFTestWaitCondition(!isnan(tappablePointInElement.x), error, @"The element with accessibility label %@ is not tappable", label);
+ [view longPressAtPoint:tappablePointInElement duration:duration];
+
+ KIFTestCondition(![view canBecomeFirstResponder] || [view isDescendantOfFirstResponder], error, @"Failed to make the view %@ which contains the accessibility element \"%@\" into the first responder", view, label);
+
+ quiesceStartTime = [NSDate timeIntervalSinceReferenceDate];
+
+ KIFTestWaitCondition(NO, error, @"Waiting for the view to settle.");
+ }];
+}
+
+ (id)stepToEnterTextIntoCurrentFirstResponder:(NSString *)text {
NSString *description = [NSString stringWithFormat:@"Type the text \"%@\" into the current first responder", text];
return [self stepWithDescription:description executionBlock:^(KIFTestStep *step, NSError **error) {
Something went wrong with that request. Please try again.