Enter "Enter key" in Appium Testing - android

How to send/press Enter key from soft keyboard in Appium in Android Automation testing?
I tried several options, but none of them are working - instead of pressing the key, they are clearing the text entered in text area. Below is the code (in JAVA Language):
String app_package_name = "abc.xyz.android";
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("deviceName", "Nexus_5X_API_23");
capabilities.setCapability("platformVersion", "6.0");
capabilities.setCapability("appPackage", app_package_name);
capabilities.setCapability("appActivity", app_package_name + ".activity.StartupActivity_");
String url = "http://127.0.0.1:4723/wd/hub";
AndroidDriver driver = new AndroidDriver(new URL(url), capabilities);
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
By password = By.id(app_package_name_with_id + "et_password");
WebElement enterPassword = driver.findElement(password);
enterPassword.click();
driver.getKeyboard().sendKeys("12345");
driver.getKeyboard().sendKeys(Keys.ENTER); // THIS IS NOT WORKING.
driver.getKeyboard().sendKeys(Keys.RETURN); // THIS IS ALSO NOT WORKING.
driver.pressKeyCode(AndroidKeyCode.ENTER); // THIS IS ALSO NOT WORKING.
driver.pressKeyCode(AndroidKeyCode.KEYCODE_NUMPAD_ENTER); // SAME HERE.
enterPassword.sendKeys(Keys.ENTER); // SAME HERE.
Please if anyone can help me achieve it?

Before using
((AndroidDriver)driver).pressKeyCode(AndroidKeyCode.ENTER);
Set the following desired capabilities
capabilities.setCapability("unicodeKeyboard", "true");
capabilities.setCapability("resetKeyboard", "true");

you can try this, it will work with all devices
driver.executeScript("mobile:performEditorAction", ImmutableMap.of("action", "done"));

Send using keyevent
Either use:
driver.press_keycode(66)
or
use
adb shell input keyevent 66

Try following code. It is working for me:
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import io.appium.java_client.android.nativekey.AndroidKey;
import io.appium.java_client.android.nativekey.KeyEvent;
((AndroidDriver<MobileElement>) driver).pressKey(new KeyEvent(AndroidKey.ENTER));
Before using enter key, you must first click on text input field.

API Docs: https://appium.github.io/java-client/constant-values.html#io.appium.java_client.android.AndroidKeyCode.ENTER
Enter code is 66
Python
self.driver.press_keycode(66)
Java
((AndroidDriver<MobileElement>) driver).pressKey(new KeyEvent(AndroidKey.ENTER));
I tested on Android 9 with Youtube search.

I was facing the same problem while automating amazon ((AndroidDriver)driver).pressKeyCode(AndroidKeyCode.ENTER); alone didn't work for me. But It worked when i clicked in the search box first.
searchBox.click();
searchBox.sendKeys("Example Input");
((AndroidDriver) driver).pressKey(new KeyEvent(AndroidKey.ENTER));

Try this ..
element.sendKeys("some text");
driver.pressKey(new KeyEvent(AndroidKey.ENTER));

You can use Robot class :-
Robot robot;
try {
robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
It is not recommended if your test cases are going to execute in the background. Robot framework just going to enter irrespectively without asserting anything.
Or you can try below code :-
driver.pressKeyCode(AndroidKeyCode.KEYCODE_NUMPAD_ENTER );
Source :- (It have other ways also to press enter) :-
https://discuss.appium.io/t/how-to-click-enter-after-entering-some-text/3136/4
Hope it will help you :)

This is what worked for me:
try {
driver.hideKeyboard();
} catch (Exception e) {
e.printStackTrace();
}

The answer from #akash and #LuckyLikey led me to this solution in JavaScript:
return driver.waitForElementById(<elementId>).type(<text to type>).click().execute( "mobile: performEditorAction", { "action": "search" } );
This allowed me to find a text field, input some text, and submit a search command (same as clicking the search icon in the keyboard). Of course, you have to replace <elementId> and <text to type> with the proper values. See http://appium.io/docs/en/commands/mobile-command/ for details on "mobile: performEditorAction".

So you can send below specified letter:
sendKeys('\n') for press Enter
Reference more sendKeys API in other programing languages

you can use action class, it worked for me
Actions action = new Actions(driver);
action.sendKeys(Keys.ENTER).perform();

So you can like this which has worked for me in some situations in the past and its real simple
for press Enter
sendKeys('\n')

I found a better solution instead of pressing ENTER button.
I wrote the following command:
driver.hideKeyboard();

Related

Java Android Appium - how to take screenshot when telephone is connected via USB cable?

Java Android Appium - how to take screenshot when telephone is connected via USB cable ?
The following line returns "Illegal base64 character a" - is there any different solution to take a screenshot ?
File source = driver.getScreenshotAs(OutputType.FILE);
I want to invoke screenshot when test fails in Test ng listeners Class:
#Override public void onTestFailure(ITestResult result) {}
That's because there is an annoying thing Appium does when using it's driver to take a screenshot, but I'm not sure if this applies in your situation.
Can you output the Base64 in the console to check it's specific output? If the output is something like this:
"Z3Rlc2dyZXNncmdyZWFncmVzZ3Jlc2dyZWFncmVzZ3Jlc2dlaW93YWpm\n"
"ZW9ndGVzZ3Jlc2dyZ3JlYWdyZXNncmVzZ3JlYWdyZXNncmVzZ2Vpb3dh\n"
"amZlb2d0ZXNncmVzZ3JncmVhZ3Jlc2dyZXNncmVhZ3Jlc2dyZXNnZWlv\n"
"d2FqZmVvZ3Rlc2dyZXNncmdyZWFncmVzZ3Jlc2dyZWFncmVzZ3Jlc2dl\n"
"aW93YWpmZW9ndGVzZ3Jlc2dyZ3JlYWdyZXNncmVzZ3JlYWdyZXNncmVz\n"
"Z2Vpb3dhamZlb2d0ZXNncmVzZ3JncmVhZ3Jlc2dyZXNncmVhZ3Jlc2dy\n"
Then you should replace the "\n" to a blank "":
String screenshotBase64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);
String replaceBase64 = screenshotBase64.replaceAll("\n","");
doSomethingWith(replaceBase64);

How to wait and grab the text of android.widget.TextView in an appium test when there is no resource_id?

The appium test is to perform certain combination of few input fields, and one field is password field.
If the username is already taken, a corresponding message will be shown below the password button saying "username already taken".
But if username is valid, but password is wrong, the message will be shown below as "username and password combo didn't work".
The error message in above cases is shown in a android.widget.TextView**
Two questions:
I recorded the test using Appium Studio. When I run the test, I want to wait for couple of second and grab the text of error message. How to do the wait part and grab the text? (More details below). THe challenge is there is no resource id for the textView, but xpath and other details are available.
Note: Since the error message is shown right below the pwd field, it has no resouceid, only xpath available.
This is the structure
<android.widget.LinearLayout resource-id="com.a.b/textinputlayout_lgin_username">
<android.widget.FrameLayout>
<android.widget.EditText resource-id="com.a.b/lgin_username_edit">
<!--above 3 lines are for username field, just added for more clarity -->
<android.widget.LinearLayout resource-id="com.a.b:id/textinputlayout_lgin_pwd">
<android.widget.FrameLayout>
<android.widget.EditText>
<android.widget.ImageButton resource-id="com.a.b/text_input_end_icon">
<android.widget.TextView> <!-- ** this is the text I'm trying to grab -->
<android.widget.TextView resource-id="com.a.b/tv_forgotpwd">
<android.widget.Button resource-id="com.a.b/btn_login">
Please help. Thanks.
I assume, you have no ability to update the app in order to add resource id for the element.
The best, you can do in this case, is to use xpath.
Find the first parent by resorce-id attribute, and then go down and search by tag. I see 2 text tag elements here in LinearLayout, so you might try to get the first text tag by index, or search for text tag without resouce id attribute.
"(//android.widget.LinearLayout[#resouce-id='com.a.b:id/textinputlayout_lgin_pwd']//android.widget.TextView)[1]"
or
"//android.widget.LinearLayout[#resouce-id='com.a.b:id/textinputlayout_lgin_pwd']//android.widget.TextView[not(#resouce-id)]"
Based on appium client you're using, just utilize webdriver wait + expected conditions and use xpath location strategy for the element.
PS: Here is the code
public class Test_9 {
private String reportDirectory = "reports";
private String reportFormat = "xml";
private String testName = "Untitled";
protected AndroidDriver<AndroidElement> driver = null;
DesiredCapabilities dc = new DesiredCapabilities();
#BeforeEach
public void setUp() throws MalformedURLException {
dc.setCapability("reportDirectory", reportDirectory);
dc.setCapability("reportFormat", reportFormat);
dc.setCapability("testName", testName);
dc.setCapability(MobileCapabilityType.UDID, "123456");
dc.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, "com.a.b");
dc.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, ".view.base.SplashActivity");
driver = new AndroidDriver<>(new URL("http://localhost:4723/wd/hub"), dc);
driver.setLogLevel(Level.INFO);
}
#Test
public void testUntitled() {
driver.findElement(By.xpath("(//*[#contentDescription='Google Map']/*[#class='android.view.View'])[26]")).click();
driver.findElement(By.xpath("//*[#text='log in']")).click();
driver.findElement(By.xpath("//*[#id='lgin_edit']")).sendKeys("1234567789");
driver.findElement(By.xpath("//*[#class='android.widget.EditText' and (./preceding-sibling::* | ./following-sibling::*)[#id='text_input_end_icon']]")).sendKeys("qwer");
new WebDriverWait(driver, 120).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//*[#class='android.widget.EditText' and (./preceding-sibling::* | ./following-sibling::*)[#id='text_input_end_icon']]")));
driver.hideKeyboard();
driver.findElement(By.xpath("//*[#class='android.widget.EditText' and (./preceding-sibling::* | ./following-sibling::*)[#id='text_input_end_icon']]")).click();
driver.findElement(By.xpath("//*[#text='Log In']")).click();
driver.findElement(By.xpath("//*[#text='Log In']")).click();
}
#AfterEach
public void tearDown() {
//driver.quit();
}
}
Ok, this is what resolved my issue.
After posting the questino I realized, the button wasn't enabled, that's because the previous input text field is not clicked or something.
All this time I was recording via Appium, but I was manually clicking the keyboard and buttons on mobile phone, not the mobile simulator of appium.
After 2.5 days, I used mouse pointer of my computer to click all the fields and all simulation on the simulator of appium and recorded and re-ran the tests and it worked.
I did try printing out the button state and it was always btn.isEnabled() was returning false.

Unable to click button on Mobile App in android

I am new of mobile app automation tested using Appium with TestNG.Am practicing to automate amazon app, App was launching successfully but when I try to click login option, it's getting:
"FAILED: login org.openqa.selenium.NoSuchElementException: An
element could not be located on the page using the given search
parameters. (WARNING: The server did not provide any stacktrace
information) Command duration or timeout: 0 milliseconds"
public void login() throws InterruptedException{
System.out.println("Login check");
Thread.sleep(3000);
// String sample = driver.findElementByXPath("//*[#class='android.widget.Button' and #index='5']").getText();
System.out.println("Next sleep");
// driver.findElement(By.xpath("//[#class='android.widget.Button' and #index='5']')]")).click();
// driver.findElement(By.id("in.amazon.mShop.android.shopping:id/sign_in_button")).click();
driver.findElement(By.xpath("//android.widget.Button[#index='5']")).click();
Thread.sleep(3000);
System.out.println("Pass");
}
Image:
"//android.widget.Button[#index='5']" is invalid xpath locator. If you will ever what to use index (but I strongly suggest not to do it), do it this way:
"(//android.widget.Button)[5]"
But in your case the best is to search by resource-id:
driver.findElement(By.id("sign_in_button")).click();
And if it still doesn't work you can print app screen xml structure just before you search for element:
System.out.println(driver.getPageSource())
Analyse the xml you get if it contains your button and what are the attributes of it.
Please try this code:
MobileElement el1 = (MobileElement) driver.findElementById("in.amazon.mShop.android.shopping:id/sign_in_button");
el1.click();

sendkeys not working properly in Appium RemotewebDriver

I am using Appium 1.4.16 to automate apk file stored in my system in real android device. I am using java-client 3.4.1
Here is the code:
public static void main(String[] args) {
File app = new File("C:\\Users\\dell\\Downloads\\App.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("device", " Android");
//mandatory capabilities
capabilities.setCapability("deviceName","Android");
capabilities.setCapability("platformName","Android");
capabilities.setCapability("udid", "849e82c6");
capabilities.setCapability("app",app.getAbsolutePath());
capabilities.setCapability("appPackage", "xxxxxxxxxxx");
capabilities.setCapability("appActivity", "xxxxxxxxxx.MainActivity");
try{
RemoteWebDriver driver = new RemoteWebDriver(new URL("http://127.0.0.1:4723/wd/hub"),capabilities);
System.out.println("Device Started");
driver.manage().timeouts().implicitlyWait(25, TimeUnit.SECONDS);
RemoteWebElement number = (RemoteWebElement)driver.findElement(By.xpath("//android.widget.EditText[#resource-id='xxxx' and #content-desc = 'Mobile Number']"));
number.sendKeys("90002");
RemoteWebElement passwordKey = (RemoteWebElement)driver.findElement(By.xpath("//android.widget.EditText[#resource-id='yyyyy']"));
passwordKey.sendKeys("ezr123");
RemoteWebElement loginButton = (RemoteWebElement)driver.findElement(By.xpath("//android.view.View[#resource-id='ezm_submit_login_form']"));
loginButton.click();
}catch(Exception e){
e.printStackTrace();
}
}
}
I am not getting any error in Appium server but facing strange actions in UI.
While entering value in username field, it automatically clicks on Login Button then again enters value in password field. Here, it always starts with entering '2' in the field and ends with 8-digit password.But my supplied password is 6-digit long.Then nothing happens.
I have also tried giving Thread.sleep() between each action.But no change is observed.
Best solution is to tap on the element first using the xpath or Id, then type on the element , this is fail proof and will work
U can also give timeout after tap and also hide keyboard by pressing key value for back (4)
Or hide keyboard command

Appium: "An element could not be located on the page using the given search parameters" error

I am new to Appium and have been trying to automate the Conversion Calculator app for Android. Am getting the error "org.openqa.selenium.NoSuchElementException: An element could not be located on the page using the given search parameters", when trying to find a EditText element. Using Appium ver 1.0.0 and Android 4.3
The following is my code:
List<WebElement> textViews = driver.findElements(By.className("android.widget.TextView"));
for (i=0; i<textViews.size(); i++) {
if(textViews.get(i).getText().toLowerCase().contains("memory")) {
textViews.get(i).click();
}
}
Thread.sleep(5000);
WebElement editText = driver.findElement(By.className("android.widget.EditText"));
editText.sendKeys("123");
Even findElement by ID is not working. Please let me know what I am doing wrong here or if I need to provide more details.
I would use
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); instead of Thread.sleep(5000).
Try to use a newer version of Appium, I's been improved a lot. You can download the latest version of Appium and Appium clients here:http://appium.io/downloads.html
But be careful because in the newer version the findElement throws an Exception if there are more then one result of the search.
I would write this in a comment but I've not enough reputation :/
Possible Cause:
Multiple EditText in the current screen.
Please try with the following:
Solution1:
List<WebElement> editText = driver.findElements(By.className("android.widget.EditText"));
editText.get(0).sendKeys("123");
0 - Index of EditText
Solution2:
Use any other locating strategy like Xpath.
Maybe you could try waiting until the element is visible or enabled using a WebDriverWait object?
Avoid using sleep as much as possible, try using the WAIT command.
Sleep without waiting for the time that has been determined, even if the element is already on the screen.
In the case of the wait command, as soon as the element appears, the action will already be performed, this along the code will reduce the execution time considerably.
The issue for me was the app path I was using. If you are using a config file make sure to declare the application separately from the device.
If not, make sure the "app" capability has the right path. Here is the code in my config file for example:
devices_by_ids = {
"platformName": "Android",
"appium:DEVICE ADB ID": {
"android_version": "13",
"device_name": "google_Pixel_5a",
"DEVICE ADB ID": "DEVICE ADB ID",
"port":"4723",
"autoGrantPermissions": "true",
},
"appium:app": "YOUR APP PATH",
"appium:appWaitActivity": "*"
}
In Appium v2 use
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));

Categories

Resources