ViewAction closeSoftKeyboard() does ensure that soft keyboard is completely gone
Opened this issue · 16 comments
What steps will reproduce the problem?
1. Soft keyboard enabled
2. EditText with focus to bring up the soft keyboard
3. Button that would normally get blocked by the soft keyboard
4. In an Espresso test, click on the button immediately after performing the
closeSoftKeyboard() ViewAction.
What is the expected output?
The soft keyboard gets dismissed and the click on the button is successful.
What do you see instead?
On certain devices (physical Nexus 4 with API19 and Nexus 5 emulator with
API19), the click is invoked while the soft keyboard is animating away despite
disabling animations in the Developer Settings. If the click is done on the
soft keyboard, a SecurityException will be thrown.
What version of the product are you using? On what operating system?
Espresso v1.1
Physical Nexus 4 Android 4.4.2 (API19)
Emulator Nexus 5 Android 4.4.2 (API19)
Please provide any additional information below.
The issue appears to be mitigated if I add a sleep of 500 milliseconds.
Please see:
https://groups.google.com/forum/#!searchin/android-test-kit-discuss/keyboard/and
roid-test-kit-discuss/IX-D3BRWQsE/-XAQmW9HrRMJ
Here is a sample call stack from one of our tests that ran into this issue:
com.google.android.apps.common.testing.ui.espresso.PerformException: Error
performing 'single click' on view 'with id: is <2131296505>'.
at com.google.android.apps.common.testing.ui.espresso.PerformException$Builder.build(PerformException.java:67)
at com.google.android.apps.common.testing.ui.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:57)
at com.google.android.apps.common.testing.ui.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:40)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:159)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.doPerform(ViewInteraction.java:90)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.perform(ViewInteraction.java:73)
at com.twitter.android.coverage.TextFirstComposerActivityTest.postActivityWithASimpleImageTweetHelper(TextFirstComposerActivityTest.java:219)
at com.twitter.android.coverage.TextFirstComposerActivityTest.testPostActivityWithASimpleImageTweetInLandscape(TextFirstComposerActivityTest.java:96)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onStart(GoogleInstrumentationTestRunner.java:167)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)
Caused by: com.google.android.apps.common.testing.ui.espresso.PerformException:
Error performing 'Send down montion event' on view 'unknown'.
at com.google.android.apps.common.testing.ui.espresso.PerformException$Builder.build(PerformException.java:67)
at com.google.android.apps.common.testing.ui.espresso.action.MotionEvents.sendDown(MotionEvents.java:90)
at com.google.android.apps.common.testing.ui.espresso.action.Tap$1.sendTap(Tap.java:24)
at com.google.android.apps.common.testing.ui.espresso.action.GeneralClickAction.perform(GeneralClickAction.java:82)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction$1.run(ViewInteraction.java:119)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by:
com.google.android.apps.common.testing.ui.espresso.InjectEventSecurityException:
java.lang.SecurityException: Injecting to another application requires
INJECT_EVENTS permission
at com.google.android.apps.common.testing.ui.espresso.base.InputManagerEventInjectionStrategy.injectMotionEvent(InputManagerEventInjectionStrategy.java:131)
at com.google.android.apps.common.testing.ui.espresso.base.EventInjector.injectMotionEvent(EventInjector.java:80)
at com.google.android.apps.common.testing.ui.espresso.base.UiControllerImpl$3.call(UiControllerImpl.java:201)
at com.google.android.apps.common.testing.ui.espresso.base.UiControllerImpl$3.call(UiControllerImpl.java:198)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: java.lang.SecurityException: Injecting to another application
requires INJECT_EVENTS permission
at android.os.Parcel.readException(Parcel.java:1465)
at android.os.Parcel.readException(Parcel.java:1419)
at android.hardware.input.IInputManager$Stub$Proxy.injectInputEvent(IInputManager.java:356)
at android.hardware.input.InputManager.injectInputEvent(InputManager.java:641)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.google.android.apps.common.testing.ui.espresso.base.InputManagerEventInjectionStrategy.injectMotionEvent(InputManagerEventInjectionStrategy.java:122)
... 9 more
Original issue reported on code.google.com by mhernan...@gmail.com
on 3 Jun 2014 at 7:15
Is it a consistent repro? (we rarely test on physical devices, but I can try
this out if it's easy to reproduce).
Original comment by vale...@google.com
on 9 Jun 2014 at 9:59
As mentioned above, I am also able to reproduce this on an emulator. It is not
100% consistent, however it is consistent enough that I had to add a 500
millisecond sleep after every call to closeSoftKeyboard() in order to make my
tests reliable.
If you follow the thread in
https://groups.google.com/forum/#!searchin/android-test-kit-discuss/keyboard/and
roid-test-kit-discuss/IX-D3BRWQsE/-XAQmW9HrRMJ, R Palan mentions that he
specifically had to configure the emulator to "hardware keyboard present" as a
workaround, meaning that he was also able to reproduce this on an emulator.
Original comment by mhernan...@gmail.com
on 10 Jun 2014 at 4:22
I find that on older devices, like the Samsung SIII Mini, this happens quite
regularly. I'd say a given test has a 50% chance of failing.
Original comment by stern....@gmail.com
on 21 Jul 2014 at 10:11
I found the best work around is to use @FlakyTest(tolerance = 5), which will
tell the instrumentation test runner to try a x times before marking the test
as failed.
Original comment by stern....@gmail.com
on 21 Jul 2014 at 10:36
[deleted comment]
Same problem here. Need to wait for the keyboard to close. Just because the RPC
call returned fast the UI is still blocked by the keyboard.
Sleeping seems the ugliest but the only solution that works.
Original comment by dnkoutso@gmail.com
on 24 Jul 2014 at 6:46
In the meantime, I wound up implementing my own wrapper closeSoftKeyboard()
ViewAction like so:
public static ViewAction closeSoftKeyboard() {
return new ViewAction() {
/**
* The delay time to allow the soft keyboard to dismiss.
*/
private static final long KEYBOARD_DISMISSAL_DELAY_MILLIS = 1000L;
/**
* The real {@link CloseKeyboardAction} instance.
*/
private final ViewAction mCloseSoftKeyboard = new CloseKeyboardAction();
@Override
public Matcher<View> getConstraints() {
return mCloseSoftKeyboard.getConstraints();
}
@Override
public String getDescription() {
return mCloseSoftKeyboard.getDescription();
}
@Override
public void perform(final UiController uiController, final View view) {
mCloseSoftKeyboard.perform(uiController, view);
uiController.loopMainThreadForAtLeast(KEYBOARD_DISMISSAL_DELAY_MILLIS);
}
};
}
Original comment by mhernan...@gmail.com
on 24 Jul 2014 at 8:11
I worked around this problem by implementing my own keyboard that is only 32dp
tall that I use on testing devices.
https://github.com/johnybot/TestingKeyboard
Original comment by johnatha...@hootsuite.com
on 28 Jul 2014 at 8:59
Is this something that happens even when system animations are turned off?
Original comment by vale...@google.com
on 19 Nov 2014 at 9:39
Yes. I was running into this with all three system animations off.
Original comment by mhernan...@gmail.com
on 21 Nov 2014 at 7:22
I also was running into this with animations turned off.
Original comment by stern....@gmail.com
on 21 Nov 2014 at 3:09
I didn't use Espresso 1.1. I tried Espresso 2.0 and I'm running into this with
all three system animations off (I think keyboard dismiss animation is not
affected by these options).
The bug can be reproduced using your own tests (lanscape mode), Google Keyboard
and:
Nexus7 (2012), Android 5.0.2
Nexus5 - Android 5.0.1
I opened an issue there:
https://github.com/googlesamples/android-testing/issues/5
It's not an invalid issue, otherwise Espresso 2.0 does not support real devices.
https://code.google.com/p/android-test-kit/issues/detail?id=44
I understand that the idea is to use emulators, CI servers and cloud but I
thought your test kit supports real devices to confirm results.
KEYBOARD_DISMISSAL_DELAY works to slve the issue and demostrate it.
Original comment by ard...@gmail.com
on 28 Dec 2014 at 6:50
Attachments:
- log_nexus5.txt
- [Test results - Class com.example.android.testing.espresso.BasicSample_nexus5.pdf](https://storage.googleapis.com/google-code-attachments/android-test-kit/issue-79/comment-12/Test results - Class com.example.android.testing.espresso.BasicSample_nexus5.pdf)
- log_nexus7.txt
- [Test results - Class com.example.android.testing.espresso.BasicSample.pdf](https://storage.googleapis.com/google-code-attachments/android-test-kit/issue-79/comment-12/Test results - Class com.example.android.testing.espresso.BasicSample.pdf)
I'd forgotten about this issue. I haven't upgraded to 2.0 yet, but for 1.1, I
put together a custom ViewAction to close the softkeyboard that synchronized on
a somewhat shady detection of the keyboard being removed. I haven't had time to
clean it up or test it in 2.0, but if it'll help someone in the meantime or if
someone can add some proper testing for it, I've attached my source class.
There were still occasional failures that I never had a chance to track down,
but it occurred so infrequently that it didn't affect my testing overall. It
may not be production ready per se.
Original comment by p.pr...@blueesoteric.com
on 28 Dec 2014 at 7:32
Attachments:
I have the same issue here. Also on a Panasonic FZ-A1. The BCloseKeyboardAction
did not help.
But the workaround from
https://code.google.com/p/android-test-kit/issues/detail?id=79#c7 is working.
Original comment by stefanto...@gmail.com
on 17 Mar 2015 at 12:53
Same issue while trying to fill in email and password fields of login form.
Email text get entered fine, but when asking Espresso to type into password it
will fail with above error.
Original comment by peter.b...@gmail.com
on 26 Mar 2015 at 11:09
Original comment by nkors...@google.com
on 5 May 2015 at 6:03
- Changed state: Accepted