Appium with Android Hydrid App doesn't recognise element - java

I am writing automation tests for a Hydrid App on Android. I have 2 problems:
From Appium Inspector, I see an element with attribute
resource-id: login_button
so I click this button with
androidDriver.findElement(By.id("login-button")).click();
and I get this error:
"An element could not be located with..."
Of course if I find element with
classname "android.widget.Button"
then it works. I asked developer, normally, resource-id would be like
resource-id: <APP_PACKAGE_NAME>:id/login_button
But he said for hydrid app he doesn't have bundleID (APP_PACKAGE_NAME). Is it correct that we don't have bundleID for Hydrid APP? And why Appium Inspector can see
"resource-id: login_button"
but this element could not be found and clickable?
So I also tried to switch context to WEBVIEW, with this code:
Set<String> contextHandles = appiumDriver.getContextHandles();
Map<String,String> hashMap= new HashMap<String,String>();
for (String contextname : contextHandles){
if (contextname.contains("NATIVE")){
hashMap.put("native", contextname);
} else {
hashMap.put("webview", contextname);
}
}
//webview
androidDriver.context(hashMap.get("webview"));
contextHandles has 2 values: NATIVE_APP and WEBVIEW_<APP_PACKAGE_NAME>. But when I set context to webview, I get error:
"There is no such context"
Can anyone please help? Thanks

Hybrid application means - An application build by combination of both Native App View and Web View.
But at a time only one view will be available either Native or Web
If the view is Native, then you can inspect elements from UI Automator.
If the view is webview, then the UI automator will not show any hierarchy. For that you have to inspect in browser using the url - chrome://inspect/#devices
In your case you are saying that you are able to click on login if you use class name, but unable to click when you are using resource-id
There might be multiple locators having the same resource-id. Please check once and make sure you are using unique locator that might be Xpath or class name etc

Related

How to get active Google profile name when I get the active Url from google chrome browser using C#

iam using this code to get the currently active tab open URL from Google Chrome browser.
public static string GetActiveTabUrl()
{
Process[] procsChrome = Process.GetProcessesByName("chrome");
if (procsChrome.Length <= 0)
return null;
foreach (Process proc in procsChrome)
{
// the chrome process must have a window
if (proc.MainWindowHandle == IntPtr.Zero)
continue;
// to find the tabs we first need to locate something reliable - the 'New Tab' button
AutomationElement root = AutomationElement.FromHandle(proc.MainWindowHandle);
var SearchBar = root.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"));
if (SearchBar != null)
return (string)SearchBar.GetCurrentPropertyValue(ValuePatternIdentifiers.ValueProperty);
}
return null;
}
is there any way that I can return the current Profile name too? the profile name which I mean is found on the upper right part of the google chrome browser so it maybe has more than a profile with different names I want only to get the current name with the URL it comes from this function. I can open or use many profiles at the same time in google chrome, so I want to get the active Tab URL and the profile name with it or the email of that profile.
this an image of the profile name i want it from chrome to be sent with the currently active tab URL.
so i expect something like that for example to be done in c# to get the profile name
var SearchBar = root.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "profile email"));
last thing it can be c# or java codes if it can be better do in it also any solution that can get it in any programming language, please help with any information.
Thanks in advance.
You are going to have to dive into the HTML a little bit. Use chrome's developer features and inspect the HTML. You will find what class the username is under and the text is stored as the title find an example below.
<a class="gb_b gb_ib gb_R" href="https://accounts.google.com/" role="button" tabindex="0" title="Google Account: FillerFirstName FillerLastName (fillerEmail#gmail.com)" aria-expanded="false"><span class="gb_db gbii"></span></a>
You can accomplish this in many different ways with C#. I would recommend Selenium.

appium selects incorrect item from the popup list

I have two questions related to the same issue that I cannot solve. I'm creating an appium programm to test a native android app. I'm using Java.
Before the login, there's an option in the app to change the environment. I'm passing in my appium class the environment name as a parameter, and I'm using the Xpath to find the element corresponding to the provided environment.
Issue: it doesn't matter which environment name I'm passing as a parameter, every time it changes to the particular one (staging).
Questions:
What could be the cause of it?
Why when I'm using the xpath with the text parameter, the appium cannot find the element despite the uiautomatorviewer tool has that text property.
selectEnv = androidDriver.findElement(By.xpath("//android.widget.LinearLayout[#text='QA']"));
I provided 2 screenshots. The first one is an actual app screen with the list of the environments and the properties from Android Studio Layout Inspector.
The second one is the screenshot of uiautomatorviewer properties for one of the items from the list.
new WebDriverWait(androidDriver, 30).until(ExpectedConditions.presenceOfElementLocated(id("md_contentRecyclerView")));
envContainer = androidDriver.findElement(By.id("md_contentRecyclerView"));
Assert.assertTrue(envContainer.isDisplayed());
if (env.equals("dev")) {
selectEnv = androidDriver.findElement(By.xpath("//android.widget.LinearLayout[#index='0']"));
selectEnv.click();
}
if (env.equals("QA")) {
selectEnv = androidDriver.findElement(By.xpath("//android.widget.LinearLayout[#index = '1']"));
selectEnv.click();
}
if (env.equals("Staging")) {
selectEnv = androidDriver.findElement(By.xpath("//android.widget.LinearLayout[#index='2']"));
selectEnv.click();
}
if (env.equals("Prod")) {
selectEnv = androidDriver.findElement(By.xpath("//android.widget.LinearLayout[#index='3']"));
selectEnv.click();
}
You're attempting to click the LinearLayout instead of its Textview.
Use:
selectEnv = androidDriver.findElement(By.xpath("//android.widget.TextView[contains(.,'QA')]"));
selectEnv.click();
Eventually was able to find the element using UiSelector
findElementByAndroidUIAutomator ("new UiSelector().textContains(\"QA\")");

Winium - how to access tool bar item if that bar doesn't have child

I am using Winium + Java for automation testing of Windows application, and trying to access tool bar menu.
When I tried to detect elements using UI Automation Verify, I couldn't see child elements under tool bar element like below screenshot.
enter image description here
But my tool bar definitely has sub menu items like screenshot and I need to access them.
enter image description here
I tried below java code, but it didn't work
WebElement el = driver.findElement(By.id('59398'));
el.click();
WebElement child = el.findElement(By.name('Start'));
child.click();
when I tried
driver.findElement(By.name"Start').click();
it clicked my windows start menu, not my application's menu.
Is there any way to access items under this tool bar?
You can try use another UI Inspector
eg. UI SPY or Inspector.exe
Probably your ID is not a AutomationID (process id?)
You should find a main window (parent of your app) (Example for calc) and get a parameter like AutomationId, ClassName or Name
I see this is MFC application, and this is an app side MFC library problem. If you hover mouse over toolbar button using Inspect.exe, the info is available but you can't reach this button from the hierarchy (the buttons have no parent somehow). Possible workaround involves combined Win32 API and UI Automation approach:
get button rectangle using Win32 API (but there is no text).
use ElementFromPoint method of UI Automation API and get actual texts to choose the right button.
P.S. My suggestion is applicable for Java + Winium in theory. But I can't estimate the complexity because I'm not a Java expert. So below is Python solution.
We have plans to implemented this mixed way in pywinauto. See issue #413. It contains Python code sample how to do that. We've had no chance to integrate it yet.
from ctypes.wintypes import tagPOINT
import pywinauto
app = pywinauto.Application().start(r'.\apps\MFC_samples\RebarTest.exe')
menu_bar = app.RebarTest.MenuBar.wrapper_object()
point = menu_bar.button(0).rectangle().mid_point()
point = menu_bar.client_to_screen(point)
elem = pywinauto.uia_defines.IUIA().iuia.ElementFromPoint(tagPOINT(point[0], point[1]))
element = pywinauto.uia_element_info.UIAElementInfo(elem)
print(element.name)

Cannot go to "chrome://downloads/" in a newly opened tab with Selenium in Chrome

I am using Selenium and Java to write a test for Chrome browser. My problem is that somewhere in my test, I download something and it covers a web element. I need to close that download bar (I cannot scroll to the element). I searched a lot and narrowed down to this way to open the download page in a new tab:
((JavascriptExecutor) driver).executeScript("window.open('chrome://downloads/');");
It opens that new tab, but does not go to download page.
I also added this one:
driver.switchTo().window(tabs2.get(1));
driver.get("chrome://downloads/");
but it didn't work either.
I tried:
driver.findElement(By.cssSelector("Body")).sendKeys(Keys.CONTROL + "t");
and
action.sendKeys(Keys.CONTROL+ "j").build().perform();
action.keyUp(Keys.CONTROL).build().perform();
Thread.sleep(500);
but neither one even opened the tab.
It is because you can't open local resources programmatically.
Chrome raises an error:
Not allowed to load local resource: chrome://downloads/
Working solution is to run Chrome with following flags:
--disable-web-security --user-data-dir="C:\chrome_insecure"
But this trick doesn't work with Selenium Chrome Driver(I don't know actually why, a tried to remove all args that appears in chrome://version, but this doesn't helps).
So for me above solution is the only one that works:
C# example:
driver.Navigate().GoToUrl("chrome://downloads/")
There is another trick if you need to open downloaded file:
JavaScript example:
document.getElementsByTagName("downloads-manager")[0].shadowRoot.children["downloads-list"]._physicalItems[0].content.querySelectorAll("#file-link")[0].click()
Chrome uses Polymer and Shadow DOM so there is no easy way to query #file-link item.
Also you need to execute .click() method with JavaScript programatically because there is a custom event handler on it, which opens actual downloaded file instead of href attribute which point to url where you downloaded file from.
I started with this post and ended up with the solution given below. This one works in Chrome 71. First I highlighted the control and then clicked it.
The window object is actually the IWebDriver, the second method is called after the first one.
internal void NavigateToDownloads()
{
window.Navigate().GoToUrl("chrome://downloads/");
}
internal void OpenFirstDownloadLinkJS()
{
IJavaScriptExecutor js = (IJavaScriptExecutor) window;
js.ExecuteScript("document.getElementsByTagName('downloads-manager')[0].shadowRoot.children[4].children[0].children[1].shadowRoot.querySelectorAll('#content')[0].querySelector('#details > #title-area > #file-link').setAttribute('style', 'background: yellow;border: 2px solid red;');");
js.ExecuteScript("document.getElementsByTagName('downloads-manager')[0].shadowRoot.children[4].children[0].children[1].shadowRoot.querySelectorAll('#content')[0].querySelector('#details > #title-area > #file-link').click();");
}
Use this code (I wrote it in Python, but it should work in Java too with very slight modifications):
#switching to new window
driver.execute_script("window.open('');")
driver.switch_to.window(driver.window_handles[1])
#opening downloads
driver.get('chrome://downloads/')
#closing downloads:
driver.close()

Android & Appium(Java) : WebView inaccessible

I'm currently using Appium and have hit an issue with regard to finding the WebView context. Using UIAutomator I can inspect the WebView and see its child elements, however I cannot access any of these by using CSS selector/ XPATH because I cannot switch to WebView.
I have tried looping over driver.getContextHandles(), however this simply returns "NAVTIVE_APP".
Android version being used is 5.0.1 and the latest version of Appium.
Does anyone know of a way to find out the name of the WebView or possibly being able to switch to it?
You need to handle the contexts....below is an example of handling Login with Facebook webview. It worked for me....
Set<String> contextHandles = driver.getContextHandles();
for (String s : contextHandles) {
System.out.println("Context : " + s);
//if context contains webview then set the webview context
if (s.contains("WEBVIEW")) {
//System.out.println("Set the Context NATIVE to WEBVIEW");
driver.context(s);
}
}
driver.findElement(By.xpath("//android.widget.EditText[#index='0']")).sendKeys(EMAIL);
//System.out.println("UserName Entered");
//sleep(3000);
driver.findElement(By.xpath("//android.widget.EditText[#index='1']")).sendKeys(PASSWORD);
//System.out.println("Password Entered");

Categories

Resources