From 5ebf267253d8a9b42a8c6aa3be0b779118f7d3c5 Mon Sep 17 00:00:00 2001 From: Harley Cooper Date: Thu, 8 Feb 2018 14:56:06 -0800 Subject: [PATCH] Addressing code review comments from @justinseanmartin --- Classes/KIFTestActor.h | 36 ----- Classes/KIFTestActor.m | 36 +---- Classes/KIFTestCase.m | 6 - Classes/KIFTextInputTraitsOverrides.h | 21 ++- Classes/KIFTextInputTraitsOverrides.m | 156 ++++++++++++++------- Classes/KIFUITestActor.h | 8 +- Classes/KIFUITestActor.m | 5 + KIF Tests/AutocorrectTests.m | 18 ++- KIF Tests/AutocorrectTests_ViewTestActor.m | 16 ++- 9 files changed, 160 insertions(+), 142 deletions(-) diff --git a/Classes/KIFTestActor.h b/Classes/KIFTestActor.h index 852eba2ff..8b0b2a63e 100644 --- a/Classes/KIFTestActor.h +++ b/Classes/KIFTestActor.h @@ -159,42 +159,6 @@ typedef void (^KIFTestCompletionBlock)(KIFTestStepResult result, NSError *error) */ + (void)setStepDelay:(NSTimeInterval)newStepDelay; -/*! - @abstract Enable autocorrect in KIF tests - @discussion When @c NO, autocorrect is disabled for the duration of the app lifecycle. It is highly unlikely that tests should ever require autocorrect, but this will provide the opportunity to decide whether or not to enable it. - */ -+ (void)setEnableAutocorrect:(BOOL)enableAutocorrect; - -/*! - @abstract Enable smart dashes in KIF tests - @discussion When @c NO, smart dashes are disabled for the duration of the app lifecycle. It is highly unlikely that tests should ever require smart dashes, but this will provide the opportunity to decide whether or not to enable them. - */ -+ (void)setEnableSmartDashes:(BOOL)enableSmartDashes; - -/*! - @abstract Enable smart quotes in KIF tests - @discussion When @c NO, smart quotes are disabled for the duration of the app lifecycle. It is highly unlikely that tests should ever require smart quotes, but this will provide the opportunity to decide whether or not to enable them. - */ -+ (void)setEnableSmartQuotes:(BOOL)enableSmartQuotes; - -/*! - @abstract Whether autocorrect is enabled in KIF tests. - @discussion To enable autocorrect, call +setAutocorrectDisabled: with @c YES. - */ -+ (BOOL)autocorrectEnabled; - -/*! - @abstract Whether smart dashes are enabled in KIF tests. - @discussion To enable smart dashes, call +setSmartDashesDisabled: with @c YES. - */ -+ (BOOL)smartDashesEnabled; - -/*! - @abstract Whether smart quotes are enabled in KIF tests. - @discussion To enable smart quotes, call +setSmartQuotesDisabled: with @c YES. - */ -+ (BOOL)smartQuotesEnabled; - /*! @abstract Fails the test. @discussion Mostly useful for test debugging or as a placeholder when building new tests. diff --git a/Classes/KIFTestActor.m b/Classes/KIFTestActor.m index 45841e8de..1957a4863 100644 --- a/Classes/KIFTestActor.m +++ b/Classes/KIFTestActor.m @@ -1,5 +1,5 @@ // -// KIFTester.m +// KIFTestActor.m // KIF // // Created by Brian Nickel on 12/13/12. @@ -130,10 +130,6 @@ - (void)runBlock:(KIFTestExecutionBlock)executionBlock static NSTimeInterval KIFTestStepDefaultTimeout = 10.0; static NSTimeInterval KIFTestStepDelay = 0.1; -static BOOL KIFAutocorrectEnabled = NO; -static BOOL KIFSmartDashesEnabled = NO; -static BOOL KIFSmartQuotesEnabled = NO; - + (NSTimeInterval)defaultAnimationWaitingTimeout { return KIFTestStepDefaultAnimationWaitingTimeout; @@ -174,36 +170,6 @@ + (void)setStepDelay:(NSTimeInterval)newStepDelay; KIFTestStepDelay = newStepDelay; } -+ (void)setEnableAutocorrect:(BOOL)enableAutocorrect; -{ - KIFAutocorrectEnabled = enableAutocorrect; -} - -+ (void)setEnableSmartDashes:(BOOL)enableSmartDashes; -{ - KIFSmartDashesEnabled = enableSmartDashes; -} - -+ (void)setEnableSmartQuotes:(BOOL)enableSmartQuotes; -{ - KIFSmartQuotesEnabled = enableSmartQuotes; -} - -+ (BOOL)autocorrectEnabled; -{ - return KIFAutocorrectEnabled; -} - -+ (BOOL)smartDashesEnabled; -{ - return KIFSmartDashesEnabled; -} - -+ (BOOL)smartQuotesEnabled; -{ - return KIFSmartQuotesEnabled; -} - #pragma mark Generic tests - (void)fail diff --git a/Classes/KIFTestCase.m b/Classes/KIFTestCase.m index 751c36552..83855f263 100644 --- a/Classes/KIFTestCase.m +++ b/Classes/KIFTestCase.m @@ -12,7 +12,6 @@ #import "UIApplication-KIFAdditions.h" #import "KIFTestActor.h" #import "KIFAccessibilityEnabler.h" -#import "KIFTextInputTraitsOverrides.h" #define SIG(class, selector) [class instanceMethodSignatureForSelector:selector] @@ -66,11 +65,6 @@ + (NSArray *)testInvocations + (void)setUp { KIFEnableAccessibility(); - - KIFSetAutocorrect([KIFTestActor autocorrectEnabled]); - KIFSetSmartDashes([KIFTestActor smartDashesEnabled]); - KIFSetSmartQuotes([KIFTestActor smartQuotesEnabled]); - [self performSetupTearDownWithSelector:@selector(beforeAll)]; } diff --git a/Classes/KIFTextInputTraitsOverrides.h b/Classes/KIFTextInputTraitsOverrides.h index 166ce3c25..29665a442 100644 --- a/Classes/KIFTextInputTraitsOverrides.h +++ b/Classes/KIFTextInputTraitsOverrides.h @@ -5,8 +5,21 @@ // Created by Harley Cooper on 1/31/18. // -#import +@interface KIFTextInputTraitsOverrides : NSObject -FOUNDATION_EXTERN void KIFSetAutocorrect(BOOL); -FOUNDATION_EXTERN void KIFSetSmartQuotes(BOOL); -FOUNDATION_EXTERN void KIFSetSmartDashes(BOOL); +/*! + @abstract If set to @c YES then KIF will observe default autocorrect behavior. If set to @c NO then autocorrect will always be disabled. + */ +@property(class) BOOL allowDefaultAutocorrectBehavior; + +/*! + @abstract If set to @c YES then KIF will observe default smart dashes behavior. If set to @c NO then smart dashes will always be disabled. + */ +@property(class) BOOL allowDefaultSmartDashesBehavior; + +/*! + @abstract If set to @c YES then KIF will observe default smart quotes behavior. If set to @c NO then smart quotes will always be disabled. + */ +@property(class) BOOL allowDefaultSmartQuotesBehavior; + +@end diff --git a/Classes/KIFTextInputTraitsOverrides.m b/Classes/KIFTextInputTraitsOverrides.m index 5ca9cc4ac..f7bc7dd8d 100644 --- a/Classes/KIFTextInputTraitsOverrides.m +++ b/Classes/KIFTextInputTraitsOverrides.m @@ -8,68 +8,130 @@ #import #import "KIFTextInputTraitsOverrides.h" -static IMP autocorrectOriginalImp; -static IMP smartDashesOriginalImp; -static IMP smartQuotesOriginalImp; +@interface KIFTextInputTraitsOverrides() -void KIFSetAutocorrect(BOOL setAutocorrectOn) { - if(!autocorrectOriginalImp) { - autocorrectOriginalImp = class_getMethodImplementation([UITextField class], @selector(autocorrectionType)); - } +/*! + @abstract Swizzles the @c autocorrectionType property of @c UITextField + @discussion Sets the property to have default behavior when @c allowDefaultAutocorrectBehavior is set to @c YES, and always return @c UITextAutocorrectionTypeNo when it's set to no. + */ ++ (void)KIFSwizzleTextFieldAutocorrect; + +/*! + @abstract Swizzles the @c smartDashesType property of @c UITextField + @discussion Sets the property to have default behavior when @c allowDefaultSmartDashesBehavior is set to @c YES, and always return @c UITextSmartDashesTypeNo when it's set to no. + */ ++ (void)KIFSwizzleTextFieldSmartDashes; + +/*! + @abstract Swizzles the @c smartQuotesType property of @c UITextField + @discussion Sets the property to have default behavior when @c allowDefaultSmartQuotesBehavior is set to @c YES, and always return @c UITextSmartQuotesTypeNo when it's set to no. + */ ++ (void)KIFSwizzleTextFieldSmartQuotes; + +@end + +@implementation KIFTextInputTraitsOverrides + +static BOOL KIFAutocorrectEnabled = NO; +static BOOL KIFSmartDashesEnabled = NO; +static BOOL KIFSmartQuotesEnabled = NO; + ++ (void)load +{ + [self KIFSwizzleTextFieldAutocorrect]; + [self KIFSwizzleTextFieldSmartDashes]; + [self KIFSwizzleTextFieldSmartQuotes]; +} + ++ (BOOL)allowDefaultAutocorrectBehavior +{ + return KIFAutocorrectEnabled; +} + ++ (void)setAllowDefaultAutocorrectBehavior:(BOOL)allowDefaultBehavior +{ + KIFAutocorrectEnabled = allowDefaultBehavior; +} + ++ (BOOL)allowDefaultSmartDashesBehavior +{ + return KIFSmartDashesEnabled; +} + ++ (void)setAllowDefaultSmartDashesBehavior:(BOOL)allowDefaultBehavior +{ + KIFSmartDashesEnabled = allowDefaultBehavior; +} - IMP autocorrectImp; - if(setAutocorrectOn) { - autocorrectImp = autocorrectOriginalImp; - } else if(!setAutocorrectOn) { - autocorrectImp = imp_implementationWithBlock(^(UITextField *_self) { - return UITextAutocorrectionTypeNo; ++ (BOOL)allowDefaultSmartQuotesBehavior +{ + return KIFSmartQuotesEnabled; +} + ++ (void)setAllowDefaultSmartQuotesBehavior:(BOOL)allowDefaultBehavior +{ + KIFSmartQuotesEnabled = allowDefaultBehavior; +} + ++ (void)KIFSwizzleTextFieldAutocorrect +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + struct objc_method_description autocorrectionTypeMethodDescription = protocol_getMethodDescription(@protocol(UITextInputTraits), @selector(autocorrectionType), NO, YES); + IMP autocorrectOriginalImp = class_getMethodImplementation([UITextField class], @selector(autocorrectionType)); + IMP autocorrectImp = imp_implementationWithBlock(^(UITextField *_self) { + if(self.allowDefaultAutocorrectBehavior) { + return (NSInteger) autocorrectOriginalImp(_self, @selector(autocorrectionType)); + } else { + return UITextAutocorrectionTypeNo; + } }); - } - struct objc_method_description autocorrectionTypeMethodDescription = protocol_getMethodDescription(@protocol(UITextInputTraits), @selector(autocorrectionType), NO, YES); - class_replaceMethod([UITextField class], @selector(autocorrectionType), autocorrectImp, autocorrectionTypeMethodDescription.types); + class_replaceMethod([UITextField class], @selector(autocorrectionType), autocorrectImp, autocorrectionTypeMethodDescription.types); + }); } -void KIFSetSmartDashes(BOOL setSmartDashesOn) { ++ (void)KIFSwizzleTextFieldSmartDashes +{ // This #ifdef is necessary for versions of Xcode before Xcode 9. #ifdef __IPHONE_11_0 if (@available(iOS 11.0, *)) { - if(!smartDashesOriginalImp) { - smartDashesOriginalImp = class_getMethodImplementation([UITextField class], @selector(smartDashesType)); - } - - IMP smartDashesImp; - if(setSmartDashesOn) { - smartDashesImp = smartDashesOriginalImp; - } else if(!setSmartDashesOn) { - smartDashesImp = imp_implementationWithBlock(^(UITextField *_self) { - return UITextSmartDashesTypeNo; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + struct objc_method_description smartDashesTypeMethodDescription = protocol_getMethodDescription(@protocol(UITextInputTraits), @selector(smartDashesType), NO, YES); + IMP smartDashesOriginalImp = class_getMethodImplementation([UITextField class], @selector(smartDashesType)); + IMP smartDashesImp = imp_implementationWithBlock(^(UITextField *_self) { + if(self.allowDefaultSmartDashesBehavior) { + return (NSInteger) smartDashesOriginalImp(_self, @selector(smartDashesType)); + } else { + return UITextSmartDashesTypeNo; + } }); - } - struct objc_method_description smartDashesTypeMethodDescription = protocol_getMethodDescription(@protocol(UITextInputTraits), @selector(smartDashesType), NO, YES); - class_replaceMethod([UITextField class], @selector(smartDashesType), smartDashesImp, smartDashesTypeMethodDescription.types); + class_replaceMethod([UITextField class], @selector(smartDashesType), smartDashesImp, smartDashesTypeMethodDescription.types); + }); } #endif } -void KIFSetSmartQuotes(BOOL setSmartQuotesOn) { - // This #ifdef is necessary for versions of Xcode before Xcode 9. ++ (void)KIFSwizzleTextFieldSmartQuotes +{ + // This #ifdef is necessary for versions of Xcode before Xcode 9. #ifdef __IPHONE_11_0 - if (@available(iOS 11.0, *)) { - if(!smartQuotesOriginalImp) { - smartQuotesOriginalImp = class_getMethodImplementation([UITextField class], @selector(smartQuotesType)); - } - - IMP smartQuotesImp; - if(setSmartQuotesOn) { - smartQuotesImp = smartQuotesOriginalImp; - } else if(!setSmartQuotesOn) { - smartQuotesImp = imp_implementationWithBlock(^(UITextField *_self) { - return UITextSmartQuotesTypeNo; + if (@available(iOS 11.0, *)) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + struct objc_method_description smartQuotesTypeMethodDescription = protocol_getMethodDescription(@protocol(UITextInputTraits), @selector(smartQuotesType), NO, YES); + IMP smartQuotesOriginalImp = class_getMethodImplementation([UITextField class], @selector(smartQuotesType)); + IMP smartQuotesImp = imp_implementationWithBlock(^(UITextField *_self) { + if(self.allowDefaultSmartQuotesBehavior) { + return (NSInteger) smartQuotesOriginalImp(_self, @selector(smartQuotesType)); + } else { + return UITextSmartQuotesTypeNo; + } + }); + class_replaceMethod([UITextField class], @selector(smartQuotesType), smartQuotesImp, smartQuotesTypeMethodDescription.types); }); } - struct objc_method_description smartQuotesMethodDescription = protocol_getMethodDescription(@protocol(UITextInputTraits), @selector(smartQuotesType), NO, YES); - class_replaceMethod([UITextField class], @selector(smartQuotesType), smartQuotesImp, smartQuotesMethodDescription.types); - } #endif - } + +@end diff --git a/Classes/KIFUITestActor.h b/Classes/KIFUITestActor.h index 4bbabca05..f5821fcba 100644 --- a/Classes/KIFUITestActor.h +++ b/Classes/KIFUITestActor.h @@ -120,7 +120,6 @@ typedef NS_ENUM(NSUInteger, KIFPullToRefreshTiming) { */ - (UIView *)waitForViewWithAccessibilityLabel:(NSString *)label traits:(UIAccessibilityTraits)traits; - /*! @abstract Waits until a view or accessibility element is present. @discussion The view or accessibility element with the given label is found in the view hierarchy. If the element isn't found, then the step will attempt to wait until it is. Note that the view does not necessarily have to be visible on the screen, and may be behind another view or offscreen. Views with their hidden property set to YES are ignored. @@ -133,6 +132,13 @@ typedef NS_ENUM(NSUInteger, KIFPullToRefreshTiming) { */ - (UIView *)waitForViewWithAccessibilityLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits; +/*! + @abstract Waits until a view or accessibility element is no longer present. + @discussion The view or accessibility element with the given value is found in the view hierarchy. If the element is found, then the step will attempt to wait until it isn't. Note that the view does not necessarily have to be visible on the screen, and may be behind another view or offscreen. Views with their hidden property set to YES are considered absent. + @param value The accessibility value of the element to wait for. + */ +- (void)waitForAbsenceOfViewWithValue:(NSString *)value; + /*! @abstract Waits until a view or accessibility element is no longer present. @discussion The view or accessibility element with the given label is found in the view hierarchy. If the element is found, then the step will attempt to wait until it isn't. Note that the view does not necessarily have to be visible on the screen, and may be behind another view or offscreen. Views with their hidden property set to YES are considered absent. diff --git a/Classes/KIFUITestActor.m b/Classes/KIFUITestActor.m index 2f87ec308..9a4e4d100 100644 --- a/Classes/KIFUITestActor.m +++ b/Classes/KIFUITestActor.m @@ -153,6 +153,11 @@ - (void)waitForAbsenceOfViewWithAccessibilityLabel:(NSString *)label traits:(UIA [self waitForAbsenceOfViewWithAccessibilityLabel:label value:nil traits:traits]; } +- (void)waitForAbsenceOfViewWithValue:(NSString *)value +{ + [self waitForAbsenceOfViewWithAccessibilityLabel:nil value:value traits:UIAccessibilityTraitNone]; +} + - (void)waitForAbsenceOfViewWithAccessibilityLabel:(NSString *)label value:(NSString *)value traits:(UIAccessibilityTraits)traits { [self runBlock:^KIFTestStepResult(NSError **error) { diff --git a/KIF Tests/AutocorrectTests.m b/KIF Tests/AutocorrectTests.m index 034f799a0..91fd4a106 100644 --- a/KIF Tests/AutocorrectTests.m +++ b/KIF Tests/AutocorrectTests.m @@ -7,6 +7,8 @@ #import +#import "KIFTextInputTraitsOverrides.h" + @interface AutocorrectTests : KIFTestCase @end @@ -14,18 +16,20 @@ @implementation AutocorrectTests + (void)setUp { - [KIFTestActor setEnableAutocorrect:YES]; - [KIFTestActor setEnableSmartQuotes:YES]; - [KIFTestActor setEnableSmartDashes:YES]; [super setUp]; + + KIFTextInputTraitsOverrides.allowDefaultAutocorrectBehavior = YES; + KIFTextInputTraitsOverrides.allowDefaultSmartDashesBehavior = YES; + KIFTextInputTraitsOverrides.allowDefaultSmartQuotesBehavior = YES; } + (void)tearDown { - [KIFTestActor setEnableAutocorrect:NO]; - [KIFTestActor setEnableSmartQuotes:NO]; - [KIFTestActor setEnableSmartDashes:NO]; [super tearDown]; + + KIFTextInputTraitsOverrides.allowDefaultAutocorrectBehavior = NO; + KIFTextInputTraitsOverrides.allowDefaultSmartDashesBehavior = NO; + KIFTextInputTraitsOverrides.allowDefaultSmartQuotesBehavior = NO; } - (void)beforeEach @@ -41,7 +45,7 @@ - (void)afterEach - (void)testClearingAndEnteringTypoIntoViewWithAccessibilityLabel { [[tester validateEnteredText:NO] clearTextFromAndThenEnterText:@" teh " intoViewWithAccessibilityLabel:@"Greeting"]; - [[viewTester usingValue:@" teh "] waitForAbsenceOfView]; + [tester waitForAbsenceOfViewWithValue:@" teh "]; } - (void)testClearingAndEnteringQuotesIntoViewWithAccessibilityLabel diff --git a/KIF Tests/AutocorrectTests_ViewTestActor.m b/KIF Tests/AutocorrectTests_ViewTestActor.m index 796e48930..91fa08843 100644 --- a/KIF Tests/AutocorrectTests_ViewTestActor.m +++ b/KIF Tests/AutocorrectTests_ViewTestActor.m @@ -7,6 +7,8 @@ #import +#import "KIFTextInputTraitsOverrides.h" + @interface AutocorrectTests_ViewTestActor : KIFTestCase @end @@ -15,18 +17,20 @@ @implementation AutocorrectTests_ViewTestActor + (void)setUp { - [KIFTestActor setEnableAutocorrect:YES]; - [KIFTestActor setEnableSmartQuotes:YES]; - [KIFTestActor setEnableSmartDashes:YES]; [super setUp]; + + KIFTextInputTraitsOverrides.allowDefaultAutocorrectBehavior = YES; + KIFTextInputTraitsOverrides.allowDefaultSmartDashesBehavior = YES; + KIFTextInputTraitsOverrides.allowDefaultSmartQuotesBehavior = YES; } + (void)tearDown { - [KIFTestActor setEnableAutocorrect:NO]; - [KIFTestActor setEnableSmartQuotes:NO]; - [KIFTestActor setEnableSmartDashes:NO]; [super tearDown]; + + KIFTextInputTraitsOverrides.allowDefaultAutocorrectBehavior = NO; + KIFTextInputTraitsOverrides.allowDefaultSmartDashesBehavior = NO; + KIFTextInputTraitsOverrides.allowDefaultSmartQuotesBehavior = NO; } - (void)beforeEach