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
Related
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.
I have tried a lot of different stuff from the google and you-tube and this is where i land and i cannot get it to work, my connection to the Appium and emulator is fine also i have checked the adb devices everything is fine.
I am getting error for the Line driver = new AndroidDriver<IWebElement>(new Uri("http://127.0.0.1:4723/wd/hub"), cap, TimeSpan.FromSeconds(180));
These are the two errors which i get:
"cannot convert from 'System.Uri' to 'OpenQA.Selenium.Appium.Service.AppiumServiceBuilder'"
and
"cannot convert from 'OpenQA.Selenium.Remote.DesiredCapabilities' to 'OpenQA.Selenium.DriverOptions".
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Appium.Enums;
using OpenQA.Selenium.Appium.Android;
namespace UnitTestProject4
{
[TestClass]
public class UnitTest1
{
AppiumDriver<IWebElement> driver;
[TestMethod]
public void TestMethod1()
{
DesiredCapabilities cap = new DesiredCapabilities();
cap.SetCapability("deviceName", "Pixel 3a Pie 9.0 - API 28");
cap.SetCapability("platformVersion", "9.0");
cap.SetCapability("udid", "emulator-5554");
cap.SetCapability("appPackage", "org.mozilla.firefox");
cap.SetCapability("appActivity", "org.mozilla.gecko.BrowserApp");
cap.SetCapability("platformName", "Android");
driver = new AndroidDriver<IWebElement>(new Uri("http://127.0.0.1:4723/wd/hub"), cap, TimeSpan.FromSeconds(180));
driver.Navigate().GoToUrl("https://www.google.com");
}
}
}
You are very close, but I would make a few small tweaks. Your error messages are complaining about two things -- the use of DesiredCapabilities instead of AppiumOptions, and the use of new Uri("http://127.0.0.1:4723/wd/hub") as a parameter for AndroidDriver<IWebElement>.
To solve these issues -- instead of DesiredCapabilities, I initialize my AndroidDriver with AppiumOptions. Additionally, you should try starting Appium through AppiumServiceBuilder() and use that service to start your driver session. You should also specify a parameter for automationName.
Here's what I always use to start a new mobile session on Android with C#:
// start appium service
var builder = new AppiumServiceBuilder();
var appiumLocalService = builder.UsingAnyFreePort().Build();
appiumLocalService.Start();
// create appium driver capabilities
var options = new AppiumOptions { PlatformName = "Android" };
options.AddAdditionalCapability("deviceName", "Pixel 3a Pie 9.0 - API 28");
// add app or appPackage / appActivity depending on preference
options.AddAdditionalCapability("appPackage", "org.mozilla.firefox");
options.AddAdditionalCapability("appActivity", "org.mozilla.gecko.BrowserApp");
options.AddAdditionalCapability("udid", "emulator-5554");
options.AddAdditionalCapability("automationName", "UiAutomator2"); // this one is important
// these are optional, but I find them to be helpful -- see DesiredCapabilities Appium docs to learn more
options.AddAdditionalCapability("autoGrantPermissions", true);
options.AddAdditionalCapability("allowSessionOverride", true);
// start the driver
var driver = new AndroidDriver<IWebElement>(appiumLocalService.ServiceUrl, options);
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();
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();
I'm working on Hybrid Application Automation.
I have asked a developer to provide webview enabled .apk file for automation.
I got the .apk and I installed in on my real device (Samsung Galaxy) and checked in chrome://inspect to view the app in inspector mode. - It is displayed
In my code I have tried System.out.println("ContextName:- " + contextNames); to check that Native and Webview context displaying. It successfully displayed both Webview and Native.
I have the following issue:
I'm able to find element till my Login page (using Native and Webview context).
After Login page I have a main screen in mobile app that contains list of tables and text, links, thus I'm unable to find any element in this page.
I tried copying the xpath using => inspector - copyxpath feature. I searched with that xpath in Chrome inspector and it's highlighted (showing) the elements. I'm using the same xpath in my code to check the size of that xpath details. But it's showing size = 0 for all my elements.
I also tried:
I swicthed to Webview context once after the login page;
I switched to Webview mode before login screen itself.
Still, I'm unable to find any element on my page.
Is it possible to capture all available elements in the page to check if at least I'm on right track? I'm not sure where is the mistake I made. Can any one suggest me some solution?
!!! Note: I have the following limitation: I can only use a real (physical) device, not an emulator.
Code:
File f = new File("D:\\APK\\");
File fs = new File(f,"android-4.0-8071-Pulse_Deb_Mode.apk");
AndroidDriver driver;
DesiredCapabilities cap =new DesiredCapabilities();
//cap.setCapability(MobileCapabilityType.DEVICE_NAME,"Auto1");
cap.setCapability(MobileCapabilityType.DEVICE_NAME,"89959777"); //5bce9757
cap.setCapability(MobileCapabilityType.APP, fs.getAbsolutePath());
//cap.setCapability("appPackage", "au.com.ventia.apps.WMS");
//cap.setCapability("appActivity", "au.com.ventia.apps.WMS.MainActivity");
//cap.setCapability("platformName", "MobilePlatform.ANDROID");
//cap.setCapability("automationName", "Appium");
//cap.setCapability("autoWebview", true);
//cap.setCapability(MobileCapabilityType.BROWSER_NAME, "BROWSER");
//cap.setCapability(MobileCapabilityType.VERSION, "4.4.2");
//cap.setCapability(MobileCapabilityType.PLATFORM_VERSION, "21");
driver = new AndroidDriver (new URL("http://127.0.0.1:4723/wd/hub"),cap);
driver.manage().timeouts().implicitlyWait(20,TimeUnit.SECONDS);
System.out.println(((AndroidDriver) driver).getOrientation());
System.out.println("Device Connected");
try{
Set<String> contextNames = driver.getContextHandles();
for (String contextName : contextNames) {
System.out.println("ContextName:- "+contextNames); //prints out something like NATIVE_APP \n WEBVIEW_1
// System.out.println("Working as:- "+ driver.getTitle());
}
Thread.sleep(40000);
driver.context((String) contextNames.toArray()[1]); // set context to WEBVIEW_1
List<WebElement> user_name = driver.findElementsById("userNameInput");
List<WebElement> pass_name = driver.findElementsById("passwordInput");
System.out.println("Checking"+user_name.size() + pass_name.size());
user_name.get(0).clear();
pass_name.get(0).clear();
user_name.get(0).sendKeys("<<>><<>>");
pass_name.get(0).sendKeys("<<>><<><");
driver.pressKeyCode(66);
Thread.sleep(30000);
//driver.context((String) contextNames.toArray()[0]); // set context to WEBVIEW_1
List<WebElement> li = driver.findElementsByXPath("//*[#id='app']/ion-pane/ion-side-menus/ion-side-menu-content/ion-header-bar/div[3]");
System.out.println("Check1-"+li.size());
List<WebElement> li2 = driver.findElementsByXPath(".//*[#id='app']/ion-pane/ion-side-menus/ion-side-menu-content/ion-header-bar/div[3]");
System.out.println("Refresh-"+li2.size());
List<WebElement> li3 = driver.findElementsByXPath("//*[#id=\"app\"]/ion-pane/ion-side-menus/ion-side-menu-content/ion-header-bar/div[3]");
System.out.println("Satus"+li3.size());
List<WebElement> li4 = driver.findElementsByXPath("//*[#id=\"au.com.ventia.apps.WMS\"]/ion-pane/ion-side-menus/ion-side-menu-content/ion-header-bar/div[3]");
System.out.println("Task"+li4.size());
}catch (Exception e){
System.out.println("Error Code---> "+e);
}
OUTPUT:
PORTRAIT
Device Connected
ContextName:- [NATIVE_APP, WEBVIEW_au.com.ventia.apps.WMS]
ContextName:- [NATIVE_APP, WEBVIEW_au.com.ventia.apps.WMS]
Checking11
Check1-0
Refresh-0
Satus0
Task0