Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

stepToWaitForSwitchWithAccessibilityLabel:value: for easier verification of UISwitch value #138

Closed
wants to merge 7 commits into from

2 participants

Simon Yun Jim Puls
Simon Yun

stepToWaitForViewWithAccessibilityLabel:value:traits: works for checking the value of a UISwitch, but I suspect that people need to do some extra typing (switchIsOn ? @"1" : @"0") to provide the value as a string. The implementation is mostly copied from stepToSetOn:forSwitchWithAccessibilityLabel:.

Simon Yun

Done.

Keh-Li Sheng added some commits
Simon Yun simonyun closed this
Simon Yun

Re-submitted this pull request properly with its own branch: #210.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 27, 2012
  1. Simon Yun
  2. Simon Yun

    Rename to stepToWaitForSwitchWithAccessibilityLabel:withValue: to con…

    simonyun authored
    …form better to KIF conventions.
  3. Simon Yun
Commits on Jul 30, 2012
  1. Simon Yun

    Add stepToEnterText:intoViewWithAccessibilityLabel:traits:expectedRes…

    simonyun authored
    …ult:clearTextFirst: to potentially clear existing text before entering text.
Commits on Oct 26, 2012
  1. Simon Yun

    Add stepToSwipeViewWithAccessibilityLabel:inDirection:withDisplacemen…

    simonyun authored
    …t: to support passing in a custom displacement for a swipe.
Commits on Mar 9, 2013
  1. add offset parameter to swipe step

    Keh-Li Sheng authored
  2. Merge branch 'offset'

    Keh-Li Sheng authored
This page is out of date. Refresh to see the latest.
Showing with 143 additions and 9 deletions.
  1. +36 −0 Classes/KIFTestStep.h
  2. +107 −9 Classes/KIFTestStep.m
36 Classes/KIFTestStep.h
View
@@ -350,6 +350,19 @@ typedef KIFTestStepResult (^KIFTestStepExecutionBlock)(KIFTestStep *step, NSErro
+ (id)stepToEnterText:(NSString *)text intoViewWithAccessibilityLabel:(NSString *)label traits:(UIAccessibilityTraits)traits expectedResult:(NSString *)expectedResult;
/*!
+ @method stepToEnterText:intoViewWithAccessibilityLabel:traits:
+ @abstract A step that enters text into 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, a tap event is simulated in the center of the view or element, then text is entered into the view by simulating taps on the appropriate keyboard keys.
+ @param text The text to enter.
+ @param label The accessibility label of the element to type into.
+ @param traits The accessibility traits of the element to type into. Elements that do not include at least these traits are ignored.
+ @param expectedResult What the text value should be after entry, including any formatting done by the field. If this is nil, the "text" parameter will be used.
+ @param clearTextFirst Whether to look for and tap the clear text button on the text field. This will be ignored if the "text" selector on the view returns nil or empty string. If the text is non-empty and for some reason the clear text button can't be found and tapped, this step will return an error.
+ @result A configured test step.
+ */
++ (id)stepToEnterText:(NSString *)text intoViewWithAccessibilityLabel:(NSString *)label traits:(UIAccessibilityTraits)traits expectedResult:(NSString *)expectedResult clearTextFirst:(BOOL)clearTextFirst;
+
+/*!
@method stepToSelectPickerViewRowWithTitle:
@abstract A step that selects an item from a currently visible picker view.
@discussion With a picker view already visible, this step will find an item with the given title, select that item, and tap the Done button.
@@ -369,6 +382,16 @@ typedef KIFTestStepResult (^KIFTestStepExecutionBlock)(KIFTestStep *step, NSErro
+ (id)stepToSetOn:(BOOL)switchIsOn forSwitchWithAccessibilityLabel:(NSString *)label;
/*!
+ @method stepToWaitForSwitchWithAccessibilityLabel:withValue:
+ @abstract A step that verifies that a UISwitch is in a specified position.
+ @discussion The UISwitch 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, the step will succeed if it's in the specified position and fail if it's not.
+ @param switchIsOn The expected position of the UISwitch.
+ @param label The accessibility label of the UISwitch element.
+ @result A configured test step.
+ */
++ (id)stepToWaitForSwitchWithAccessibilityLabel:(NSString *)label value:(BOOL)switchIsOn;
+
+/*!
@method stepToDismissPopover
@abstract A step that dismisses a popover on screen.
@discussion With a popover up, tap at the top-left corner of the screen.
@@ -432,6 +455,19 @@ typedef enum {
+ (id)stepToSwipeViewWithAccessibilityLabel:(NSString *)label inDirection:(KIFSwipeDirection)direction;
/*!
+ @method stepToSwipeViewWithAccessibilityLabel:inDirection:withDisplacement:
+ @abstract A step that swipes a particular view in the view hierarchy in the given direction.
+ @discussion The view will get the view with the specified accessibility label and swipe the screen in the given direction from the view's center.
+ @param label The accessibility label of the view to swipe.
+ @param direction The direction in which to swipe.
+ @PARAM displacement The amount of displacement in the path of the swipe.
+ @param offset An offset from center inside the view
+ @result A configured test step.
+ */
++ (id)stepToSwipeViewWithAccessibilityLabel:(NSString *)label inDirection:(KIFSwipeDirection)direction withDisplacement:(CGFloat)displacement;
+
++ (id)stepToSwipeViewWithAccessibilityLabel:(NSString *)label inDirection:(KIFSwipeDirection)direction withDisplacement:(CGFloat)displacement atOffset:(UIOffset)offset;
+/*!
@method stepToWaitForFirstResponderWithAccessibilityLabel:
@abstract A step that waits until a view or accessibility element is the first responder.
@discussion The first responder is found by searching the view hierarchy of the application's
116 Classes/KIFTestStep.m
View
@@ -37,7 +37,7 @@ + (BOOL)_enterCustomKeyboardCharacter:(NSString *)characterString;
+ (UIAccessibilityElement *)_accessibilityElementWithLabel:(NSString *)label accessibilityValue:(NSString *)value tappable:(BOOL)mustBeTappable traits:(UIAccessibilityTraits)traits error:(out NSError **)error;
typedef CGPoint KIFDisplacement;
-+ (KIFDisplacement)_displacementForSwipingInDirection:(KIFSwipeDirection)direction;
++ (KIFDisplacement)_displacementForSwipingInDirection:(KIFSwipeDirection)direction withDisplacement:(CGFloat)displacement;
@end
@@ -357,6 +357,18 @@ + (id)stepToEnterText:(NSString *)text intoViewWithAccessibilityLabel:(NSString
+ (id)stepToEnterText:(NSString *)text intoViewWithAccessibilityLabel:(NSString *)label traits:(UIAccessibilityTraits)traits expectedResult:(NSString *)expectedResult;
{
+ return [self stepToEnterText:text intoViewWithAccessibilityLabel:label traits:traits expectedResult:expectedResult clearTextFirst:NO];
+}
+
++ (id)stepToEnterText:(NSString *)text intoViewWithAccessibilityLabel:(NSString *)label traits:(UIAccessibilityTraits)traits expectedResult:(NSString *)expectedResult clearTextFirst:(BOOL)clearTextFirst
+{
+ __block BOOL performedInitialEmptinessCheck = NO;
+ __block BOOL viewInitiallyContainsText = NO;
+
+ __block UIAccessibilityElement *clearTextElement = nil;
+ __block NSTimeInterval clearTextQuiesceStartTime = 0.0;
+ const NSTimeInterval clearTextQuiesceWaitInterval = 0.5;
+
NSString *description = [NSString stringWithFormat:@"Type the text \"%@\" into the view with accessibility label \"%@\"", text, label];
return [self stepWithDescription:description executionBlock:^(KIFTestStep *step, NSError **error) {
@@ -367,7 +379,7 @@ + (id)stepToEnterText:(NSString *)text intoViewWithAccessibilityLabel:(NSString
UIView *view = [UIAccessibilityElement viewContainingAccessibilityElement:element];
KIFTestWaitCondition(view, error, @"Cannot find view with accessibility label \"%@\"", label);
-
+
CGRect elementFrame = [view.window convertRect:element.accessibilityFrame toView:view];
CGPoint tappablePointInElement = [view tappablePointInRect:elementFrame];
@@ -380,6 +392,61 @@ + (id)stepToEnterText:(NSString *)text intoViewWithAccessibilityLabel:(NSString
// Wait for the keyboard
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
+ // Tap to clear any existing text first, if specified
+ if (clearTextFirst) {
+
+ // First check if the field has any text in it.
+ if (!performedInitialEmptinessCheck) {
+ // This is probably a UITextField- or UITextView-ish view, so make sure it's non-empty before looking for the clear text button.
+ if ([view respondsToSelector:@selector(text)]) {
+ NSString *actual = [view performSelector:@selector(text)];
+
+ viewInitiallyContainsText = [actual length] != 0;
+ }
+
+ performedInitialEmptinessCheck = YES;
+ }
+
+ // We only need to clear text if the view is non-empty.
+ if (viewInitiallyContainsText) {
+ if (!clearTextElement) {
+ // We haven't tapped the button yet.
+
+ // NOTE: Using a hard-coded English accessibility label to grab the clear text element is not robust.
+ // But it's good enough for now.
+ NSString *clearTextLabel = @"Clear text";
+ clearTextElement = [self _accessibilityElementWithLabel:clearTextLabel accessibilityValue:nil tappable:YES traits:UIAccessibilityTraitButton error:error];
+ if (!clearTextElement) {
+ return KIFTestStepResultWait;
+ }
+
+ UIView *clearTextView = [UIAccessibilityElement viewContainingAccessibilityElement:clearTextElement];
+ KIFTestWaitCondition(clearTextView, error, @"Failed to find view for accessibility element with label \"%@\"", clearTextLabel);
+
+ if (![self _isUserInteractionEnabledForView:clearTextView]) {
+ if (error) {
+ *error = [[[NSError alloc] initWithDomain:@"KIFTest" code:KIFTestStepResultFailure userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"View with accessibility label \"%@\" is not enabled for interaction", clearTextLabel], NSLocalizedDescriptionKey, nil]] autorelease];
+ }
+ return KIFTestStepResultWait;
+ }
+
+ CGRect elementFrame = [clearTextView.window convertRect:clearTextElement.accessibilityFrame toView:clearTextView];
+ CGPoint tappablePointInElement = [clearTextView tappablePointInRect:elementFrame];
+
+ // This is mostly redundant of the test in _accessibilityElementWithLabel:
+ KIFTestWaitCondition(!isnan(tappablePointInElement.x), error, @"The element with accessibility label %@ is not tappable", clearTextLabel);
+ [clearTextView tapAtPoint:tappablePointInElement];
+
+ KIFTestCondition(![clearTextView canBecomeFirstResponder] || [clearTextView isDescendantOfFirstResponder], error, @"Failed to make the view %@ which contains the accessibility element \"%@\" into the first responder", clearTextView, clearTextLabel);
+ KIFTestWaitCondition(NO, error, @"Waiting for the view to settle.");
+
+ } else {
+ // We've already tapped the clear text button; wait for the quiesce interval.
+ KIFTestWaitCondition(([NSDate timeIntervalSinceReferenceDate] - clearTextQuiesceStartTime) >= clearTextQuiesceWaitInterval, error, @"Waiting for things to stabilize after tapping the clear text button.");
+ }
+ }
+ }
+
for (NSUInteger characterIndex = 0; characterIndex < [text length]; characterIndex++) {
NSString *characterString = [text substringWithRange:NSMakeRange(characterIndex, 1)];
@@ -498,6 +565,25 @@ + (id)stepToSetOn:(BOOL)switchIsOn forSwitchWithAccessibilityLabel:(NSString *)l
}];
}
++ (id)stepToWaitForSwitchWithAccessibilityLabel:(NSString *)label value:(BOOL)switchIsOn
+{
+ NSString *description = [NSString stringWithFormat:@"Verify that the switch with accessibility label \"%@\" is %@", label, switchIsOn ? @"ON" : @"OFF"];
+ return [self stepWithDescription:description executionBlock:^(KIFTestStep *step, NSError **error) {
+
+ UIAccessibilityElement *element = [self _accessibilityElementWithLabel:label accessibilityValue:nil tappable:YES traits:UIAccessibilityTraitNone error:error];
+ if (!element) {
+ return KIFTestStepResultWait;
+ }
+
+ UISwitch *switchView = (UISwitch *)[UIAccessibilityElement viewContainingAccessibilityElement:element];
+ KIFTestWaitCondition(switchView, error, @"Cannot find switch with accessibility label \"%@\"", label);
+ KIFTestWaitCondition([switchView isKindOfClass:[UISwitch class]], error, @"View with accessibility label \"%@\" is a %@, not a UISwitch", label, NSStringFromClass([switchView class]));
+
+ BOOL current = switchView.on;
+ return current == switchIsOn ? KIFTestStepResultSuccess : KIFTestStepResultFailure;
+ }];
+}
+
+ (id)stepToDismissPopover;
{
return [self stepWithDescription:@"Dismiss the popover" executionBlock:^(KIFTestStep *step, NSError **error) {
@@ -549,9 +635,20 @@ + (id)stepToTapRowInTableViewWithAccessibilityLabel:(NSString*)tableViewLabel at
}
#define NUM_POINTS_IN_SWIPE_PATH 20
+#define MAJOR_SWIPE_DISPLACEMENT 200
+ (id)stepToSwipeViewWithAccessibilityLabel:(NSString *)label inDirection:(KIFSwipeDirection)direction
{
+ return [self stepToSwipeViewWithAccessibilityLabel:label inDirection:direction withDisplacement:MAJOR_SWIPE_DISPLACEMENT];
+}
+
++ (id)stepToSwipeViewWithAccessibilityLabel:(NSString *)label inDirection:(KIFSwipeDirection)direction withDisplacement:(CGFloat)displacement
+{
+ return [KIFTestStep stepToSwipeViewWithAccessibilityLabel:label inDirection:direction withDisplacement:displacement atOffset:UIOffsetZero];
+}
+
++ (id)stepToSwipeViewWithAccessibilityLabel:(NSString *)label inDirection:(KIFSwipeDirection)direction withDisplacement:(CGFloat)displacement atOffset:(UIOffset)offset
+{
// The original version of this came from http://groups.google.com/group/kif-framework/browse_thread/thread/df3f47eff9f5ac8c
NSString *directionDescription = nil;
@@ -586,8 +683,10 @@ + (id)stepToSwipeViewWithAccessibilityLabel:(NSString *)label inDirection:(KIFSw
CGRect elementFrame = [viewToSwipe.window convertRect:element.accessibilityFrame toView:viewToSwipe];
CGPoint swipeStart = CGPointCenteredInRect(elementFrame);
+ // Offset by the desired amount
+ swipeStart = CGPointMake(swipeStart.x + offset.horizontal, swipeStart.y + offset.vertical);
- KIFDisplacement swipeDisplacement = [self _displacementForSwipingInDirection:direction];
+ KIFDisplacement swipeDisplacement = [self _displacementForSwipingInDirection:direction withDisplacement:displacement];
CGPoint swipePath[NUM_POINTS_IN_SWIPE_PATH];
@@ -984,10 +1083,9 @@ + (UIAccessibilityElement *)_accessibilityElementWithLabel:(NSString *)label acc
return element;
}
-#define MAJOR_SWIPE_DISPLACEMENT 200
#define MINOR_SWIPE_DISPLACEMENT 5
-+ (KIFDisplacement)_displacementForSwipingInDirection:(KIFSwipeDirection)direction
++ (KIFDisplacement)_displacementForSwipingInDirection:(KIFSwipeDirection)direction withDisplacement:(CGFloat)displacement
{
switch (direction)
{
@@ -995,16 +1093,16 @@ + (KIFDisplacement)_displacementForSwipingInDirection:(KIFSwipeDirection)directi
// swipe if you move purely horizontally or vertically, so need a
// slight orthogonal offset too.
case KIFSwipeDirectionRight:
- return CGPointMake(MAJOR_SWIPE_DISPLACEMENT, MINOR_SWIPE_DISPLACEMENT);
+ return CGPointMake(displacement, MINOR_SWIPE_DISPLACEMENT);
break;
case KIFSwipeDirectionLeft:
- return CGPointMake(-MAJOR_SWIPE_DISPLACEMENT, MINOR_SWIPE_DISPLACEMENT);
+ return CGPointMake(-displacement, MINOR_SWIPE_DISPLACEMENT);
break;
case KIFSwipeDirectionUp:
- return CGPointMake(MINOR_SWIPE_DISPLACEMENT, -MAJOR_SWIPE_DISPLACEMENT);
+ return CGPointMake(MINOR_SWIPE_DISPLACEMENT, -displacement);
break;
case KIFSwipeDirectionDown:
- return CGPointMake(MINOR_SWIPE_DISPLACEMENT, MAJOR_SWIPE_DISPLACEMENT);
+ return CGPointMake(MINOR_SWIPE_DISPLACEMENT, displacement);
break;
default:
return CGPointZero;
Something went wrong with that request. Please try again.