Selenium with headless chrome - javascript

I have testing environment which is perfectly working with chrome driver in desktop mode. I am using some javascript injections (everything works) f.e.:
public static void ForceFillInput(this Driver driver, string selector, string value)
{
var javaScriptExecutor = (IJavaScriptExecutor)driver.webDriver;
javaScriptExecutor.ExecuteScript($"$(\"{selector}\").val(\"{value}\")");
}
but when i want to run it in headless mode
AddArguments("--headless")
it will just fail on
"$ is not defined"
Can somebody help me how to inject js/jquery into headless solution?
M.

your Javascript snippet used jQuery api. In modern web development, we put Javascript at the end of HTML page to let browser to load javascript at last, so that static resources (like picture/image/text content) can display earlier as possible, withing this way to improve user experience when user open website.
I think your page also put jQuery at the end to load, try add some wait/sleep before ExecuteScript to wait browser complete load jQuery.

It looks like the shorthand for JQuery is not yet created at the time your script is executed.
Use a waiter to wait for JQuery and for the selector to be found:
public static void ForceFillInput(this Driver driver, string selector, string value)
{
string JS_SET_VALUE =
"var e; return !!window.$ && (e = window.$(arguments[0])).length > 0 && (e.val(arguments[1]), true);";
new WebDriverWait(driver, TimeSpan.FromSeconds(60))
.until(ctx => (bool)((IJavaScriptExecutor)ctx).ExecuteScript(JS_SET_VALUE, selector, value));
}

Related

Launch .exe with html link [firefox]

I am currently developing an application in php / js / html and I would like to launch an application made in C # via a html button (no download) however I use Mozilla Firefox and the only solution I found is a script featuring ActiveXObject which is only used by IE apparently.
You can use the Firefox command line options of -url
"C:\Program Files\Mozilla Firefox\firefox.exe" -url "https:\\www.stackoverflow.com"
or
Use selenium Webdriver, this can launch the browser to any url you specify and can fill any form on the page with any details you specify and press any buttons that you can find.
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;
class HelloSelenium
{
static void Main()
{
using (IWebDriver driver = new FirefoxDriver())
{
WebDriverWait wait = new WebDriverWait(driver);
driver.Navigate().GoToUrl("https://www.stackoverflow.com/ncr");
driver.FindElement(By.Name("q")).SendKeys("Vote Up" + Keys.Enter);
}
}
}

Synchronization problems with automated testing Angular website with Selenium and testing issues with Internet Explorer.

I am trying to write an automated test program for one of my website using Selenium WEbDriver. I am having some problems when doing the test on Internet Explorer. The website that I am trying to test is built in AngularJS. I will explain my problems in detail.
Here, is the code that waits until Angular has finished processing.
private static ExpectedCondition angularHasFinishedProcessing() {
return (ExpectedCondition<Boolean>) driver -> {
String hasAngularFinishedScript = "var callback = arguments[arguments.length - 1];\n" +
"var el = document.querySelector('html');\n" +
"if (!window.angular) {\n" +
" callback('false')\n" +
"}\n" +
"if (angular.getTestability) {\n" +
" angular.getTestability(el).whenStable(function(){callback('true')});\n" +
"} else {\n" +
" if (!angular.element(el).injector()) {\n" +
" callback('false')\n" +
" }\n" +
" var browser = angular.element(el).injector().get('$browser');\n" +
" browser.notifyWhenNoOutstandingRequests(function(){callback('true')});\n" +
"}";
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
assert javascriptExecutor != null;
String isProcessingFinished = javascriptExecutor.executeAsyncScript(hasAngularFinishedScript).toString();
return Boolean.valueOf(isProcessingFinished);
};
}
private void waitForAngular() {
WebDriverWait wait = new WebDriverWait(driver, 15, 100);
wait.until(angularHasFinishedProcessing());
}
And here is the code that instantiates WebDriver for Internet Explorer.
System.setProperty("webdriver.ie.driver",
new File("H:/libraries/webdrivers/IEDriverServer.exe").getAbsolutePath());
DesiredCapabilities d = DesiredCapabilities.internetExplorer();
// To bypasse the Protected Mode settings of IE
d.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
driver = new InternetExplorerDriver(d);
driver.manage().timeouts().setScriptTimeout(30, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.get("https://arandomangularjsapp.com"); // Let's suppose this
I had to bypass the Protected Mode settings (shown in above code) because I was constantly getting this Exception
Caused by: org.openqa.selenium.WebDriverException: Unexpected error launching Internet
Explorer. Protected Mode must be set to the same value (enabled or disabled) for all
zones. (WARNING: The server did not provide any stacktrace information)
though I made sure that protected mode was enabled and same values were set for all zones.
Now comes the real issue I am having. Look at this block of code,
waitForAngular();
WebElement el = driver.findElement(By.xpath("//div[#class='events-list__event-info' and #id='48040']" +
"//following-sibling::div[#class='events-list__event-buy']/a"));
if(driver.toString().toUpperCase().contains("INTERNETEXPLORER"))
el.sendKeys(Keys.ENTER);
else
el.click();
waitForAngular();
webElement = driver.findElement(By.xpath("(//div[#class='ticket u-cf ng-scope'])[1]//select"));
select = new Select(webElement);
select.selectByIndex(1);
My first question, the way I am trying to wait for Angular app to get ready by calling waitForAngular(), is it a good way? In my program I even had to use Thread.sleep() so many times in order to let elements to properly render before I could invoke actions on them. It would be great if you guys can suggest me a proper way to use Selenium WebDriver along with Angular App.
Now let's talk about my second issue. I had to completely disable Protected Mode from Internet Explorer's options in order to run the program. Otherwise, I would get this exception,
Caused by: org.openqa.selenium.JavascriptException: JavaScript error in async script. (WARNING: The server did not provide any stacktrace information)
I get this exception when trying to execute waitForAngular(). What could be causing this? Is there any way by which I could keep the Protected Mode enabled and still be able to execute that script inside angularHasFinishedProcessing() method?
Finally, my third problem is related to click action not being triggered. Forget about the previous issues for a second. I disabled IE's Protected Mode, so my program starts IE without throwing any exception. The program successfully finds the first element as shown in the code above. But, the click action is not triggered, browser thus doesn't navigate to next page, and the program fails to find the second element. As a workaround I even tried el.sendKeys(Keys.ENTER); but it didn't work.** So, am I having this problem because I bypassed/disabled Protected Mode? Or, is there something else that I am not being able to see?**
I run tests on IE, Opera, Chrome and Firefox and the problem seems to occur only in IE. Any sort of help, suggestions or guidelines are highly appreciated.
Thank You.

programmatically print a web page

I am making a program to automatically go to a website and print a page, Can't seem to make it work, I tried selenium chrome driver, problem is it doesn't work. i tried action.sendkeys keys ctrl + shift + p to no avail, the biggest problem is print preview pop-up.
I tried sending JavaScript command: window.print(), but the print preview in chrome stands in my way, because you need to press enter. Is there a way in JavaScript to simulate the pressing of the ENTER key? Help would be appreciated.
Well, after a bit of research, I found this video, if you can add these switches: "--kiosk --kiosk-printing", to the chrome driver start, it would automatically skip the print preview prompt, just as shown in the video.
also, I tested this on the latest version of SRWare iron(fork of chromium), and it worked.
If you are using C# to make your program, then there is an easier solution:
private void Button1_Click(object sender, EventArgs e)
{
PrintHelpPage();
}
private void PrintHelpPage()
{
// Create a WebBrowser instance.
WebBrowser webBrowserForPrinting = new WebBrowser();
// Add an event handler that prints the document after it loads.
webBrowserForPrinting.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(PrintDocument);
// Set the Url property to load the document.
webBrowserForPrinting.Url = new Uri(#"http://www.google.com"); //This is what you want to change
}
private void PrintDocument(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
// Print the document now that it is fully loaded.
((WebBrowser)sender).Print();
// Dispose the WebBrowser now that the task is complete.
((WebBrowser)sender).Dispose();
}
Found the answer in Here, this uses the WebBrowser control to navigate to a specific Url, can be a local url or from the internet, and prints it using your default printer.
Maybe you could you use this approach that doesn't require windows forms, worked like a charm for me:
With C# use Chrome to covert HTML to PDF
var process = new System.Diagnostics.Process();
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
var chrome = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), #"Google\Chrome\Application\chrome.exe");
// use powershell
process.StartInfo.FileName = "powershell";
// set the Chrome path as local variable in powershell and run
process.StartInfo.Arguments = "$chrome='" + chrome + #"'; & $chrome --headless --print-to-pdf='c:\Users\" + Environment.UserName + #"\desktop\myReport.pdf' https://google.com";
process.Start();

Selector that confirms image loaded using Selenium Python API

I am looking for a way to confirm the image has actually loaded. Maybe JavaScript is an option? I am using right now WebdriverWait to simply force the wait on all images, then the actual src, then I finally run my tests after...
wait = WebDriverWait(driver, 10)
...
albums = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".albums .album img")))
albumslength = len(albums)-1
while albumslength > 0:
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ('.album:nth-child('+str(albumslength)+') img[src*="album-foo"]'))))
albumslength -= 1
...
This will at some point confirm "album-foo" exists in the <img src="http://www.album-foo/images/blah.jpg" of each album in albums. But it does not confirm that the image completed loading into view. I have searched high and low, anyone have a solution?
I am testing on Chrome and Firefox, so no phantom or IE restrictions, if the ideas grow into including JavaScript or related ideas that might have environment restrictions.
I am not that experienced with selenium, though I will give this a try.
If you want to check whether an image is loaded, I'd say use a boolean. Set the original value of this boolean let's say 'loaded' to false.
Then just call something like this, making sure it returns true the moment the image has loaded.
Boolean loaded = false;
WebDriver driver = new AnyDriverYouWant();
JavascriptExecutor js;
if (driver instanceof JavascriptExecutor) {
js = (JavascriptExecutor)driver;
}
loaded = (Boolean)js.executeScript("image.onload(function() { return true; });");

script to extract information from a webpage in a browser

Background
I have a network performance testing tool which after every test,displays all its results in a new results page. Below is my workflow to find the final value.(Details not relevant here but the html elements i am looking for might
1.Go to a section called "Data frame" ( which has a table with timestamp,transmit,recieve and percentage as columns) and get the time stamp when percentage first drops below 99.9
Here is a snippet of the "Data Frame" table
Data frame snippet
2.Go to another section called "Data throughput" ( table with timestamp, throughput as columns) and get the maximum value of throughput before the previously found timestamp.
After every test, i have to do this manually, but there should be someway to automate this.
Question
1.Is it possible to write a script ( maybe in javascript ) to automate my workflow for every new results page?
example algorithm
section = webpage.section_with_title("Data frames")
for each row in section
find first my_timestamp with percent < 99.9
done
section2 = webpage.section_with_title("Data Throughput")
for each row in section2
find max row.throughput if row.timestamp < my_timestamp
don
2.Once i write the script, how do i execute it in the web page?
3.Can i leverage the firefox/chrome developer console in some way ?
Note:I develop mostly in C,C++ and ruby with very basic experience in HTML and CSS. I have barely used javascript, but i have a vague idea that the browsers use it to handle the content of every page.
My thought process was to somehow execute the script through firefox console, and it will provide me with the results... is that difficult?
edit: since i am not familiar with the web development terms, ill put an a different choice of words...
1.i open up the results page
2.i open the console window of firefox/chrome
3.run my script(dont know what language).
4.i should get the result in the console. i do not want to modify the results page. i just need the result displayed to me(in the console, or to a text file).
Yes it's possible to do what you think using Javascript. Please look up XMLHttpRequest
Here is a way for you to start (in Java):
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class YourClass
{
private WebDriver webDriver = null;
public void open() throws Exception
{
webDriver = new FirefoxDriver();
}
public void close() throws Exception
{
webDriver.quit();
}
public void doStuff() throws Exception
{
WebElement element = webDriver.findElement(By.id(...));
...
// Alternatively, it might be easier to parse the entire
// page-source instead of searching elements in the DOM
String pageSource = webDriver.getPageSource();
...
}
}
You will need to download the following JAR files and add them in your project's class-path:
selenium-java-2.xx.0.jar (currently xx=39)
selenium-server-standalone-2.xx.0.jar (currently xx=39)

Categories