Switching to browser from a native android app with Appium - selenium

I'm trying to handle the opening browser from a native app.
I have a native android app. When I click a link on it, it opens a browser. I'm trying to switch to that browser but couldn't do it. My code block is:
Set<String> contextNames = ((AppiumDriver) webDriver).getContextHandles();
for (String contextName : contextNames) {
if (contextName.contains("android.browser")) {
((AppiumDriver) webDriver).context(contextName);
}
}
After I debugged some (for further questions)
My app contains a vebview on all pages. Here's what I get when I check with getContextHandles() on any page:
0 = "NATIVE_APP"
1 = "WEBVIEW_com.dmall.app"
If I switch context to webview and getPageSource(), I see there is an empty view.
html xmlns="http://www.w3.org/1999/xhtml">head>/head>body>iframe name="chromedriver dummy frame" src="about:blank">/iframe>/body>
(I removed some chars because of this page accept html)
I started the test again and after click the link that opens a browser and check getContextHandles(), I see
0 = "NATIVE_APP"
1 = "WEBVIEW_com.dmall.app"
2 = "WEBVIEW_com.android.browser"
Everything looks as it should be, right?
Then I'm doing:
((AppiumDriver) webDriver).context(WEBVIEW_com.android.browser);
when I check the page source, I see the same empty webview
html xmlns="http://www.w3.org/1999/xhtml">
By the way, I can't switch to other webview after this point, it says:
"An unknown server-side error occurred while processing the command. Original error: We already have a chromedriver instance running (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 134 milliseconds"
I guess this is normal
So, how can I switch to browser, any idea, solution, questions, brain storming, anything can be useful.
My capabilities is here:
DesiredCapabilities capability = DesiredCapabilities.android();
capability.setCapability(MobileCapabilityType.APP, "http://172.20.0.196:8088/android/mfandroid-debug.apk");
capability.setCapability(MobileCapabilityType.DEVICE_NAME, "AndroidEmulator" + RandomStringUtils.randomNumeric(3));
capability.setCapability(MobileCapabilityType.PLATFORM, "Android");
capability.setCapability(MobileCapabilityType.PLATFORM_VERSION, "5.1");
capability.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 3000);
capability.setCapability("autoAcceptAlerts", "true");
capability.setCapability("sendKeyStrategy", "setValue");
Thanks

I have faced this issue before so I think I am the right person to answer this question.
You can switch to webView of the app under test [AUT] only and not to the webView of any other app. Which means your app under test is app1 and you want to switch to webView of app2.
To switch to webView of app2 you need to change the app Capabilites at run time after you perform some actions on app1. I suggest you to do:
Close the driver once you click on the link in your first native app (I hope after clicking the link will be opened in the app2).
Re-initialise the driver with new app capabilities of app2.
Now, you should able to switch to webView of app2 (browser).

Related

How to find the driver instance in QAF framework

During execution I want to know which browser currently the script is running and do some actions based on the browser the script is running.
I am using
Option 1:
if (new QAFExtendedWebDriver().getUnderLayingDriver().equals("ChromeDriver")) {
// Do`enter code here` some thing if this is a chrome browser
}
else if (new QAFExtendedWebDriver().getUnderLayingDriver() instanceof FirefoxDriver) {
}
Thsi option is not working during my excution. What is the way to know which browser I am in ?
Below are few examples:
//to get driver name for this thread which provided using driver.name
String drivername = TestBaseProvider.instance().get().getDriverName();
//if running in browser, browser name for this thread, will not be avialable for mobile native or hybrid apps
String browserName =getDriver().getCapabilities().getBrowserName();
//underlying driver class name, which can be remote driver if you are using remote driver
String driverClassname = getDriver().getUnderLayingDriver().getClass().getSimpleName();
you didn't provided details about what you are trying to achieve. If you want to do something when browser opens, you can utilize driver listener.
If you are using bdd and you have platform/browser specific code, instead of using if else you can have separate step implementation for each platform/browser in different package and load step provider package accordingly, for example:
step.provider.pkg=com.exmple.steps.common;com.exmple.steps.chrome

org.openqa.selenium.WebDriverException: unknown error: cannot focus element on trying to upload a file in selenium

I am trying to upload a file in the webpage through selenium webdriver, and i have written the below code
driver.findElement(By.cssSelector("#collapseDocuments > div > button.button.ng-isolatescope")).sendKeys("C:\\Users\\siva.247588\\Desktop\\Clarient+AML+Questionnaire.docx");
The CSS selector is that of the browse button.
I am getting the below error whwn i run this:
Exception in thread "main" org.openqa.selenium.WebDriverException: unknown error: cannot focus element
What is wrong with my code? Could any one advise?
When you try to upload a file, the control is shifted to our local machine from website where we were writing scripts.
So normal click method and select method won't work. You can use robot method to browse and upload some file from your local machine to websites.
Hope this help you..
See the below link for help:
http://www.seleniumeasy.com/selenium-tutorials/webdriver-file-upload-using-robots
I've used this somewhere , hope you can relate this:
Robot rb = new Robot();
rb.keyPress(KeyEvent.VK_A);
rb.keyRelease(KeyEvent.VK_A);
rb.keyPress(KeyEvent.VK_L);
rb.keyRelease(KeyEvent.VK_L);
rb.keyPress(KeyEvent.VK_E);
rb.keyRelease(KeyEvent.VK_E);
rb.keyPress(KeyEvent.VK_R);
rb.keyRelease(KeyEvent.VK_R);
rb.keyPress(KeyEvent.VK_T);
rb.keyRelease(KeyEvent.VK_T);
Thread.sleep(4000L);
rb.keyPress(KeyEvent.VK_TAB);
rb.keyRelease(KeyEvent.VK_TAB);
Thread.sleep(4000L);
rb.keyPress(KeyEvent.VK_ENTER);
rb.keyRelease(KeyEvent.VK_ENTER);
This will browse and upload a file with name "Alert"
If you need more help, kindly provide me code and what you want to upload , I'll help you to resolve your issue.
As #theroot mentioned AutoIT is a good solution, but the downside is it works only on windows based platforms. The best solution so far that I have come across for upload or focus outside browser situations is using Sikuli. Example code is below
Screen sikuliObject= new Screen(); // Creating Screen class object
Pattern add = new Pattern("path to the image.png"); // Path of the upload button image.
sikuliObject.click(add); // Click on Upload button
Thread.sleep(2000); // Wait for 2 seconds for upload window pop-up.
sikuliObject.type("Path of the uploading file and click on enter."+ Key.ENTER );
//Path of the uploading file and click on enter.
Thread.sleep(2000); // Wait for 2 seconds to load the file.
I've once had a similar problem (I'm not sure anymore if it threw a "not visible" exception or the "could not focus"one) and the problem was that the input Element wasn't accessible because it had no dimensions. I've changed the DOM information using the JavaScriptExecuter and afterwards it worked fine. Just go through your page with Firebug and look if the element is really visible.

How to interact with multiple browsers in the same CodedUI test

I'm trying to automate a scenario where I login to a site with two users on two different browsers where further interaction will then occur in the same test. It runs up to the point where Chrome has launched the URL and the recorded steps fail giving an error that web page cannot be accessed. The recorded steps do work on Chrome if they were separated out into its testmethod of its own.
BrowserWindow window;
window = BrowserWindow.Launch(new Uri("http://example.com"));
this.UIMap.ClickOnSignInLink();
this.UIMap.TypeInValidUserCredential();
this.UIMap.ClickOnSignInButton();
this.UIMap.AssertUserIsLoggedIn();
BrowserWindow window2;
BrowserWindow.CurrentBrowser = "Chrome";
window2 = BrowserWindow.Launch(new Uri("http://example.com"));
this.UIMap.ClickOnSignInLink();
this.UIMap.TypeInValidUserCredential();
this.UIMap.ClickOnSignInButton();
Test method FeaturesTest.LiveBidding threw exception:
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotAvailableException: The web page could not be accessed. If the page is refreshing, please wait until the page refreshes and then perform actions on it.
Only way i managed to do this is by closing the first browser. To do this you can do either of these below. Add this after IE job is finished and you want to switch to Chrome.
window.Close();
or initialize a new playback
if (Playback.IsInitialized)
{
Playback.Cleanup();
Playback.Initialize();
}

Element not being added when running test through webdriver

I am working on writing a story for a bdd framework which uses jbehave/selenium/webdriver and am having a problem where the test encounters an error while running the story but appears to be fine when running manually. I'm having a problem where javascript for the functionality I'm testing behaves slightly different when I'm running tests manually on firefox vs through selenium web driver on the same system/version of firefox and this difference is causing a js error.
I've debugged and basically the root of the problem appears to be that var request_XML_container = $('div_appendpoint_id'); returns something different when I'm running the test manually vs when I run through the bdd framework.
var request_XML_container = $('div_appendpoint_id');
request_XML_container.innerHTML = encoded_xml_from_request;
var pos = method_to_get_position('id_of_place_div_should_be_appended_to');
// JS exception is thrown saying that style is not defined **ONLY**
// when running through web driver. Running test manually on
// same system and same browser works fine.
request_XML_container.style.left = (pos[0] - 300) + 'px';
request_XML_container.style.top = (pos[1] + 25) + 'px';
request_XML_container.style.display = "block";
Why this would work fine when running manually that var request_XML_container = $('div_appendpoint_id'); would return an item with style defined, but when running through webdriver that the style attribute of the element would not be defined?
UPDATE: I had originally thought that this was updating an iframe, but I read the markup wrong and the iframe I saw is a sibling - not a parent - of the element where the response is being appended to. I'm trying to simply append the response to a div. To be honest, this only makes things more confusing as grabbing a div by id should be pretty straight forward and I'm now sure why webdriver would be producing a different return element in this situation.
UPDATE 2: Steps to reproduce and information about the system I'm on:
Use webdriver to navigate to this url: http://fiddle.jshell.net/C3VB5/11/show/
Have webdriver click the button. It should not work
Run your test again, but pause put a breakpoint at your code to click the driver
Click the button on the browser that webdriver opened. It should not work
Refresh the browser page on the browser that webdriver opened. Now, it should work.
System details:
OS : OS X 10.8.5 (12F37)
IDE : Eclipse Kepler: Build id: 20130614-0229
Browser (used manually and by webdriver) : Firefox 23.0.1
Selenium version: 2.35.0
UPDATE 3: I have provided this maven project on github to aid in reproducing: https://github.com/dkwestbr/WebdriverBug/tree/master/Webdriver
Synopsis/tl:dr; Basically, in certain situations it appears as though webdriver is overwriting the '$()' javascript method with a method that does not return an HTMLElement with innerHTML or style defined (among other things). This post details the issue and how to reproduce.
I have opened this ticket to track the issue: https://code.google.com/p/selenium/issues/detail?id=6287&thanks=6287&ts=1379519170
I have confirmed that this is a bug with the Thucydides framework (understandable since they still aren't at a 1.0 release).
Issue can be tracked here: https://java.net/jira/browse/THUCYDIDES-203

Selenium: Can't SendKeys() to an item that was below the visible window but was made visible by Click()

I have this problem with a text field that is visible at the time of the SendKeys. I'm using IEDriverServer.exe and C#.
Here's how I can reproduce the problem:
The text field in question is visible in the window but you have to scroll down to see it. To scroll down I click on the element using code like this:
var element = driver.FindElement(By.Xpath("…"));
element.Click();
This scrolls the window down and makes the text field visible.
But when I try to send text to now-visible window:
element.SendKeys("blah");
I get the exception:
When_applicant_enters_application.Should_be_instantly_approved_on_external threw exception: OpenQA.Selenium.ElementNotVisibleException: Element is not displayed
How can I fix or workaround this problem?
Selenium version: 2.32.1
OS: Windows 7
Browser: IE
Browser version: 9.0.15
I've written code demonstrating the problem and submitted it to the Selenium tech support volunteers.
The full discussion is at http://code.google.com/p/selenium/issues/detail?id=5620
but the take-home is:
// Doesn't work
// driver = new InternetExplorerDriver();
// driver.Navigate().GoToUrl(#"D:\CGY\selenium\Bug5620\Bug5620\Bug5620.htm");
// Works
// driver = new FirefoxDriver();
// driver.Navigate().GoToUrl(#"D:\CGY\selenium\Bug5620\Bug5620\Bug5620.htm");
// Works
driver = new InternetExplorerDriver();
driver.Navigate().GoToUrl(#"http://localhost:8080/Bug5620/"); // Hosted on Tomcat
so there may be a problem that possibly involves IE, IE security settings, Visual Studio local servers and/or the IE Driver. This may not even be a code problem, but something that needs to be documented, since other people are apparently running into the problem.
I don't know where the problem is exactly but I do have a work-around at this point, which is to use the Firefox Driver.
Thanks for your help, Jim. If you find out a better way of dealing with the problem, please add an answer here for the other folks.