Can I check if a view exists on the screen with KIF?

人盡茶涼 提交于 2019-12-03 22:57:01
user2738882

I would suggest to try this approach:

if([[[UIApplication sharedApplication] keyWindow] accessibilityElementWithLabel:@"backButton"] != nil) {
     [tester tapViewWithAccessibilityLabel:@"backButton"];
} else {
     [tester tapViewWithAccessibilityLabel:@"Logout"];
}
kuglisb

These methods do the trick. Add them to a category for KIFUITestActor.

#import "UIApplication-KIFAdditions.h" 
#import "UIAccessibilityElement-KIFAdditions.h"
#import "NSError-KIFAdditions.h"

- (BOOL)existsViewWithAccessibilityLabel:(NSString *)label
{
    UIView *view = nil;
    UIAccessibilityElement *element = nil;
    return [self existsAccessibilityElement:&element view:&view withLabel:label value:nil traits:UIAccessibilityTraitNone tappable:YES];
}

- (BOOL)existsAccessibilityElement:(UIAccessibilityElement **)element view:(out UIView **)view withLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits tappable:(BOOL)mustBeTappable
{
    KIFTestStepResult (^executionBlock)(NSError **) = ^(NSError **error) {
        return [UIAccessibilityElement accessibilityElement:element view:view withLabel:label value:value traits:traits tappable:mustBeTappable error:error] ? KIFTestStepResultSuccess : KIFTestStepResultWait;
    };

    NSDate *startDate = [NSDate date];
    KIFTestStepResult result;
    NSError *error = nil;
    NSTimeInterval timeout = 10.0;

    while ((result = executionBlock(&error)) == KIFTestStepResultWait && -[startDate timeIntervalSinceNow] < timeout) {
        CFRunLoopRunInMode([[UIApplication sharedApplication] currentRunLoopMode] ?: kCFRunLoopDefaultMode, 0.1, false);
    }

    if (result == KIFTestStepResultWait) {
        error = [NSError KIFErrorWithUnderlyingError:error format:@"The step timed out after %.2f seconds: %@", timeout, error.localizedDescription];
        result = KIFTestStepResultFailure;
    }

    return (result == KIFTestStepResultSuccess) ? YES : NO;
}

It works for me very well.

In case anyone is still looking for an answer, there is a family of methods in KIF that does just that KIFUITestActor-ConditionalTests.h:

- (BOOL)tryFindingViewWithAccessibilityLabel:(NSString *)label error:(out NSError **)error;

- (BOOL)tryFindingViewWithAccessibilityLabel:(NSString *)label traits:(UIAccessibilityTraits)traits error:(out NSError **)error;

- (BOOL)tryFindingViewWithAccessibilityLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits error:(out NSError **)error;

- (BOOL)tryFindingTappableViewWithAccessibilityLabel:(NSString *)label error:(out NSError **)error;

- (BOOL)tryFindingTappableViewWithAccessibilityLabel:(NSString *)label traits:(UIAccessibilityTraits)traits error:(out NSError **)error;

- (BOOL)tryFindingTappableViewWithAccessibilityLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits error:(out NSError **)error;

- (BOOL)tryFindingAccessibilityElement:(out UIAccessibilityElement **)element view:(out UIView **)view withIdentifier:(NSString *)identifier tappable:(BOOL)mustBeTappable error:(out NSError **)error;

- (BOOL)tryFindingAccessibilityElement:(out UIAccessibilityElement **)element view:(out UIView **)view withElementMatchingPredicate:(NSPredicate *)predicate tappable:(BOOL)mustBeTappable error:(out NSError **)error;

If you're using the Accessibility Identifier additions (pod 'KIF/IdentifierTests') there's also the very handy equivalent method: - (BOOL) tryFindingViewWithAccessibilityIdentifier:(NSString *) accessibilityIdentifier;

For swift 3:

/** return true when the view is found */
func searchForElement(_ label:String) -> Bool{
    do {
        try tester().tryFindingView(withAccessibilityLabel: label)
        return true
    } catch {
        return false

    }
}

You could try something like this:

@try {
   if([tester waitForViewWithAccessibilityLabel:@"backButton"])
   {
      [tester tapViewWithAccessibilityLabel:@"backButton"];
   }
@catch (NSException *exception )
{
   [tester tapViewwithAccesibilityLabel:@"Logout"];
}
@finally 
{
   NSLOG(@"User logged out.");
}

I made this function that seems to do the trick in a pinch, but it would have some issues if multiple integration tests were simultaneously relying on the global default timeout. So far, seems to work for me.

static CGFloat CPKIFDefaultTimeout = 2

- (BOOL)elementExistsWithAccessibilityLabel:(NSString *)accessibilityLabel {
    [KIFTestActor setDefaultTimeout:0.0];
    BOOL result = [tester waitForViewWithAccessibilityLabel:accessibilityLabel] ? YES : NO;
    [KIFTestActor CPKIFDefaultTimeout];
    return result;
}

Alright, none of these worked for me... However I have a solution

Checkout this gist.

What I've done is taken KIF's code and just removed their error checking - works like a charm for me.

This won't fail your tests when it can't find an element!

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!