Upload File on selenium node (grid environment) , where in upload button is not of input(type='file') - file-upload

I do have a page , where import button looks like this .
Dom Structure of above import button is as below
<button ngf-select="" ng-model="$parent.enduserMashups.files" class="btn btn-default text-center ng-pristine ng-untouched ng-valid ng-empty">
<i class="icon-import-data"></i>
<span>Import</span></button>
I have written selenium upload utility as below , which works fine in case of NON-GRID environment (local machine)
public void uploadFile(String filePath)
{
// Setting up clipBoard location
StringSelection ss = new StringSelection(filePath);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
// Using Robot class to upload file
Robot robot;
try
{
robot = new Robot();
try
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
// Press Enter
robot.keyPress(KeyEvent.VK_ENTER);
// Release Enter
robot.keyRelease(KeyEvent.VK_ENTER);
// Press CTRL+V
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
// Release CTRL+V
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_V);
try
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
};
// Press Enter
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
} catch (AWTException e)
{
e.printStackTrace();
}
}
In case of running above code on selenium grid-node environment , 'import' button gets clicked on node browser instance and here it doesn't find file(obviously), as it is saved on another machine from where testcase is running .
Googling a lot , I found some solutions which states that in case of having button , we can use webdriver.sendKeys(file) method , which sends file to selenium node directly , however that is applicable in case of tag only .
What about in case of NOT having element ?

Here's what you can do to solve your issue.
You need to build a custom servlet which has a POST/GET method defined and which can be used to trigger a file upload. ( See here for an example). You need to also make sure that this servlet will return back the absolute file path of where the file was saved after it was accepted.
You now inject the newly built custom servlet into the Grid node ( See here to learn how to do it )
Similar to (1) and (2) you build another servlet with a GET/POST action which when invoked can internally call your uploadFile() method. [ You will basically pass the filepath that you obtain from invoking the servlet explained in (1)
You refer to this blog post of mine to learn how to find out where did the Grid route your tests to and using the mechanism I have explained you retrieve the IP and port of the node to which your test was routed to.
Using the IP and Port number obtained from (4) you first invoke the Upload file servlet to first upload your file to the remote machine on which the node is running and get back the saved file's absolute file path from the servlet.
You now invoke your other servlet which contains the uploadFile() method and driven by the ROBOT APIs by passing the absolute file path from (5) and have it perform the upload action using ROBOT on the remote host.
That should do the trick.

Related

Selenium getting stuck on data:, (MS Edge)

I want to use Selenium to navigate to a website. Selenium opens up the browser but does not navigate further to the specified website URL, but gets stuck on the "data:," url. After some time time I get the following exception:
"The HTTP request to the remote WebDriver server for URL http://localhost:58504/session timed out after 60 seconds"
Note: I did not specify the 58504 port anymore, so I guess it is the default port that Selenium use?
I am programming in C# and using the following Nuget Packages:
https://www.nuget.org/packages/Selenium.WebDriver/4.1.1
https://www.nuget.org/packages/WebDriverManager/2.13.0
Here is the code:
using OpenQA.Selenium;
using OpenQA.Selenium.Edge;
using WebDriverManager;
using WebDriverManager.DriverConfigs.Impl;
using WebDriverManager.Helpers;
public void VisitWebsite()
{
IWebDriver driver = null;
try
{
new DriverManager().SetUpDriver(new EdgeConfig(), VersionResolveStrategy.MatchingBrowser);
EdgeOptions options = new EdgeOptions();
options.AddArgument("--no-sandbox);
options.AddArgument("--disable-infobars");
options.AddArgument("--disable-dev-shm-usage");
options.AddArgument("--disable-browser-side-navigation");
options.AddArgument("--disable-extensions");
options.AddArgument("--dns-prefetch-disable");
options.AddArgument("--disable-gpu");
options.AddArgument("--disable-software-rastersizer");
driver = new EdgeDriver(options);
}
catch (Exception ex)
{
throw ex;
}
driver.Navigate().GoToUrl("https://www.google.com");
}
Where does it go wrong? Thanks!
I found the answer. It seems the DeveloperToolsAvailability policy for the MSEdge browser had a value that "blocks" Selenium from working. You can read more about it here: https://learn.microsoft.com/en-us/microsoft-edge/webdriver-chromium/?tabs=c-sharp#developer-tools-availability-policy

selenium chrome driver select certificate popup confirmation in c#

I am automating tests using selenium chrome webdriver. Whenever I launch the site, I get a certificate selection popup like the one below:
The following code works in Java:
try {
driver.get(url);
} catch (Exception e) {
e.printStackTrace();
}
};
public void myfunction {
try {
Thread mthread = new Thread(mlauncher);
mthread.start
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
} catch (Exception e) {
e.printStackTrace();
}
I have not found code that works in c#.
I try with your solution, I use AutoIt.AutoItX library and use it to select a certificate but I have a problem.
when I click in the LogIn button, it show on the popup possibility to select ssl certificate.
The execution of the automatic test stops, and waits for the selection of the certificate.
When I manually select certificate, my automatic test continues with further execution, of that part that should select automaticly certificate in AutoIt.AutoItX.
It should contue automaticly without stopping, AutoIt.AutoItX part should not be on hold, but should be used to select a certificate.
{
welcomePage.LogIn.Click();
AutoIt.AutoItX.Send("{TAB}", 0);
AutoIt.AutoItX.Send(url, 10);
AutoIt.AutoItX.Send("{ENTER}", 0);
}

Winium remote automation?

I am using Winium to automate a desktop application. The process is I download a file from the web and execute it. which opens the remote application. Till here everything is working fine, but I am unable to access any control of that newly launched remote Citrix application. Any help would be appreciated.
public void SetupEnv() throws InterruptedException
{
DesktopOptions options = new DesktopOptions();
options.setApplicationPath("C:\\Users\\ajinkya\\Downloads\\launch.ica");
try
{
driver = new WiniumDriver(new URL("http://localhost:9999"), options);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
Thread.sleep(5000);
driver.findElementByClassName("Transparent Windows Client").click();
Thread.sleep(5000);
}
Maybe you should try something like this:
WebElement window = driver.findElementByName("abcd.exe");
WebElement menuItem = window.findElement(By.name ("Find Item"));
menuItem.click();

Selenium tests hang on CI while loading content

I'm trying to debug some Selenium tests but I cannot reproduce the issue locally. On the CI, after selecting some check boxes, the page reloads (a loading animation is displayed), and on the Jenkins agent it hangs for hours. I tried using these options, which I've added in the class constructor of the page:
driver.manage().timeouts().implicitlyWait(8, SECONDS);
driver.manage().timeouts().pageLoadTimeout(8, SECONDS);
Also I tried
public static void waitForLoadingPopUpToBecomeInvisible() {
try {
WebdriverWait wait = new WebDriverWait(driver, 20);
wait.until(invisibilityOfElementLocated(By.className("loading")));
} catch (Exception e) {
driver.navigate().refresh()
}
}
I want to refresh the page if the loading animation is visible for more than X seconds, or to force kill the test if it has been running for more than Y minutes.
Can you please suggest any better ideas?

Handling Browser Authentication using Selenium

Does anyone know about handling Browser Authentication using Selenium or any other tool during automation?
EDIT in 2015:
This answer is outdated. WebDriver nowadays supports authentication! See How to handle authentication popup with Selenium WebDriver using Java
Original answer:
This is not handled very well by Selenium.
You can try using http://username:password#example.com/yourpage
instead of just http://example.com/yourpage
However, as far as I know, Firefox will still pop up a browser dialog requesting a confirmation.
You can try Robot if you're using Java (or any similar tool like AutoIt).
You could use driver.manage().addCookie() if you're using WebDriver.
Or a custom FirefoxProfile that has already passed the authentication once.
I spent days on this - literally.
Trying to get past browser level authentication within my company network to hit an application.
The solution was to use the 'unsername:password#' component within the URL, BUT to add a forward slash at the end of the login URL.
So total login URL looks like this (note the '/' after yourpage):
http://username:password#example.com/yourpage/
Works with Watir, Capybara and Selenium Webdriver.
Everything I have read on the Web didn't help me. So before making a request, like this:
driver.get(url);
you have to run a new thread like this:
RunScript runScript = new RunScript();
runScript.start();
In this case you are free to input login and password on another thread of follwing class
public class RunScript extends Thread {
#Override
public void run() {
try {
File file = new File("D:\\jacob-1.18-x86.dll");
System.setProperty(LibraryLoader.JACOB_DLL_PATH, file.getAbsolutePath());
AutoItX autoIt = new AutoItX();
Thread.sleep(2000);
autoIt.winActivate("yourWindowName", "");
autoIt.winWaitActive("yourWindowName");
if (autoIt.winExists("yourWindowName")) {
autoIt.send("username{TAB}", false);
autoIt.send("password{Enter}", false);
}
}
} catch (InterruptedException ex) {
//
}
}
}
All the hacks via auto-it, sikuli, etc. just wasting your time when you'll run it in your CI solution, using several browser types / OS / Version / Resolutions etc.
The way to do it correctly is to identify the authentication actual method and perform a login using Rest protocol for instance.
I used it to get the JSESIONID cookie and insert it to the selenium driver.
hint on that: go to a non-exiting url of the domian first, then set the cookie, then go to the required url - you are logged-in.
use: rest client authentication to get the JSESSION ID
and With this information:
browser().navigate(foo.getUrl()+"non-exiting-url");
//the information got from the rest client login:
Cookie cookie = new Cookie(name, value, domain, path, expiry, isSecure, isHttpOnly);
try {
driver.manage().addCookie(cookie);
} catch (Exception e) {
System.out.println(e.toString());
}
browser().navigate(foo.getUrl());
you can use auto IT script to handle this problem
WinWaitActive("[CLASS:Chrome_WidgetWin_1]", "", time)
Send("user")
Send("{TAB}")
Send("pass")
Send("{ENTER}")
with Chrome 70 and other versions :
http://username:password#example.com/yourpage
You can use Java Robot class with Selenium 2 /Selenium WebDriver using Firefox
WebDriver driver = new FirefoxDriver();
driver.get("http://localhost:9990");
WebElement myDynamicElement = driver.findElement(By.id("app"));
Alert alert = driver.switchTo().alert();
try {
Robot robot = new Robot();
alert.sendKeys("username");
robot.keyPress(KeyEvent.VK_TAB);//go to password feild
robot.keyPress(KeyEvent.VK_P);
robot.keyPress(KeyEvent.VK_A);
robot.keyPress(KeyEvent.VK_S);
robot.keyPress(KeyEvent.VK_S);
robot.keyPress(KeyEvent.VK_ENTER);
} catch (AWTException e) {
e.printStackTrace();
}
}
Using Selenium with Robot
http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Robot.html