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");
Related
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.
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\")");
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
the problem I'm having is injecting some JavaScript into a WebView. I only have this problem on Android version 2.3.6 and below I'm assuming, don't have a test device lower than that though. My code works fine in Android 4+ so I'm not quite sure why it's failing. It seems to "submit" the form but doesn't fill out the username and password field in 2.3.6 so it always fails. My main goal is to simulate a form fill-out and submit in a WebView with two EditTexts so the user doesn't have to interact with the WebView itself. When the user hits the login button it runs this code:
//Set what needs to be filled out in the WebView
String javaScript = "(function(){ " +
"document.getElementById('user').value = '" + mUsername + "'; " +
"document.getElementById('password').value = '" + mPassword + "'; " +
"document.getElementById('form').submit(); " +
"})()";
//Load the javascript here
mWebView.loadUrl("javascript: " + javaScript);
I'm also setting my WebView settings to this:
//Setup the WebView options/settings
...
mWebView.getSettings().setSaveFormData(false);
mWebView.getSettings().setJavaScriptEnabled(true);
...
I've tried searching for any reason why this wouldn't work on 2.3.6 but haven't come up with anything. Is there some restriction in version 2.* that isn't present in 4+?
Edit: The button that runs the above code is only enabled once the page is finished loading. So when this button is clicked the above JS injection is run.
#Override
public void onPageFinished(WebView view, String url) {
...
//Only allow the user to inject the JS when the page has loaded
if(url.equals("...")
button.setEnabled(true);
...
}
SOLUTION: I'm not sure if this actually was the cause but changing the single quotes in the JS code to use double quotes seemed to make it run. Something like:
String javaScript = ... + "document.getElementById(\"user\").value = \"" + mUsername + "\"; "
There aren't any restrictions that I'm aware of but it's not uncommon to encounter issues stemming from differing Javascript engines in various versions of Android. It is likely simply a matter of trying different syntax to achieve the same result in an attempt to hit upon a version of the logic that makes that version of Javascript happy.
Including JQuery and writing your function using Jquery syntax might be a solution, too. As JQuery itself seems pretty good at dealing with these differences.
At which point in your flow does the JavaScript URL get loaded? Are you certain that at this time the DOM is loaded and the elements you reference are valid?
Do you see anything output in logcat when trying to execute the JavaScript? That should show JavaScript errors.
I have a problem with loading local html pages to webView in android 4. Before, I tested it for android 2.3 and it was ok. I load the page like this webView.loadUrl(file:///android_asset/drawable/test.html) I read a lot of information about bug with loading local pages, but I have not solution of this problem. Can you explain me why it doesn't load pages and write that "Web page not avaliable" . May be problems with "file:///" or "android_asset". Please give me real advice how I can load my html pages to webview in android 4. I really need. Thank you.
P.S I am sure that the file exists in that folder.
I resolved my problem. I used:
private final int boundaryApiValue = 10;
/**Function set root directory for current api version.*/
private void setRootPathForCurrentVersionOfAndroid() {
if (Build.VERSION.SDK_INT >= boundaryApiValue)
rootPath = "file:///android_res/drawable/";
else {
rootPath = "file:///android_asset/res/drawable/";
}
}
If u have a version lower than Android HoneyComb than u should load html files for webview from "file:///android_asset/res/drawable/" if u have HoneyComb and later than use "file:///android_res/drawable/" It's works for me fine.