C#, Visual Studio 2015, .NET 4.x Framework, Internet Explorer 11 (or latest Chrome), Windows 8.1 Pro workstation.
For testing purposes, using a Windows Forms or Console application written in C#, I need to automate an existing browser instance running on a Windows 8 or 10 system.
I created a Windows Forms application, and I'm able to automate a browser that I start using the Navigate(...) method within the application using the WebBrowser control and do things like click on a button in a Javascript popup, login using a username and password, select an item from the datagridview and click on the "edit" button associated with that item.
However, once that "edit" button is clicked, additional browser windows are created that are now running outside the "scope" of the WebBrowser control.
The web application opens new instances of the browser using window.open(...,_blank);
I've tried working with the NewWindow event, but I don't seem to be able to grab any kind of "handle" or such to the newly opened windows. The event fires, but what I'm seeing when I debug inside the event is just information about the window that I'm currently working with (not the newly spawned window).
The other things I've tried are Selenium and WatIn.
For both, the examples I had an instance of Internet Explorer 11 running on my Windows 8.1 Pro workstation at www.google.com.
Generally, the examples seem to show that for "attaching to an existing instance" of a browser the examples first firing off the browser. I've tried to connect to an existing browser using both libraries, and I've not had success.
I've tried to use the RemoteWebDriver(...) for Selenium, using the InternetExplorer driver. Another Stack Overflow post indicates I don't need the server component running because the browser and application for testing are on the same machine. My code is as follows:
private void doSeleniumStuff()
{
DesiredCapabilities desired = DesiredCapabilities.InternetExplorer();
using (IWebDriver driver = new RemoteWebDriver(new Uri("http://www.google.com/wd/hub"), desired))
{
IWebElement query = driver.FindElement(By.Name("q"));
query.SendKeys("Cheese");
query.Submit();
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => d.Title.StartsWith("cheese", StringComparison.OrdinalIgnoreCase));
Console.WriteLine("Page title is: " + driver.Title);
}
}
I'm somewhat confused about the URL used in the RemoteWebDriver constructor. The documentation doesn't seem to describe this usage well. What is this "/wd/hub" usage all about?
It failes with:
{"Unexpected error. <!DOCTYPE html>\r\n<html lang=en>\r\n <meta charset=utf-8>\r\n <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">\r\n <title>Error 404 (Not Found)!!1</title>\r\n <style>\r\n *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}#media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}#media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}#media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\r\n </style>\r\n <a href=//www.google.com/><span id=logo aria-label=Google></span></a>\r\n <p><b>404.</b> <ins>That’s an error.</ins>\r\n <p>The requested URL <code>/wd/hub/session</code> was not found on this server. <ins>That’s all we know.</ins>\r\n"}
I've tried using the AttachTo(...) method in WatIn.
[STAThread]
private void doWatNStuff()
{
using (IE myIE = Browser.AttachTo<IE>(Find.Any))
{
DomContainer dc = myIE.DomContainer;
}
}
Fails in the using with
{"Could not find an IE window matching constraint: Any. Search expired
after '30' seconds."}
The example code provided for WatIn has the code first creating an instance of IE and then attaching to it. I can't help but think that WatIn can attach to a running instance of a browser, but WatIn must first create that instance.
That won't meet my needs.
My final attempt was to use System.Windows.Automation to get an open Internet Explorer window and try to work with it. While I get the window, all I can get access to are the Windows and Transform patterns. Hence, I could potentially automate the resizing of the browser window and close it. But, I can't get the DOM or anything useful.
There are a few articles out there about using Interop with MSHTML or SHDocVw, but nothing super helpful.
I would appreciate any guidance anyone can provide on using whatever tools possible for a .NET C# Windows Forms or Console application to use to somehow connect to an independently opened browser window on the same Windows machine and automating it.
I've been using WatiN succesfully for this. A console app with Program.cs that looks like the following works for me:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using WatiN.Core;
namespace WatinTest
{
class Program
{
[STAThread]
static void Main(string[] args)
{
var ie = IE.AttachTo<IE>(Find.ByTitle(new Regex(".*")));
foreach (var div in ie.Divs)
{
Console.WriteLine(div.IdOrName);
}
Console.ReadLine();
}
}
}
This is with Windows 10 and WatiN 2.1.0.
Related
I want to click on the app menu button on the android emulator device.andoid emulator home screen
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium;
namespace AppTesting
{
[TestClass]
public class UnitTest1
{
AndroidDriver<AndroidElement> driver;
[TestMethod]
public void Scroll_Method()
{
DesiredCapabilities cap = new DesiredCapabilities();
cap.SetCapability("deviceName", "TestingMachine");
cap.SetCapability("platformversion", "7.0");
cap.SetCapability("platformName", "Android");
driver = new AndroidDriver<AndroidElement>(new Uri("http://127.0.0.1:4723/wd/hub"), cap);
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
driver.PressKeyCode(AndroidKeyCode.Keycode_MENU);
}
}
}
but when I run the code I get the following error
Message: Test method AppTesting.UnitTest1.Scroll_Method threw
exception: System.InvalidOperationException: An unknown server-side
error occurred while processing the command. Original error: The
desired capabilities must include either an app, appPackage or
browserName
I am new to mobile automation testing, what I don't understand at this point is why I need to provide an app-package and app-activity even when I am clicking on the button that is present on the home screen. If it is necessary to provide than what is the "app-package" and "app activity" for clicking the menu button.
Note:
Also, help on how to scroll through the android native application menu. Thanks in advance. Solution to this single problem will be an answer to many other problems that I am facing right now. I am new to mobile automation testing using Appium with C# in visual studio 2017
As a newbie you can try Appium Studio.
They have the object spy feature which would be easier for you to identify the elements.
And its possible to swipe the screen without providing the app-activity.
client.swipe(swipeDirection,offset,timeToSwipe);
I am using Selenium to simulate a user to automate some legacy software. The software works only with IE6 (I'm using IE11 in compatibility mode) and is a bit crap.
There is a point in the software where the Windows Security dialog appears. This requires credentials before the user/simulator can proceed.
I'm using IAlert.SetAuthenticationCredentials to try and populate the dialog but this doesn't seem to work. To move on from this, I can enter the details manually, but then Selenium seems to thing the main browser window has been closed:
Currently focused window has been closed.
The WindowHandles collection at this point is empty, but the browser window is still open, and has rendered the correct page.
What's going on here?
UPDATE
The answers provided are suggestions on how to handle the dialog. I'm wondering why Selenium thinks the browser window is closed when in fact it is still there.
It is not possible to interract with native windows via selenium. The way to deal with your issue is for example to use analogue of Robot in Java. Since you are using C# there is a simulator here https://www.codeproject.com/Articles/28064/Global-Mouse-and-Keyboard-Library.
Example code would be like following:
// Simulate (Ctrl + C) shortcut, which is copy for most applications
KeyboardSimulator.SimulateStandardShortcut(StandardShortcut.Copy);
// This does the same as above
KeyboardSimulator.KeyDown(Keys.Control);
KeyboardSimulator.KeyPress(Keys.C);
KeyboardSimulator.KeyUp(Keys.Control);
There are also Mouse simulators, so with this framework it will be possible to enter the required values in window and accept it.
Try to switch to that alert by,
var alert = driver.SwitchTo().Alert();
alert.SetAuthenticationCredentials("Username", "Pwd");
alert.Accept();
I have tested it and it works for IE11, selenium v3.1.0
Ref: https://seleniumhq.github.io/selenium/docs/api/dotnet/html/M_OpenQA_Selenium_IAlert_SetAuthenticationCredentials.htm
Suggesstion 1-Go to internet explorer settings->security settings-> user authentication-> select automatic login with current username and password.
Suggesstion 2- if your application has access to it's API, then login via API, get the authentication token and set the auth.token in browser cookie.
Currently, I'm trying to run my Selenium tests on Safari using Selenium Grid and RemoteWebDriver. This is my setup:
Mac OS Sierra 10.12.6 as a machine for running tests.
Selenium server 3.5.3.
Safari 11.
C# Selenium WebDriver and Selenium Support (latest version).
I'm using port forwarding on my host OS (Windows 10) to forward requests to Mac, running on my Virtual Machine. On my Mac I have Selenium Grid hub, which I run like this:
java -jar selenium-server-standalone-3.5.3.jar -role hub -port 4723
Also, there is a node:
java -jar selenium-server-standalone-3.5.3.jar -role node -hub http://10.0.2.15:4723/grid/register
In code, I start my driver like this:
SafariOprions options = new SafariOptions();
IWebDriver driver = new RemoteWebDriver(new Uri(hubURL), options.ToCapabilities());
My tests are running fine with current setup. But when it comes to clicking a link with attribute target='_blank' I'm starting to face some troubles. For other drivers, which I run locally, I can switch tab without any trouble: I'm getting driver.WindowHandles before I click a link, then I click a link and again retrieve Window Handles to compare with previous handles. After that I use driver.SwitchTo().Window(newHandle) and everything is ok.
But when it comes to RemoteWebDriver (or SafariDriver from Apple, I cannot say more precisely) I'm always getting only one Window Handle, even if the new tab is opened and i can see it.
I'm trying to avoid switching tab with "Command + T" as one of solutions suggested, because my tests are meant to be run on all browsers (Chrome, Firefox, Opera, Edge, Safari) and this wont work.
UPDATE: I've tried running Chrome and other browsers in Selenium Grid via RemoteWebDriver and I can say that this is not an issue of RemoteWebDriver. Next, I've installed Visual Studio for Mac and rewrite several things to run my tests without Selenium Grid, just using this code:
//if memory serves, just like this
SafariOptions options = new SafariOptions();
SafariDriver driver = new SafariDriver(options);
But, unfortunately, this didn't help. Driver navigated me to the page, clicked the link and opened a new tab, but without any switch. When I checked for driver.WindowHandles I've only got one, although there was two visible tabs. Neither driver.SwitchTo().ActiveElement nor driver.SwitchTo().Frame(hardcoded_frame_name) doesn't seem to work. Pretty long waits (for 60 seconds after opening the link and another one after that) aren't working too. Now I think that this is really a bug and I will try to report this to Apple as soon as I can.
But for now, maybe someone has a fancy workaround for this?
As we discussed in the comments, it seems to be a timing issue. So we will induce
WebDriverWait to sync up with the trailing Browser instance. I am providing a code block as a solution through Selenium-Java, consider implementing it in C# and update me if it works for you.
driver.get("http://www.google.com");
System.out.println("Page Title is : "+driver.getTitle());
String parent_window = driver.getWindowHandle();
((JavascriptExecutor) driver).executeScript("window.open('http://facebook.com/');");
WebDriverWait wait = new WebDriverWait(driver,3);
wait.until(ExpectedConditions.numberOfWindowsToBe(2));
Set<String> allWindows_1 = driver.getWindowHandles();
ArrayList<String> tabs = new ArrayList<>(allWindows_1);
driver.switchTo().window(tabs.get(1));
wait.until(ExpectedConditions.titleContains("Facebook"));
System.out.println("First Child Handle : "+driver.getTitle());
I could help you with the Java version:
After the actions done, do this below.
//Store the parent window
String parentWindow = driver.getWindowHandle();
//Open a new Windows(Mailtrap)
String a = "window.open('https://mailtrap.io/signin','_blank');";
((JavascriptExecutor)driver).executeScript(a);
//This Thread.sleep is useful with Safari. Do not remove.
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Take control over new browser
for(String handle: driver.getWindowHandles()){
driver.switchTo().window(handle);
}
i have issue in cross browser testing using codedui.
Using below code,
Process.Start("firefox", url);
BrowserWindow.CurrentBrowser = "firefox";
Browser = BrowserWindow.Launch(new System.Uri(url));
Keyboard.SendKeys("^{0}");
all code developed in IE . but now i have to execute code in firefox or chrome.I am going to execute the code in forefox.I am using this code here
Browser = BrowserWindow.Launch(new System.Uri(url));
in this line getting error like "An error occurred while connecting to Firefox".how to resolve this issue?I installed selenium components also. if i remove this line I am getting diffrent error like " Unable to find browser"...Please help.
Out of the box Visual Studio doesn't support cross browser CodedUI testing.
You're going to need to install Selenium components to allow for cross browser testing in Visual Studio.
Details on that can be found here:
http://blogs.msdn.com/b/visualstudioalm/archive/2012/10/30/introducing-cross-browser-testing-with-coded-ui-tests.aspx
Selenium components can be found here:
http://visualstudiogallery.msdn.microsoft.com/11cfc881-f8c9-4f96-b303-a2780156628d
Looks like CodedUI doesn't support playback on very many different browsers http://msdn.microsoft.com/en-us/library/dd380742(VS.100).aspx
There are some other tools out there http://watin.org/ is one, but I can't find anything myself that will really solve your problem.
Try
BrowserWindow.CurrentBrowser = "firefox";
BrowserWindow WebApp;
WebApp.CopyFrom(BrowserWindow.LaunchUrl(new System.Uri(url)));
I set up something similar to the following and it works well (I hand code everything, bypassing the UIMap).
public class WebApp : BrowserWindow
{
private string _url;
public WebApp(string url)
{
//define search properties using this keyword so the web application can be treated as a browser
_url = url;
BrowserWindow.CurrentBrowser = "Chrome";
this.CopyFrom(BrowserWindow.Launch(new Uri(url));
}
}
You can overload the constructor, of course, by adding a parameter for the browser to use or whether to start up the browser or not.
By setting up the web application as a BrowserWindow, you can have one open and ready and the playback engine should find it. I find this helps when working on tests (in IE).
Just a reminder, you do need the Selenium plug-in and that plug-in will only work for playback, not recording.
Cheers!
In our environment, we set up the Launch() method by doing the following:
public void LaunchBrowser(string uri)
{
BrowserWindow.CurrentBrowser = "firefox";
BrowserWindow myBrowser = BrowserWindow.Launch(new System.Uri(uri));
}
One thing to note is that if there is a firefox process already running in the background, the WebDriver will not launch a new instance, so be sure that all instances of firefox are shut down before the LaunchBrowser() is called. I've found that there are Java plugins that can keep it running in the background, so try to disable those that you don't need. Another good place to look, if you check your Task Manager and this is the case, is here.
I'm trying to use Selenium WebDriver to automatically login in to a site with a user-name and password. I've done my research and I don't believe this feature is supported by WebDriver, so I need to find another way. The site I'm trying to automate logging into is located here.
When prompted to login a popup window comes up that doesn't seem to be part of the browser. I'm using Firefox and Chrome. It seems Windows API may be required? I already tried passing the credentials in the URL but that didn't work. Also tried sendkeys, but received a Windows exception that the application was not accepting Windows messages. I also tried switching the current handle using driver.windowhandles but the popup doesn't seem to be a new handle.
Does anybody have any ideas? I'm kinda stuck. The preliminary code to get to the popup window is:
IWebDriver driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://www.portal.adp.com");
string currentWindow = driver.CurrentWindowHandle;
IWebElement userLogin = driver.FindElement(By.Id("employee"));
userLogin.Click();
The popup you are seeing is prompted by web server and is a authentication prompt. Selenium doesn't support this operation.
One of the way to handle this limitation is to pass user and password in the url like like below:
http://user:password#example.com
More info available here : http://aleetesting.blogspot.in/2011/10/selenium-webdriver-tips.html
I wanted my answer out there because I think I've solved it. This answer does not require passing the credentials through the URL (for those of you that are unable to like me). It also does not require any custom Firefox Profiles or extensions to be installed or included with the solution or installed onto the browser eliminating cross-machine compatibility issues.
The issue with me was that the authentication could not be completed via passing the credentials through the URL because the login was behind a proxy.
So, I turned to windows automation toolkits and found AutoIT. Using AutoIT and Selenium, you can login automatically by sending the username and password to the windows dialog that appears. Here's how (note the steps below are for c#:
1 - Download AutoIT from http://www.autoitscript.com/site/autoit/downloads/
2 - Add the autoit .dll to your project references.
Right click on references, select Add Reference. Next click the browse button and browse to the dll location (most default installations it will be c:\Program Files (x86)\AutoIt3\AutoItX\AutoItX3.dll), and add to project.
3 - use AutoIT and Selenium like this (assuming your web driver is already initialized):
//Initialize AutoIT
var AutoIT = new AutoItX3();
//Set Selenium page load timeout to 2 seconds so it doesn't wait forever
Driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(2));
//Ingore the error
try
{
Driver.Url = url;
}
catch
{
return;
}
//Wait for the authentication window to appear, then send username and password
AutoIT.WinWait("Authentication Required");
AutoIT.WinActivate("Authentication Required");
AutoIT.Send("username");
AutoIT.Send("{TAB}");
AutoIt.Send("password");
AutoIT.Send("{ENTER}");
//Return Selenium page timeout to infinity again
Driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(-1));
Anyway, that's it, and it works like a charm :)
Also note that there are some special characters that need to be escaped in AutoIT using the sequence "{x}". For example, if your password is "!tRocks", you'd need to pass it into AutoIT as "{!}tRocks".
Happy automating.
FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference("network.http.phishy-userpass-length", 255);
profile.SetPreference("network.automatic-ntlm-auth.trusted-uris", hostname);
Driver = new FirefoxDriver(profile);
hostname is your URL (example.com) then try to
Driver.Navigate().GoToUrl(http://user:password#example.com);
I just got done working on a prototype project that is supposed to handle exactly this kind of situation.
It utilizes BrowserMob, a popular open source proxy, to perform the authentication.
SeleniumBasicAuthWrapper Hope it helps! It is still a work in progress, but hopefully we'll get any kinks or defects ironed out in the near future.