问题
I have this issue with selenium webdriver tests with chromedriver. Although I can run tests succesfully when using Chrome browser I can't run the same tests in headless mode.
I cannot handle the Js alerts. Actually when taking a screenshot it seems that the alert won't even pop-up.
Alert screenshot
I have tried several workarounds:
1) driver.window_handles
--> No other window seems to be present
2) driver.execute_script("window.confirm = function(){return true;}")
--> Nothing changed with that script
3) element = WebDriverWait(driver, 20).until(EC.alert_is_present())
and of course an explicit wait
In browser mode I use a plain:
try:
print driver.switch_to.alert.text
driver.switch_to.alert.accept()
except NoAlertPresentException as e:
print("no alert")
Anyone else having this issue with alerts in headless mode?
- chromedriver v.2.30.477691
- Chrome Version 59.0.3071.115
回答1:
Still having this problem as of Chrome 61, so I spent a while looking for a different solution. My favorite because of it's simplicity is injecting javascript before the alert is shown in order to automatically accept the alert.
Just put the following line of code before the line that causes the alert to be shown:
driver.ExecuteJavaScript("window.confirm = function(){return true;}");
Works with both headless chrome and PhantomJS.
回答2:
It seems that I have the same issue when running headless chrome. The alert window does not pop up base on the screen shots. It works fine on chrome but not headless chrome.
I am running on chrome 60.0.3112.72 and chrome driver 2.30
Because the headless chrome automatically discards alerts. check this: https://bugs.chromium.org/p/chromium/issues/detail?id=718235
BTW, how come you can screen shot in chrome 59 in headless mode? chrome 59 has a bug that makes every screen shot a 1x1 pixel image in headless mode, so I upgraded to chrome 60.
回答3:
Since Chrome headless doesn't (currently) support alerts, you have to monkeypatch the alert()
and confirm()
methods. This is the approach I've used (in C#):
/// <summary>
/// The Chrome Headless driver doesn't support alerts, so we need to override the window.alert method to get the expected behavior.
/// </summary>
/// <param name="driver">The active IWebDriver instance</param>
/// <param name="result">The result that the alert should return, i.e., true if we want it "accepted", false if we don't</param>
public static void SetupAlert(this IWebDriver driver, bool result)
{
// ks 7/27/17 - The Chrome Headless driver doesn't support alerts, so override the various window.alert methods to just set
const string scriptTemplate = @"
window.alertHandlerCalled = false;
window.alertMessage = null;
window.alert = window.confirm = function(str) {
window.alertHandlerCalled = true;
window.alertMessage = str;
return {{result}};
};";
var script = scriptTemplate.Replace("{{result}}", result.ToString().ToLower());
var js = (IJavaScriptExecutor)driver;
js.ExecuteScript(script);
}
/// <summary>
/// This is an optional accompaniment to the <see cref="SetupAlert"/> method, which checks to see
/// if the alert was, in fact, called. If you don't want to bother to check, don't worry about calling it.
/// Note that this doesn't reset anything, so you need to call <see cref="SetupAlert"/> each time before calling
/// this method.
/// </summary>
public static void WaitForAlert(this IWebDriver driver, TimeSpan? timeout = null)
{
const string script = @"return window.alertHandlerCalled";
var js = (IJavaScriptExecutor)driver;
var timeToBail = DateTime.Now.Add(timeout ?? TimeSpan.FromMilliseconds(500));
while (DateTime.Now < timeToBail)
{
var result = (bool)js.ExecuteScript(script);
if (result) return;
Thread.Sleep(100);
}
throw new InvalidOperationException("The alert was not called.");
}
I use it like this:
Driver.SetupAlert(true);
this.ClickElement(ResetButton);
Driver.WaitForAlert();
回答4:
Just wanted to add this in case someone comes across this issue using NightwatchJS.
The above accepted solution worked for me, but using JS it needed a slight modification from
driver.ExecuteJavaScript("window.confirm = function(){return true;}");
I needed to change it to
// this.api.perform() in my case is the same as browser.perform()
this.api.perform(function () { this.confirm = function () { return true; }})
来源:https://stackoverflow.com/questions/45242264/chromedriver-headless-alerts