Is there any way to switch from headless to headed in the middle of a task in Selenium?
For example, I'm running some workflow headless, but in the middle I want the user to be able to push a button to see what the actual browser window looks like. How do I do that?
Not possible.
But it is possible to hide browser window from the screen :) :
driver.Manage().Window.Position =new Point(-2000, 0);
Unfortunately, switching between UI (headed) and HeadLess execution through selenium is not possible.
For example, Selenium creates an instance of browser of type WebDriver (either Firefox/Chrome/IE/HtmlUnit). Selenium can operate only on the instance it has created, and during creation time it will be defined if it is a UI test (Firefox/Chrome/IE) or Headless (HtmlUnit).
So, the design of Selenium prevents to switch between headless/UI execution in the middle of the test, as per your requirement.
Using xvfb you can do this. You can develop your tests using any driver, so, after configured the xvfb, you just need to use
xvfb-run tests
to run headless and if you don't want, you can run the tests without xvfb parameter.
A linux machine is required to use xvfb.
I've done this for one of my daily tasks - signin into firewall. It was a 2FA process, which required combo of browser interaction and a (random generated) token. For the first part a simple powershell script was running in headless mode, so when the site prompts for your token, it turns IE to visible and waits for user input. If such is provided, again switches to headless and finishes the process. The user is informed for success/fail of the operation with dialog message box.
You can start with such simple IE automation and optimize your .ps1 script later. The solution I was using back in the days:
$ie = new-object -ComObject "InternetExplorer.Application"
$requestUri = http://-your-site-here
# switch the browser headless mode on/off
#$ie.visible = $true
$ie.silent = $true
$ie.navigate($requestUri)
while($ie.Busy) { Start-Sleep -Milliseconds 100 }
# get DOM in order to interact
$doc = $ie.Document
$userInputId = "your-uname-id-here"
$doc.getElementsByTagName("input") | % {
if ($_.id -ne $null){
if ($_.id.Contains($userInputId)) { $_.value = "your-username-here" }
}
}
# can call JS events on elements
# like $btn.click()
Write-Verbose "Login Complete"
Related
I use the following code to run Tor controlled by Selenium in Lubuntu:
from selenium import webdriver
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
torexe = os.popen(r'/home/sergey/.local/share/torbrowser/tbb/x86_64/tor-browser_en-US/Browser/firefox')
profile = FirefoxProfile(r"/home/sergey/.local/share/torbrowser/tbb/x86_64/tor-browser_en-US/Browser/TorBrowser/Data/Browser/profile.default")
profile.set_preference('network.proxy.type', 1)
profile.set_preference('network.proxy.socks', '127.0.0.1')
profile.set_preference('network.proxy.socks_port', 9050)
profile.set_preference("network.proxy.socks_remote_dns", False)
profile.update_preferences()
driver = webdriver.Firefox(firefox_profile=profile, executable_path=r'/usr/local/bin/geckodriver')
driver.get("https://www.google.com")
...
It works, but in somewhat strange manner. Running it results in opening two windows, one window is Tor's while the other one being that of Firefox. Selenium controls the FF window only. The Tor window just sits there idly.
It is not to say that makes life unbearable, as I have said every thing works, but I am merely curious to know how to «make it completely right» (by this, I mean executing Selenium script in the only window of Tor).
I figured it out. In order to launch Tor using Selenium please run the following code (it still launches Firefox, this time without any Tor windows, but it uses the Tor service):
from selenium import webdriver
profile = webdriver.FirefoxProfile()
profile.set_preference('network.proxy.type', 1)
profile.set_preference('network.proxy.socks', '127.0.0.1')
profile.set_preference('network.proxy.socks_port', 9050)
profile.set_preference("network.proxy.socks_remote_dns", False)
profile.update_preferences()
driver = webdriver.Firefox(profile)
You may want to add the following three lines to verify the Tor service provides new IP for you Firefox instance:
driver.get("http://icanhazip.com")
current_IP = driver.find_element_by_css_selector("body > pre:nth-child(1)")
print(current_IP.get_attribute("innerHTML"))
This site icanhazip.com allows one to see his external IP without necessity to pass the abominable captcha test.
I have written a (Python) script using Selenium to automate some downloads from Box (I'm aware there is a Box API, but I'm accessing school resources and I'm not sure that the API would interact well with the school's external authentication). The script works using the Chrome driver in non-headless mode, but not in headless.
The step where I'm having issues is an attempt to query the status of downloads. I think my script is actually able to execute the downloads correctly: I've added some code from SO to disable security defaults that prevent downloading in headless mode.
I've successfully queried the download status using two methods (both executing Javascript in Chrome):
Selenium (Python) - waiting for a download process to complete using Chrome web driver
https://gist.github.com/ic0n/a38b354cac213e5aa50c55a0d8b87a0b
Both stop working when I switch to headless mode.
Here's the actual code I'm using:
# Headless Chrome disables downloads by default (at least as of 2017).
# https://stackoverflow.com/questions/45631715/downloading-with-chrome-headless-and-selenium
def enable_download_in_headless_chrome(driver, download_dir):
# add missing support for chrome "send_command" to selenium webdriver
driver.command_executor._commands["send_command"] = \
("POST", '/session/$sessionId/chromium/send_command')
params = {
'cmd': 'Page.setDownloadBehavior',
'params': {'behavior': 'allow', 'downloadPath': download_dir},
}
return driver.execute("send_command", params)
def get_top_download_state(driver):
"""Call this after running driver.get("chrome://downloads")."""
[state, percent, progress] = driver.execute_script("""
var item = downloads.Manager.get().items_[0];
var state = item.state;
var percent = item.percent;
var progress = item.progressStatusText;
return [state, percent, progress];
""")
return state, percent, progress
Errors for the first method say that downloads is not defined. Errors for the second method say that you can't get the shadowRoot property of null (presumably the query selectors are just finding nothing).
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();
}
I am running through an internal site with Behat and for the most part it is going really well. But the problem is that on certain parts of the site we have popup windows that come up to complete an action. In this case we hit a "Withdraw" button and a popup comes up to have you select a reason and save it.
In an ideal world, and if I had actually designed this app, the site wouldn't be using any popup windows. But I am the new guy who is supposed to implement automated functional tests (and I am learning how to do that from the ground up). So I don't really have any say over the site design at this point (though I will push for a lot of changes as time goes by).
I am running Behat with Mink and the Selenium 2 driver on an Ubuntu 12.10 system (will eventually have to run some tests on a Windows environment for testing in IE). I am also using PhantomJS for some of the tests I have setup.
Anyway, does Behat/Mink support working with popup windows somehow through the Selenium 2 driver (or through PhantomJS)? I am early in all of this automation setup and really I am just experimenting with tools. If there is a better tool that can handle this then please let me know.
My primary question is how do I get Behat/Mink to work with the popup window, check a box, fill in a field, and click the save button? I know how to do everything except get it to interact directly with the newly popped up window. Any ideas/suggestions would be welcome.
Thanks!
So it turns out that Mink includes some window switching features, but no way to identify said windows. So I wrote two functions getWindowName() and getWindowNames() that identify the current window and all open windows respectively. I committed these changes to the project in GitHub it seems that my fixes will get implemented soon into the code base.
But with these changes I am able to switch windows no problem.
Link: https://github.com/Behat/Mink/pull/341
By setting the focus of the window we can also name these windows so we can access them again in the future.
Using this method we can easily switch between popup windows and continue testing...
/**
* #Then I switch to popup :name
*
* #param $name
*/
public function iSwitchToPopup($name)
{
$this->iSetMainWindowName();
$this->getSession()->switchToWindow($name);
}
/**
* #Then I set main window name
*/
public function iSetMainWindowName()
{
$window_name = 'main_window';
$script = 'window.name = "' . $window_name . '"';
$this->getSession()->executeScript($script);
}
/**
* #Then I switch back to main window
*/
public function iSwitchBackToMainWindow()
{
$this->getSession()->switchToWindow('main_window');
}
the popup window is only happening if I use the Fire Fox browser otherwise, is there a way to fix this problem? I have to enter userid/password every time the i use FF as my browser.
currently, I am entering every time i run my test which is very painful but looking to make it more automated....
I have goggled and found two links here and here but no avail
http://username:password#xyz.com
This worked for me (xyz.com being the site name)
After spending hours reading I finally found the solution which works pretty well and I hope this will help others too. - Enjoy!!
First - follow this steps:
1) Open the FireFox browser
2) Type the following `about:config`
3) Look for `network.http.phishy-userpass-length` if you don't find then create a new Integer key
Create a new Integer key (right-click->New->Integer): `network.http.phishy-userpass-length` with value `255`
Second: You need to create a Firefox driver with the following:
FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference("network.http.phishy-userpass-length", 255);
profile.SetPreference("network.automatic-ntlm-auth.trusted-uris", "YOUR HOST ADDRESS HERE");
_driver = new FirefoxDriver(profile);
let me know if you have any questions.
If this is a windows user account & password, then you need to enable the integrated windows login by setting
network.negotiate-auth.delegation-uris: MyIISServer.domain.com
network.automatic-ntlm-auth.trusted-uris: MyIISServer.domain.com
network.automatic-ntlm-auth.allow-proxies: True
network.negotiate-auth.allow-proxies: True
in the Firefox profile that WebDriver starts. Once you have the profile created and saved (run "Firefox -P" when no other instances are running to select a profile), you can do this in the code:
File profileDir = new File("C:/wherever/SeleniumFirefoxProfile");
FirefoxProfile profile = new FirefoxProfile(profileDir);
profile.setEnableNativeEvents(true);
driver = new FirefoxDriver(profile);
I have had to handle these a few times, but my approach is using a script outside Selenium. Are you working on Windows?
Basically what you do is this:
1) Prior to loading the page, clicking the URL, etc that causes that dialog to appear:
-- Launch an asynchronous script to handle the login
2) Then load the page, click the link, etc
-- Selenium will block until your asynch script completes
The async script:
-- Sleep for a few seconds
-- Activate the dialog
-- Send the username
-- Send a TAB
-- Send the password
-- Send a TAB
-- Send the Enter Key
If you are working on windows, I can post sample scripts to handle this. I've done it with Java and C#, but I would guess that basically the same thing would work regardless of how you are writing your tests (unless you are strictly using the FF plugin, in which case this won't work).
Let me know if you'd like more details.
You can use a FF plugin "autoauth". Download this plugin and create Firefox instance by the following way:
FirefoxProfile firefoxProfile = new ProfilesIni().getProfile("default");
File pluginAutoAuth = new File("D:\\autoauth-2.1-fx+fn.xpi");
firefoxProfile.addExtension(pluginAutoAuth);
driver = new FirefoxDriver(firefoxProfile);
I used "autoauth-2.1-fx+fn.xpi"