C# not able to get console Logs from PhantomJSDriver (Selenium) - c#

I'm using Selenium in C# with the PhantomJS Driver.
I need to click specific coordinates on a website, that works with using Javascript (im using the ExecutePhantomJS(string script) function of the selenium phantomjs driver). I also need to capture the network traffic. I used browsermob earlier to do that, but for now i cant use it because i also need to use another proxy. So i solved it like that until now:
//Hide CMD of PhantomJS.exe
var driverService = PhantomJSDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
//Initialize Driver and execute Network Script to capture traffic
driver = new PhantomJSDriver(driverService);
driver.ExecutePhantomJS(networkScript);
//Call URL
driver.Navigate().GoToUrl(url);
This is the networkScript:
string networkScript = "var page = this; page.onResourceRequested = function(req) { console.log('received: ' + JSON.stringify(res, undefined, 4)); }; page.onResourceReceived = function(res) { console.log('received: ' + JSON.stringify(res, undefined, 4)); };";
The good thing:
URL is called and all network traffic is logged into the console of the PhantomJS.exe.
But I dont know how I can get these console logs now in my C# code (I need to get specific things like URLs etc.. out of the network log).
I already read the whole afternoon but couldn't find a solution until now. Some of the things I already tried:
1) Tried to use PhantomJSOptions, there u can set LoggingPreferences and later i called driver.Manager().Logs.GetLog(LogType), but there were none of the console logs
2) Dont use console.log inside networkScript. I used require('system').stdout.write(...). It was also logged into console but I cant get the standard output stream of the phantomjs.exe from my C# code.
...
I really dont know how i could solve the problem.
One way would be to log into a .txt file instead of console, but it is very much text and later there will be many opened drivers, so I want to avoid that because then i will have very much and big .txt files

Related

C# Selenium Edge Driver unable to download file - Keep file prompt shows up

I am using C# with Selenium for QA automation, and I am having issues with downloading an .xml file, because a prompt is always showing up asking if I want to keep the file. It also opens a second tab to execute the download, closing it after the prompt shows up.
[keep file prompt][1]
Using Chrome I do not see this behavior.
I searched all over and could not find a EdgeOptions() and/or AddArguments() capable of taking care of this issue.
Any ideas?
You need to use JS to interact with elements in another browser. I have had such experience and I used if else statement in my method to handle that problem. Just look trough the Selenium documentation, JS with selenium examples and so long so for.
Just add this to your OneTimeSetup method. Make sure to run Visual Studio as administrator. This works since Edge 105+:
public void SetEdgeXmlDownloadPolicy()
{
var keyName = "Software\\Policies\\Microsoft\\Edge\\";
var valueName = "ExemptFileTypeDownloadWarnings";
var valueData = #"{""domains"": ["" * ""], ""file_extension"": ""xml""}";
var currentUser = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
var currentKey = currentUser.OpenSubKey(keyName, true);
if (currentKey == null)
currentKey = currentUser.CreateSubKey(keyName);
if (currentKey.GetValue(valueName) == null)
currentKey.SetValue(valueName, valueData);
}

WatiN doesn't find anything

I'm new to C# and I'm trying to do an application that automatize Internet Explorer.
When I click a button, the application does :
using ( var Browser = new IE())
{
Browser.GoTo("http://testweb.com");
Browser.TextField(Find.ByName("username")).TypeText("User");
Browser.TextField(Find.ByName("password")).TypeText("Pass");
}
But it doesn't write anything. It navigates to the web but...
Try this:
IE ie = null;
ie = new IE();
ie.GoTo("Link");
ie.WaitForComplete();
At least to get started.
For the other bit, you need to get an exact identification and then you can tell WaTiN to interact with it.
Textfield userTextBox = ie.Textfield(Find.ByName("name"));
userTextBox.TypeText("user");
This may seem banal but now you can add a peek definition in your code and see if "userTextBox" gets found by name. If it doesn't you need to find it through another method (ID or class).

How to maintain browser state between invocations under Selenium and Firefox?

Context: Microsoft Azure VM; VS2015 Community; C#; Selenium.WebDriver.2.52.0; Firefox 44.0.2; Console (i.e. not running under IIS)
How is state maintained under Firefox using Selenium. Programmatically I go to one page, enter login details, and traverse to a second domain. Then I close the browser, re-open and try to go to a link on the second domain. I end up at the login page again being requested for login details.
When doing this interactively, the browser remembers that I logged in on the first page and automagically transports me the second domain's page.
I have set up a webserver profile in C:\Users\Bruce\AppData\Roaming\Mozilla\Firefox\profiles.ini as
[General]
StartWithLastProfile=1
[Profile0]
Name=default
IsRelative=1
Path=Profiles/eracklz4.default
[Profile1]
Name=webserver
IsRelative=1
Path=Profiles/webserver.default
Default=1
So one would think that even if I didn't explicitly state that I wanted to use the webserver profile, nevertheless, it would choose that profile and work with it. Just in case I go on to state it explicitly
var seleniumProxy = new Proxy();
seleniumProxy.HttpProxy = "localhost:" + port; // port provided by BrowserMob Proxy
...
FirefoxBinary fb = new FirefoxBinary(#" C:\Program Files (x86)\Mozilla Firefox\firefox.exe");
FirefoxProfileManager fpm = new FirefoxProfileManager();
FirefoxProfile fp = fpm.GetProfile("webserver");
fp.DeleteAfterUse = false;
fp.SetProxyPreferences(seleniumProxy);
IWebDriver wd = null;
try
{
wd = new FirefoxDriver(fb, fp);
}
catch (Exception exc)
{
System.Diagnostics.Debug.Print(exc.Message);
}
IJavaScriptExecutor js = wd as IJavaScriptExecutor;
ExistingProfiles in the FirefoxProfileManager lists webserver so the fpm var is not null.
At this point, I'm getting pretty confident that the session's data will be persisted, because when I look at fpm in the debugger, Non-Public members -> profiles -> [1] -> Value is given as "C:\\Users\\Bruce\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles/webserver.default".
Having transferred the profile data from fpm to fp, with the .GetProfile method, the ProfileDirectory property of fp reads as null, Non-Public members -> profileDir is also null and Non-Public members -> sourceProfileDir is "C:\\Users\\Bruce\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles/webserver.default"
By rights, therefore, one should expect passwords to be persisted to the webserver profile, especially when one explicitly saves data to the profile with regular calls to fp.WriteToDisk();.
However! The last time I ran the code, I got a anonymous.359f853715d5418c87c7393c629dcb1a.webdriver-profile in C:\Users\Bruce\AppData\Local\Temp
Granted, there did appear to be some activity in the Roaming profile. However, the password for the login page was not persisted.
What's happening here? Is session data persistable in Selenium + Firefox, or was there a design decision somewhere that no matter how you specified it, no state would be saved? Am I wanting to do something that is intrinsically forbidden?
NEXT DAY
Added the following code after reading a StackOverflow posting from 2014 discussing similar issues. However, I'm still seeing a temporary profile being created in AppData\Local\Temp. And no changes were made to the Roaming profile. Problem not solved.
A LITTLE LATER
Am currently experimenting with Google Chrome instead of Firefox, viz
ChromeOptions co = new ChromeOptions();
string tfn = #"C:\Temp";
co.AddArgument("user-data-dir=" + tfn);
co.Proxy = seleniumProxy;
IWebDriver wd = new ChromeDriver(co);
I'm not very confident that this will make much difference. Notably, I can't figure out how to set or get the name of the profile folder created in Temp. The above code creates a Default folder, but there's no mention of that in the properties view in VS2015C.
FINALLY
Surprise, surprise, that actually worked. Bye bye Firefox. Hello Google Chrome. Seems there's enough session data stored to make the traversal to the second site feasible. Will probably change the directory away from Temp and have it client-specific. Kudos to the folk at ActiveState Python.

How can I enter an email address into text input field in Edge using Selenium WebDriver?

I have the following program:
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Edge;
namespace ConsoleApplication1
{
static class Program
{
static void Main()
{
//var driver = new ChromeDriver();
var driver = new EdgeDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(20));
driver.Navigate().GoToUrl("http://www.cornelsen.de/shop/registrieren-lehrer");
driver.FindElement(By.Id("email")).SendKeys("dummy#user.de");
}
}
}
When I run this in Chrome or any other browser aside from Edge, then the email adress is entered correctly. But if I try the same thing in Edge, the "#" character is missing. The field displays only "dummyuser.de".
Any idea what I can do?
As a workaround, you can set the input value directly via ExecuteScript():
IWebElement email = driver.FindElement(By.Id("email"));
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
string script = "arguments[0].setAttribute('value', 'arguments[1]');";
js.ExecuteScript(script, email, "dummy#user.de");
Or, what you can do is to create a fake input element with a predefined value equal to the email address. Select the text in this input, copy and paste into the target input.
Not pretty, but should only serve as a workaround:
// create element
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
string script = #"
var el = document.createElement('input');
el.type = 'text';
el.value = 'arguments[0]';
el.id = 'mycustominput';
document.body.appendChild(el);
";
js.ExecuteScript(script, "dummy#user.de");
// locate the input, select and copy
IWebElement myCustomInput = driver.FindElement(By.Id("mycustominput"));
el.SendKeys(Keys.Control + "a"); // select
el.SendKeys(Keys.Control + "c"); // copy
// locate the target input and paste
IWebElement email = driver.FindElement(By.Id("email"));
email.SendKeys(Keys.Control + "v"); // paste
It wasn't as easy as I thought after all. Issues with alecxe's answer:
arguments[0].setAttribute('value', '...'); works only the first time you call it. After calling element.Clear();, it doesn't work any more. Workaround: arguments[0].value='...';
The site doesn't react on the JavaScript call like it would on element.SendKeys();, e.g. change event is not invoked. Workaround: Send the first part of the string up to the last "forbidden" character via JavaScript, the rest via WebElement.SendKeys (in this particular order, bc if you do another JavaScript call to the same field after SendKeys(), there will occur no change event either).
I also realized that there are more "forbidden" characters in Edge, e.g. accented or Eastern European ones (I'm Central European). The problem with 2. is that the last character might be a forbidden character. In this case, I append a whitespace. Which of course affects the test case behavior, but I haven't had any other idea.
Full C# code:
public static void SendKeys(this IWebElement element, TestTarget target, string text)
{
if (target.IsEdge)
{
int index = text.LastIndexOfAny(new[] { '#', 'Ł', 'ó', 'ź' }) + 1;
if (index > 0)
{
((IJavaScriptExecutor) target.Driver).ExecuteScript(
"arguments[0].value='" + text.Substring(0, index) + "';", element);
text = index == text.Length ? Keys.Space : text.Substring(index);
}
}
element.SendKeys(text);
}
This problem used to occur in old browsers. Apparently it returned in Edge.
You can try sending the string in pieces
IWebElement email = driver.FindElement(By.Id("email"));
email.SendKeys("dummy");
email.SendKeys("#");
email.SendKeys("user.de");
Or try using # ASCII code
driver.FindElement(By.Id("email")).SendKeys("dummy" + (char)64 + "user.de");
Try to clear the Text field first.
try following
driver.FindElement(By.Id("email")).clear().SendKeys("dummy#user.de");
Have you tried Copy Paste?
Clipboard.SetText("dummy#user.de");
email.SendKeys(OpenQA.Selenium.Keys.Control + "v");
Hope it could help.
I just added one extra line to click on text field and then send keys, I tried this and its working for me.
Code is written in java, you can change that to any other, if you want.
//INITIALISE DRIVER
WebDriver driver = null;
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.navigate().to("http://www.cornelsen.de/shop/registrieren-lehrer");
driver.manage().window().maximize();
//CLICK EMAIL FIELD, JUST TO HAVE FOCUS ON TEXT FIELD
driver.findElement(By.id("email")).click();
driver.findElement(By.id("email")).sendKeys("dummy#user.de");
I'm the Program Manager for WebDriver at Microsoft. I just tried to reproduce your issue on my home machine (Windows 10 build 10586) and couldn't reproduce. Your exact test entered the '#' symbol fine.
You should check if you have the latest version of Windows 10 and WebDriver. If you hit the Windows key and type "winver" and hit enter it'll open a popup with the Windows version info. You want it to say
Microsoft Windows
Version 1511 (OS Build 10586.104)
This is the latest version of Windows 10 released to the public. If you have this version you'll also need the corresponding version of WebDriver found here:
http://www.microsoft.com/en-us/download/details.aspx?id=49962
Note that if the build is 10240 that you're on the original release build. Our November update added substantial support for new features (like finding elements by XPath and more!) along with bug fixes which might explain your issues.
Lastly I should note we have an Insiders release as well for WebDriver to match with the Insiders program. If you're subscribed to the Insiders program and want to see the newer features and bug fixes for WebDriver you can find the download here:
https://www.microsoft.com/en-us/download/details.aspx?id=48740
Note that it currently supports build 10547 which was actually before the November update. It'll be updated very shortly (next couple of days) to support the latest Windows Insiders flight, build 14267.
Sorry but I not agree with the last comment (Program Manager for WebDriver at Microsoft). I can reproduce the problem. This is my configuration:
Target Machine (Hub node where tests are run):
Win 10 build 10585.104
MS Edge 25.10586.0.0
MS EdgeHTML 13.10586
Selenium framework:
SeleniumHQ (for Java): 2.48.0
I am using Selenium Grid to run my suite. In this case, I was only doing conceptual test of Egde implementing a basic test:
1. Start Hub in local machine (Win 7) opening console (administrator privileges)
2. Register Node in Hub in target remote machine (Win 10 build 10585) opening console (in this case without administrator privileges because in other way edge hangs when create new session).
Setting up my grid and checking that everything is ok when I try to write my account name in login page I can not see the # and my basic test fails (wrong credentials).
I have introduced # by hand in the moment edge is opened (interrupt point) and I can see symbol.
I have sent "###############" to the text field and I can not see any. In summary, I have tried many things and I can not see #
When I started with Web Automation Testing using Selenium (Java) I remember this behaviour in old versions of Firefox and Chrome. I not really sure which one but it was reproducible in old version.
This partial basic code (implementated with pageobject) IS WORKING with Firefox 35.0 and Chrome 48.0.2564.109 but NOT IS WORKING with Edge's version I put at the beginning of my comment.
WebElement element = WebDriverExtensions.findElement(context, By.cssSelector("input[name='username'][type='email']"));
element.clear();
element.sendKeys(email);
Front Developers are using AngularJS and are validating user's text input to match with a welformatted email:
I afraid that current Edge version does not support sendkeys with this kind of character, maybe the problem is front on-line validation and Edge has to suits these situations because they are really common.
Best regards
None of the above worked for me with the version 2.52. This worked for me :
EdgeDriver edgeDriver = new EdgeDriver("folder of my edge driver containing MicrosoftWebDriver.exe");
IJavaScriptExecutor js = _edgeDriver as IJavaScriptExecutor;
js.ExecuteScript("document.getElementById('Email').value = 'some#email.com'");
Make sure to replace the ".getElementById('Email')" with what you should use to find your field with javascript and replace the "folder of my edge driver containing MicrosoftWebDriver.exe" with the correct path.
Good luck!

How do I get back results running a VB Script from C#?

I want to be able to call VB scripts from C#, which is easy enough, but I need to be able to get back the results from these scripts at times. Should I use the method referenced with something to read back, or should I use a different method? I've found a method to getting data back from powershell scripts using Runspaces and Pipelines, but I don't know enough about this technology to know if it will work with VB scripts as well. Ideally, I'd like to do something similar to the powershell method where I can just pass in the contents of the script without needing to reference an external file and get back the results. Can anyone tell me how to do this? Thanks.
Here's a pretty simple way to do it by listening to an event:
Process vbsProcess = new Process();
vbsProcess.StartInfo.FileName = "yourscript.vbs";
vbsProcess.StartInfo.UseShellExecute = false;
vbsProcess.StartInfo.RedirectStandardOutput = true;
vbsProcess.OutputDataReceived += new DataReceivedEventHandler(YourOutputHandler);
vbsProcess.Start();
vbsProcess.WaitForExit();

Categories