ImageView Click

On our application, we have a three vertical dots similar to whatsapp application in the right top corner. I need to have a program to click that to get to login option and to get to login page.

….driver.findElement(By.className(“android.widget.ImageView[@clickable=‘true’]”)).click();

This is what I am using to click the three dots since I have the classname and I still get this error:

FAILED: Options
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: 120.51 seconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: ‘2.47.1’, revision: ‘411b314’, time: ‘2015-07-30 02:56:46’
System info: host: ‘WUSJH255011-BYY’, ip: ‘172.16.12.53’, os.name: ‘Windows 7’, os.arch: ‘amd64’, os.version: ‘6.1’, java.version: ‘1.8.0_11’
Driver info: io.appium.java_client.android.AndroidDriver
Capabilities [{appPackage=com.salientfed.maptest2, networkConnectionEnabled=true, warnings={}, databaseEnabled=false, deviceName=57a74cc2, platform=LINUX, appActivity=com.salientfed.maptest2.SplashScreen, desired={appActivity=com.salientfed.maptest2.SplashScreen, appPackage=com.salientfed.maptest2, platformName=Android, deviceName=57a74cc2}, platformVersion=5.0.1, webStorageEnabled=false, locationContextEnabled=false, browserName=Android, takesScreenshot=true, javascriptEnabled=true, platformName=Android}]
Session ID: 27305874-4233-41d4-bc1f-46d73b98f051
*** Element info: {Using=class name, value=android.widget.ImageView[@clickable=‘true’]}
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:206)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:158)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:595)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:42)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1)
at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:348)
at org.openqa.selenium.remote.RemoteWebDriver.findElementByClassName(RemoteWebDriver.java:429)
at io.appium.java_client.DefaultGenericMobileDriver.findElementByClassName(DefaultGenericMobileDriver.java:110)
at io.appium.java_client.AppiumDriver.findElementByClassName(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.findElementByClassName(AndroidDriver.java:1)
at org.openqa.selenium.By$ByClassName.findElement(By.java:388)
at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:340)
at io.appium.java_client.DefaultGenericMobileDriver.findElement(DefaultGenericMobileDriver.java:52)
at io.appium.java_client.AppiumDriver.findElement(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.findElement(AndroidDriver.java:1)
at TTIAndroidTest.Options(TTIAndroidTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)

Super frustrated… Can someone tell me what I am doing wrong? Thank you!!!

In the UIAutomatorViewer, check what the “content-description” field. The 3 dots image is often labeled as “Overflow” (for overflow menu).

If the image is labeled “Overflow”, you can retrieve a MobileElement for that view using MobileBy.AccessibilityId(“Overflow”). If not, a quick and dirty hack would be to do something like…

driver.tap(1, x, y, 1), where you would have to calculate x to be 95% of the screen’s width and y to be 5% of the screen’s width. My Java code for this type of trick is

Dimension screenDim = driver.manage().window().getSize();
int x = (int)(0.95 * screenDim.getWidth());
...//same thing for y with 0.05 instead of 0.95
driver.tap(1, x, y, 1);

Hello,

Thank you. Unfortunately, the content description field is blank for us…

On our application, we have a three vertical dots similar to whatsapp application in the right top corner. I need to have a program to click that to get to login option and to get to login page.

….driver.findElement(By.className(“android.widget.ImageView[@clickable=‘true’]”)).click();

This is what I am using to click the three dots since I have the classname and I still get this error:

FAILED: Options
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: 120.51 seconds
For documentation on this error, please visit: Selenium
Build info: version: ‘2.47.1’, revision: ‘411b314’, time: ‘2015-07-30 02:56:46’
System info: host: ‘WUSJH255011-BYY’, ip: ‘172.16.12.53’, os.name: ‘Windows 7’, os.arch: ‘amd64’, os.version: ‘6.1’, java.version: ‘1.8.0_11’
Driver info: io.appium.java_client.android.AndroidDriver
Capabilities [{appPackage=com.salientfed.maptest2, networkConnectionEnabled=true, warnings={}, databaseEnabled=false, deviceName=57a74cc2, platform=LINUX, appActivity=com.salientfed.maptest2.SplashScreen, desired={appActivity=com.salientfed.maptest2.SplashScreen, appPackage=com.salientfed.maptest2, platformName=Android, deviceName=57a74cc2}, platformVersion=5.0.1, webStorageEnabled=false, locationContextEnabled=false, browserName=Android, takesScreenshot=true, javascriptEnabled=true, platformName=Android}]
Session ID: 27305874-4233-41d4-bc1f-46d73b98f051
*** Element info: {Using=class name, value=android.widget.ImageView[@clickable=‘true’]}
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:206)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:158)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:595)
at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:42)
at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1)
at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:348)
at org.openqa.selenium.remote.RemoteWebDriver.findElementByClassName(RemoteWebDriver.java:429)
at io.appium.java_client.DefaultGenericMobileDriver.findElementByClassName(DefaultGenericMobileDriver.java:110)
at io.appium.java_client.AppiumDriver.findElementByClassName(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.findElementByClassName(AndroidDriver.java:1)
at org.openqa.selenium.By$ByClassName.findElement(By.java:388)
at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:340)
at io.appium.java_client.DefaultGenericMobileDriver.findElement(DefaultGenericMobileDriver.java:52)
at io.appium.java_client.AppiumDriver.findElement(AppiumDriver.java:1)
at io.appium.java_client.android.AndroidDriver.findElement(AndroidDriver.java:1)
at TTIAndroidTest.Options(TTIAndroidTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)

Super frustrated… Can someone tell me what I am doing wrong? Thank you!!!

Hi again! I must have skipped over the code portion (strange blindness case for me). It looks like you’re trying to combine Xpath and non-Xpath syntax together. Instead, try one of these:

driver.findElement(By.className("android.widget.ImageView").click();

This will click the first ImageView found on the screen, so this might be a menu button or the application logo. If this is the case, you can modify the command to instead be:

List<WebElement> imageViews = driver.findElements(By.className("android.widget.ImageView");
//Iterate through the elements returned in the list to find the one you want.

The overflow menu icon is often the second or third image view in the array, so you can try tapping on the second or third element (a bit of trial and error involved).

Explanation of what happens when you use By.className(“android.widget.ImageView[@clicakable=‘true’]”): When this command is run, Appium tries to find a UI element on the screen whose class literally is “android.widget.ImageView[@clickable=‘true’]”, rather than searching for an element whose class type is “android.widget.ImageView” and has an attribute “clickable” set to “true”. If you want to use Xpath notation, you can use By.Xpath(…) instead. Be sure that there is an attribute “clickable” on the element, though.

My goodness, it worked! You are a savior! Now I need to find a code to enter username and password on the page… Thank you so much!!!

My Goodness, it worked only once and not working anymore! I saw once login page brought up and after that one time, does not work.

driver.findElementByClassName(“android.widget.ImageView”).click();
driver.findElementByName(“Login”).click();

I think you might have to explain what you mean a bit more. My understanding is that the following line:

driver.findElementByClassName("android.widget.ImageView").click()

runs without issue. Appium processes this line by simulating a tap on the overflow icon and brings up the menu. Then Appium tries to run

driver.findElementByName("Login").click()

Is this where the problem happens?

It worked once then no longer works…It’s not clicking the three dots after that one time… That’s why elclipse error says can’t find the Name Login since it’s can’t click on the three dots.

BTW, thank you so much for this…

Yes. When I commented driver.findElementByName(“Login”).click() out, it clicked on the three dot. This Login is a text…

My best guess is that your test code and Appium are executing too quickly. After Appium responds to your test code that it has tapped on the overflow icon, your test code generates another request for Appium to search for and locate the element named “Login”. However, on the app-side, the overflow icon was just tapped, and the app needs to build and render the UI element named “Login”. When the search request for “Login” comes in, the UI element has not been created yet, so the Android device has to return empty for the search. Appium responds with an Exception stating that the element could not be found. You can try adding in a wait between the tap and the search for “Login” (using Thread.sleep or a WebDriverWait tend to be the simplest options).

In any case, can you copy the stack trace from running your test project when the test fails, and also copy+paste the Appium logs from the Appium application (these logs should either be in the console or the Appium window).

Hello,

driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
Would this work in between? Thank you again.

WebDriverWait wait = new WebDriverWait(driver, 360);

Worked!!! Thank you so much!!!

Hello,

I hope you don’t find this annoying, not trying to bug so much but I am learning as I am going.
So trying to use the WebDriverWait wait = new WebDriverWait(driver, 360); multiple times and it does not like it since the wait variable is same… This is the code then it bombs out on the login element again… Any thoughts? Thank you so much…

    driver.findElementByClassName("android.widget.ImageView").click();
WebDriverWait wait = new WebDriverWait(driver, 360);
	driver.findElementByName("Login").click();
	WebDriverWait wait2 = new WebDriverWait(driver, 360);
	driver.findElementById("com.salientfed.maptest2:id/email").sendKeys("janet2");
	WebDriverWait wait3 = new WebDriverWait(driver, 360);
	driver.findElementById("com.salientfed.maptest2:id/password").sendKeys("test");
	WebDriverWait wait4 = new WebDriverWait(driver, 360);
	driver.findElementById("com.salientfed.maptest2:id/email_sign_in_button").click();
	WebDriverWait wait5 = new WebDriverWait(driver, 360);

Don’t worry about bugging me. I visit these forums during my free time.

In your code, you need to actually call the “until()” method of the WebDriverWait class. These lines:

WebDriverWait wait = new WebDriverWait(driver, 360);

only construct the WebDriverWait object. To actually wait for the object to show up, you need to also do something like this:

wait.until(new Predicate<WebDriver>() {
    @Override
    public boolean apply(WebDriver input) {
        WebElement elementToCheckFor = input.findElement(By.className("android.widget.ImageView"));
        return elementToCheckFor != null;
    }
});

The WebDriverWait class will repeatedly call the apply() method of the Predicate instance you pass to the WebDriverWait’s until() method. If you do not do this, the WebDriverWait object actually does not perform any waiting. The wait object will repeatedly call apply() until one of the following happens:

  1. The apply() method returns true.
  2. The timeout is reached.

When situation #1 occurs, then the until() method will return, and the condition you want to check for inside the apply() method should be true (in this case, the existence of some object with class android.widget.ImageView). The condition you want to check for should be implemented inside the apply() method.

When the apply() method returns false, or throws a NoSuchElementException, the wait object will put your thread to sleep for 500 ms. When the thread awakens again, the wait object will just call apply() again to check if the condition became true while the thread was sleeping. This is how the wait object will poll the device to check for the condition you want.

When the wait object has repeated the cycle in the previous paragraph enough times without success and the timeout has been reached, then the wait object will stop polling and throw a TimeoutException. In this case, if you chose a suitable timeout, then you can be sure that the condition you were checking for did not occur.

The neat thing about using WebDriverWait is that the wait will only wait as long as necessary until the condition becomes true. This lets your test run very quickly while waiting only as long as necessary. The timeout you pass to the constructor is how long you want to wait at most for a condition.

I also want to note that your timeout is set to 360 ms. You generally want this to be larger than 500 ms, because if the first apply() call fails, then the thread will sleep for 500 ms. When the thread reawakens, you’ll immediately receive a TimeoutException because the thread has “polled” the device longer than the given timeout of 360 ms.

so sorry. I think I am not a java coder. Even your detailed explanation, I still can’t code it make it work… :frowning:

Try this:

driver.findElementByClassName("android.widget.ImageView").click();
WebDriverWait wait = new WebDriverWait(driver, 1000);
wait.until(new Predicate<WebDriver>() {
    @Override
    public boolean apply(WebDriver input) {
        return input.findElement(By.name("Login")) != null;
    }
}); 
driver.findElementByName("Login").click();

I literally copied in then getting following errors.

The type new Predicate(){} must implement the inherited abstract method Predicate.test(WebDriver)

The method apply(WebDriver) of type new Predicate(){} must override or implement a supertype method

Hmm… did you import the Predicate class with

import com.google.common.base.Predicate;

This package is available from the Google Guava library. This library should already be on your dependency list (since Appium’s Java client itself is dependent on Guava).

import java.util.function.Predicate;

I have this… thank you