From 5e6f8d49daead57b20f91ecf49ef78edf6f72d3d Mon Sep 17 00:00:00 2001 From: Szymon Kazmierczak <szymonkaz@gmail.com> Date: Wed, 21 Nov 2018 10:38:38 +0000 Subject: [PATCH] Fix for UITextView notifications not triggered when using replaceText --- AppFramework/Action/GREYActions.m | 23 ++++++++++ .../Sources/Swift/FTRSwiftTests.swift | 26 +++++++++++ Tests/TestRig/Sources/TypingViewController.h | 1 + Tests/TestRig/Sources/TypingViewController.m | 38 +++++++++------ .../TestRig/Sources/TypingViewController.xib | 46 +++++++++++-------- 5 files changed, 99 insertions(+), 35 deletions(-) diff --git a/AppFramework/Action/GREYActions.m b/AppFramework/Action/GREYActions.m index 3316d6a85..1b1963eaa 100644 --- a/AppFramework/Action/GREYActions.m +++ b/AppFramework/Action/GREYActions.m @@ -510,6 +510,8 @@ + (void)grey_setText:(NSString *)text onWebElement:(id)element { grey_execute_sync_on_main_thread(^{ BOOL elementIsUIControl = [element isKindOfClass:[UIControl class]]; BOOL elementIsUITextField = [element isKindOfClass:[UITextField class]]; + BOOL elementIsUITextView = [element isKindOfClass:[UITextView class]]; + // Did begin editing notifications. if (elementIsUIControl) { [element sendActionsForControlEvents:UIControlEventEditingDidBegin]; @@ -521,6 +523,12 @@ + (void)grey_setText:(NSString *)text onWebElement:(id)element { object:element]; [NSNotificationCenter.defaultCenter postNotification:notification]; } + + if (elementIsUITextView) { + if ([((UITextView *)element).delegate respondsToSelector:@selector(textViewDidBeginEditing:)]) { + [((UITextView *)element).delegate textViewDidBeginEditing:((UITextView *)element)]; + } + } // Actually change the text. [element setText:text]; @@ -529,24 +537,39 @@ + (void)grey_setText:(NSString *)text onWebElement:(id)element { if (elementIsUIControl) { [element sendActionsForControlEvents:UIControlEventEditingChanged]; } + if (elementIsUITextField) { NSNotification *notification = [NSNotification notificationWithName:UITextFieldTextDidChangeNotification object:element]; [NSNotificationCenter.defaultCenter postNotification:notification]; } + + if (elementIsUITextView) { + if ([((UITextView *)element).delegate respondsToSelector:@selector(textViewDidChange:)]) { + [((UITextView *)element).delegate textViewDidChange:((UITextView *)element)]; + } + } // Did end editing notifications. if (elementIsUIControl) { [element sendActionsForControlEvents:UIControlEventEditingDidEndOnExit]; [element sendActionsForControlEvents:UIControlEventEditingDidEnd]; } + if (elementIsUITextField) { NSNotification *notification = [NSNotification notificationWithName:UITextFieldTextDidEndEditingNotification object:element]; [NSNotificationCenter.defaultCenter postNotification:notification]; } + + if (elementIsUITextView) { + if ([((UITextView *)element).delegate respondsToSelector:@selector(textViewDidEndEditing:)]) { + [((UITextView *)element).delegate textViewDidEndEditing:((UITextView *)element)]; + } + } + }); } return YES; diff --git a/Tests/FunctionalTests/Sources/Swift/FTRSwiftTests.swift b/Tests/FunctionalTests/Sources/Swift/FTRSwiftTests.swift index 3ce537777..d68f97135 100644 --- a/Tests/FunctionalTests/Sources/Swift/FTRSwiftTests.swift +++ b/Tests/FunctionalTests/Sources/Swift/FTRSwiftTests.swift @@ -127,6 +127,32 @@ class FTRSwiftTests: XCTestCase { .assert(grey_text("FooBar")) } + func testTypingOnUITextView() { + openTestView(named: "Typing Views") + let typingField = grey_accessibilityID("TypingTextView") + let charCounter = grey_accessibilityID("charCounter") + + EarlGrey.selectElement(with: typingField) + .perform(grey_typeText("Simple")) + EarlGrey.selectElement(with: grey_text("Done")) + .perform(grey_tap()) + EarlGrey.selectElement(with: charCounter) + .assert(grey_text("6")) + } + + func testReplacingTextOnUITextView() { + openTestView(named: "Typing Views") + let typingField = grey_accessibilityID("TypingTextView") + let charCounter = grey_accessibilityID("charCounter") + + EarlGrey.selectElement(with: typingField) + .perform(grey_replaceText("Simple")) + EarlGrey.selectElement(with: grey_text("Done")) + .perform(grey_tap()) + EarlGrey.selectElement(with: charCounter) + .assert(grey_text("6")) + } + func testButtonPressWithGREYAllOf() { openTestView(named: "Basic Views") EarlGrey.selectElement(with: grey_text("Tab 2")).perform(grey_tap()) diff --git a/Tests/TestRig/Sources/TypingViewController.h b/Tests/TestRig/Sources/TypingViewController.h index c3304dd71..395648fd0 100644 --- a/Tests/TestRig/Sources/TypingViewController.h +++ b/Tests/TestRig/Sources/TypingViewController.h @@ -27,6 +27,7 @@ @property(nonatomic, retain) IBOutlet UITextField *inputAccessoryTextField; @property(nonatomic, retain) IBOutlet UIButton *inputButton; @property(nonatomic, retain) IBOutlet UITextField *textField; +@property(nonatomic, retain) IBOutlet UILabel *charCounter; @property(nonatomic, retain) IBOutlet UITextField *nonTypingTextField; @property(nonatomic, retain) IBOutlet CustomTextView *customTextView; @property(nonatomic, retain) UIBarButtonItem *dismissKeyboardButton; diff --git a/Tests/TestRig/Sources/TypingViewController.m b/Tests/TestRig/Sources/TypingViewController.m index 5fe67180a..7f1a6baed 100644 --- a/Tests/TestRig/Sources/TypingViewController.m +++ b/Tests/TestRig/Sources/TypingViewController.m @@ -54,9 +54,9 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { _keyboardTypeStringArray = @[ - @"Default", @"ASCIICapable", @"NumbersAndPunctuation", @"URL", @"NumberPad", @"PhonePad", - @"NamePhonePad", @"EmailAddress", @"DecimalPad", @"Twitter", @"WebSearch" - ]; + @"Default", @"ASCIICapable", @"NumbersAndPunctuation", @"URL", @"NumberPad", @"PhonePad", + @"NamePhonePad", @"EmailAddress", @"DecimalPad", @"Twitter", @"WebSearch" + ]; NSAssert([_keyboardTypeStringArray count] == kKeyboardTypeCount, @"count must be kKeyboardTypeCount"); _keyboardTypeArray[0] = UIKeyboardTypeDefault; @@ -76,47 +76,50 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil - (void)viewDidLoad { [super viewDidLoad]; - + self.dismissKeyboardButton = - [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:self - action:@selector(dismissKeyboard)]; - + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(dismissKeyboard)]; + self.textField.delegate = self; self.textField.isAccessibilityElement = YES; self.textField.userInteractionEnabled = YES; self.textField.accessibilityIdentifier = @"TypingTextField"; self.textField.autocorrectionType = UITextAutocorrectionTypeYes; - + + self.charCounter.isAccessibilityElement = YES; + self.charCounter.accessibilityIdentifier = @"charCounter"; + self.nonTypingTextField.delegate = self; self.nonTypingTextField.isAccessibilityElement = YES; self.nonTypingTextField.userInteractionEnabled = YES; self.nonTypingTextField.accessibilityIdentifier = @"NonTypingTextField"; - + self.textView.delegate = self; self.textView.isAccessibilityElement = YES; self.textView.userInteractionEnabled = YES; self.textView.accessibilityIdentifier = @"TypingTextView"; self.textView.autocorrectionType = UITextAutocorrectionTypeYes; - + self.inputAccessoryTextField.delegate = self; self.inputAccessoryTextField.isAccessibilityElement = YES; self.inputAccessoryTextField.userInteractionEnabled = YES; self.inputAccessoryTextField.accessibilityIdentifier = @"InputAccessoryTextField"; self.inputAccessoryTextField.autocorrectionType = UITextAutocorrectionTypeYes; [self AddInputAccessoryViewtoKeyboard]; - + self.inputButton.accessibilityIdentifier = @"Input Button"; [self.inputButton addTarget:self action:@selector(buttonPressedForTyping) forControlEvents:UIControlEventTouchUpInside]; - + self.keyboardPicker.accessibilityIdentifier = @"KeyboardPicker"; - + self.customTextView.isAccessibilityElement = YES; self.customTextView.userInteractionEnabled = YES; self.customTextView.accessibilityIdentifier = @"CustomTextView"; - + [self.view sendSubviewToBack:_customKeyboardTracker]; self.customKeyboardTracker.isAccessibilityElement = YES; self.customKeyboardTracker.accessibilityIdentifier = @"CustomKeyboardTracker"; @@ -151,6 +154,11 @@ - (void)textViewDidBeginEditing:(UITextView *)textView { self.navigationItem.rightBarButtonItem = self.dismissKeyboardButton; } +- (void)textViewDidEndEditing:(UITextView *)textView { + NSUInteger len = textView.text.length; + _charCounter.text = [NSString stringWithFormat: @"%lu", (unsigned long)len]; +} + - (void)dismissKeyboard { [self.textView resignFirstResponder]; self.navigationItem.rightBarButtonItem = nil; diff --git a/Tests/TestRig/Sources/TypingViewController.xib b/Tests/TestRig/Sources/TypingViewController.xib index 62f5f6069..47338a0bf 100644 --- a/Tests/TestRig/Sources/TypingViewController.xib +++ b/Tests/TestRig/Sources/TypingViewController.xib @@ -1,13 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="NO"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES"> + <device id="retina4_7" orientation="portrait"> + <adaptation id="fullscreen"/> + </device> <dependencies> <deployment identifier="iOS"/> - <development version="7000" identifier="xcode"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="TypingViewController"> <connections> + <outlet property="charCounter" destination="MP1-3R-IW1" id="DQ1-eR-dg5"/> <outlet property="customKeyboardTracker" destination="bnj-yZ-VR3" id="0ns-aw-ahE"/> <outlet property="customTextView" destination="kf2-uc-vdE" id="XsY-7I-QdM"/> <outlet property="inputAccessoryTextField" destination="Zla-Kl-dQS" id="XJs-DG-mGU"/> @@ -21,7 +25,7 @@ </placeholder> <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT"> - <rect key="frame" x="0.0" y="0.0" width="320" height="480"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Input Accessory View TextField" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Zla-Kl-dQS" userLabel="Input Accessory Text Field"> @@ -30,7 +34,7 @@ <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits"/> </textField> - <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Never First Responder" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="PBX-7b-uV2"> + <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Never First Responder" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="PBX-7b-uV2"> <rect key="frame" x="20" y="75" width="374" height="30"/> <accessibility key="accessibilityConfiguration" label=""/> <fontDescription key="fontDescription" type="system" pointSize="14"/> @@ -42,20 +46,20 @@ <constraint firstAttribute="width" constant="133" id="Sle-WE-dbc"/> </constraints> <state key="normal" title="next returnKeyType"> - <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="calibratedRGB"/> + <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="changeReturnKeyType:" destination="-1" eventType="touchUpInside" id="jOw-jE-AVj"/> </connections> </button> - <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Text Field" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="HbD-2h-bQc"> + <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Text Field" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="HbD-2h-bQc"> <rect key="frame" x="20" y="141" width="374" height="30"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits" autocorrectionType="yes" spellCheckingType="yes"/> </textField> - <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" keyboardDismissMode="interactive" translatesAutoresizingMaskIntoConstraints="NO" id="F8N-FE-LqS"> + <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" misplaced="YES" keyboardDismissMode="interactive" translatesAutoresizingMaskIntoConstraints="NO" id="F8N-FE-LqS"> <rect key="frame" x="20" y="179" width="374" height="53"/> - <color key="backgroundColor" red="0.91907269021739135" green="0.91907269021739135" blue="0.91907269021739135" alpha="1" colorSpace="calibratedRGB"/> + <color key="backgroundColor" red="0.91907269021739135" green="0.91907269021739135" blue="0.91907269021739135" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstAttribute="height" constant="53" id="dkB-da-5H4"/> </constraints> @@ -66,7 +70,7 @@ <rect key="frame" x="226" y="31" width="46" height="30"/> <state key="normal" title="Button"/> </button> - <pickerView contentMode="scaleToFill" verticalCompressionResistancePriority="749" translatesAutoresizingMaskIntoConstraints="NO" id="D9d-aK-L7i"> + <pickerView contentMode="scaleToFill" verticalCompressionResistancePriority="749" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="D9d-aK-L7i"> <rect key="frame" x="47" y="313" width="320" height="100"/> <constraints> <constraint firstAttribute="height" constant="100" id="EaZ-Z7-fey"/> @@ -76,16 +80,16 @@ <outlet property="delegate" destination="-1" id="iXT-ja-Und"/> </connections> </pickerView> - <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kf2-uc-vdE" customClass="CustomTextView"> + <view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kf2-uc-vdE" customClass="CustomTextView"> <rect key="frame" x="74" y="240" width="266" height="51"/> - <color key="backgroundColor" red="0.72336632013320923" green="0.72336632013320923" blue="0.72336632013320923" alpha="1" colorSpace="calibratedRGB"/> + <color key="backgroundColor" red="0.72336632013320923" green="0.72336632013320923" blue="0.72336632013320923" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <accessibility key="accessibilityConfiguration" identifier="CustomTextView"/> <constraints> <constraint firstAttribute="width" constant="266" id="Jks-lU-kXW"/> <constraint firstAttribute="height" constant="51" id="KQW-5b-HjZ"/> </constraints> </view> - <view contentMode="bottomLeft" translatesAutoresizingMaskIntoConstraints="NO" id="bnj-yZ-VR3" customClass="CustomKeyboardTracker"> + <view contentMode="bottomLeft" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bnj-yZ-VR3" customClass="CustomKeyboardTracker"> <rect key="frame" x="149" y="606" width="88" height="51"/> <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/> <accessibility key="accessibilityConfiguration" identifier="CustomKeyboardTracker"/> @@ -96,8 +100,15 @@ <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="10" id="vJa-7j-eqY"/> </constraints> </view> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="charCounter" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MP1-3R-IW1" userLabel="CharCounter"> + <rect key="frame" x="16" y="112" width="96" height="21"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> </subviews> - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="ugr-WT-H7I" firstAttribute="top" secondItem="PBX-7b-uV2" secondAttribute="bottom" constant="-2" id="235-Sq-djF"/> <constraint firstItem="D9d-aK-L7i" firstAttribute="top" secondItem="kf2-uc-vdE" secondAttribute="bottom" constant="22" id="89S-kl-2ip"/> @@ -121,12 +132,7 @@ <constraint firstItem="HbD-2h-bQc" firstAttribute="trailing" secondItem="PBX-7b-uV2" secondAttribute="trailing" id="zCU-gO-eFg"/> <constraint firstAttribute="bottom" secondItem="bnj-yZ-VR3" secondAttribute="bottom" constant="10" id="zv1-fF-81e"/> </constraints> - <point key="canvasLocation" x="-17.5" y="29.5"/> + <point key="canvasLocation" x="-28" y="26.53673163418291"/> </view> </objects> - <simulatedMetricsContainer key="defaultSimulatedMetrics"> - <simulatedStatusBarMetrics key="statusBar"/> - <simulatedOrientationMetrics key="orientation"/> - <simulatedScreenMetrics key="destination"/> - </simulatedMetricsContainer> </document>