Skip to content

Instantly share code, notes, and snippets.

@augustj
Created July 23, 2014 16:44
Show Gist options
  • Save augustj/66a416cb549a59db0cf8 to your computer and use it in GitHub Desktop.
Save augustj/66a416cb549a59db0cf8 to your computer and use it in GitHub Desktop.
KIF accessibilityElementExists
- (BOOL)accessibilityElementExists:(NSString *)label {
/* OK, so KIF doesn't have a built in "optional" test, nor does it have a friendly "If element exists".
* It was possible to wait for an element to exist and catch the exception, however if the element didn't exist the test would fail.
* This code is almost a direct copy/paste from UIAccessibilityElement-KIFAdditions, however it doesn't use errors
* - Max Chuquimia
*/
__block UIView *view = nil;
BOOL showing = TRUE;
@try
{
[self runBlockWithoutError:^KIFTestStepResult(NSError **error){
error = nil;
return [KIFUITestActor accessibilityElement:NULL view:&view withLabel:label value:nil traits:UIAccessibilityTraitNone tappable:NO] ? KIFTestStepResultSuccess : KIFTestStepResultWait;
} timeout:1];
}
@catch (NSException *exception)
{
showing = FALSE;
}
return showing;
}
// The following are just to support the method above. From https://gist.github.com/Jugale/54f5d5cf13d25353f7b0
- (void)runBlockWithoutError:(KIFTestExecutionBlock)executionBlock timeout:(NSTimeInterval)timeout {
@autoreleasepool {
NSDate *startDate = [NSDate date];
KIFTestStepResult result;
NSError *error = nil;
while ((result = executionBlock(&error)) == KIFTestStepResultWait && -[startDate timeIntervalSinceNow] < timeout) {
CFRunLoopRunInMode([[UIApplication sharedApplication] currentRunLoopMode] ?: kCFRunLoopDefaultMode, 0.1, false);
}
if (result == KIFTestStepResultWait)
{
result = KIFTestStepResultFailure;
}
if (result == KIFTestStepResultFailure)
{
NSException *e = [NSException exceptionWithName:@"KIF Extension Exception" reason:@"Could not find accessibility element" userInfo:nil];
[e raise];
}
}
}
+ (UIView *)viewContainingAccessibilityElement:(UIAccessibilityElement *)element tappable:(BOOL)mustBeTappable {
// Small safety mechanism. If someone calls this method after a failing call to accessibilityElementWithLabel:..., we don't want to wipe out the error message.
if (!element) {
return nil;
}
// Make sure the element is visible
UIView *view = [UIAccessibilityElement viewContainingAccessibilityElement:element];
if (!view) {
return nil;
}
// Scroll the view to be visible if necessary
UIScrollView *scrollView = (UIScrollView *)view;
while (scrollView && ![scrollView isKindOfClass:[UIScrollView class]]) {
scrollView = (UIScrollView *)scrollView.superview;
}
if (scrollView) {
if ((UIAccessibilityElement *)view == element) {
[scrollView scrollViewToVisible:view animated:YES];
} else {
CGRect elementFrame = [view.window convertRect:element.accessibilityFrame toView:scrollView];
[scrollView scrollRectToVisible:elementFrame animated:YES];
}
// Give the scroll view a small amount of time to perform the scroll.
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.3, false);
}
if ([[UIApplication sharedApplication] isIgnoringInteractionEvents]) {
return nil;
}
// If we don't require tappability, at least make sure it's not hidden
if ([view isHidden]) {
return nil;
}
if (mustBeTappable && !view.isProbablyTappable) {
return nil;
}
return view;
}
+ (BOOL)accessibilityElement:(out UIAccessibilityElement **)foundElement view:(out UIView **)foundView withLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits tappable:(BOOL)mustBeTappable {
UIAccessibilityElement *element = [KIFUITestActor accessibilityElementWithLabel:label value:value traits:traits];
UIView *view = [KIFUITestActor viewContainingAccessibilityElement:element tappable:mustBeTappable];
return element || view;
}
+ (UIAccessibilityElement *)accessibilityElementWithLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits {
UIAccessibilityElement *element = [[UIApplication sharedApplication] accessibilityElementWithLabel:label accessibilityValue:value traits:traits];
if (element) {
return element;
}
element = [[UIApplication sharedApplication] accessibilityElementWithLabel:label accessibilityValue:nil traits:traits];
// For purposes of a better error message, see if we can find the view, just not a view with the specified value.
if (value && element) {
return nil;
}
// Check the traits, too.
element = [[UIApplication sharedApplication] accessibilityElementWithLabel:label accessibilityValue:nil traits:UIAccessibilityTraitNone];
if (traits != UIAccessibilityTraitNone && element) {
return nil;
}
return nil;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment