I am using htmlunit and groovy to perform a lot of web automation. I'm stuck when attempting to press the "OK" button on a javascript popup alert window (not a normal browser window). I've set up ConfirmHandler - I think correctly - but the button still is not being pressed.
This is what I have currently:
conn = new WebClient(javaScriptTimeout:1000)
conn.waitForBackgroundJavaScript(1000)
conn.getOptions().setJavaScriptEnabled(true);
conn.getOptions().setCssEnabled(false);
ConfirmHandler okayHandler = new ConfirmHandler() {
boolean handleConfirm(Page page,String message) {
return true
}
}
def page = conn.getPage(url)
def form = page.getFormByName("loginForm");
// code to login here - won't bore you with it
if (login failed) { // <-- this isn't the actual if statement, but need to remove for security purposes
println "\n\nNeed to hit the okayHandler here"
okayResult = conn.setConfirmHandler(okayHandler)
println "\n\nOkay Result: ${okayResult}"
}
The things I notice:
The okayHandler method seems to be run
The value of "okayResult" is null
I can verify manually that the actual button has not been pressed
So, either my ConfirmHandler is incorrect, I'm calling it incorrectly, or my understanding of the javascript alert window is off. My questions are:
What am I doing wrong with ConfirmHander?
Is there a better way to handle the javascript alert window? All I need to do is acknowledge it by pressing "ok".
==============
Here is my browser setup
public void setupBrowser() {
conn = new WebClient(javaScriptTimeout:1000)
conn.waitForBackgroundJavaScript(1000)
conn.getOptions().setJavaScriptEnabled(true);
conn.getOptions().setCssEnabled(false);
AlertHandler myAlertHandler = new AlertHandler() {
void handleAlert(Page page,String message) {
println "\n\nClosing login alert message"
}
}
}
Here is how I am attempting to handle the alert:
conn.myAlertHandler(handleAlert(resultPage,errorMessage))
And here is the error message:
FAIL - Unexpected exception: No signature of method: Groovy_charterLogin_Test.handleAlert() is applicable for argument types: (com.gargoylesoftware.htmlunit.html.HtmlPage, java.lang.String) values: [HtmlPage('pagestuffhere'),passedErrorMesageHere]
You have to set the confirm handler before the alert opens; in your case you can do this directly after the construction and make sure with the real browser you are facing a confirm dialog (window.confirm(....)).
Related
The web app I am testing gives an alert. I wanted to use cypress to test if the alert is being shown and click cancel on the alert but cypress is automatically confirming the alert.
Here is the code:
cy.get('a').contains('Concepts').click();
cy.on('window:alert', (t) => {
//assertions
expect(t).to.contains('You have unsaved changes, are you sure you want to leave?');
return false;
})
I have returned false but still, on running the test, it says confirm without the assertion being handled and it goes to the new URL (which it should not). (see image below)
What am I doing wrong?
Look like you are using window:confirm not alert.
Change it to confirm instead
cy.on('window:confirm', (t) => {
//assertions
expect(t).to.contains('You have unsaved changes, are you sure you want to leave?');
return false;
})
Summarize the problem
I'm trying to create a macOS tabbed web browser using WKWebView and Swift. Everything works fine except the webpage doesn't know I closed the tab. I want to tell the webpage that I closed the tab
Describe what you've tried
I haven't tried anything because I don't know what to do
Show some code
I've tried doing this
webView.removeFromSuperView()
But the webpage didn't know that I closed the tab
I don't know much javascript so please include code instead of explaining
Javascript scripts use onbeforeunload and onunload events to tap into browser closing.
Since you know the browser is about to close, you can dispatch this event yourself. For example, with beforeunload event:
let script = """
const event = new Event("beforeunload", { cancellable: true });
const cancelled = !window.dispatch(event);
// return back whether the user cancelled
cancelled;
"""
When you need to close the browser, invoke the script:
let webView = WKWebView()
// ... other config
webView.evaluateJavaScript(script, completionHandler: { result, error in
guard let cancelled = result else { return }
if cancelled == 1 {
// ... do whatever
}
})
I'm attempting to log on to a web page that I cannot guarantee has previously been logged out of.
If the prior logoff was not successful then a javascript alert pops up which needs to be acknowledged, then logging back on will work.
1: Initial Logon
2: Acknowledge javascript alert
3: Second Logon
I can verify that this works using a web browser. I can also verify that my handleAlert function works. However... upon attempting my second logon the javascript alert opens back up.
I'm not much of a javascript or web expert. I've tried clearing the cache, reloading the page, emptying the form and re-setting the credentials, and I cannot get around this issue.
Are there any suggestions for what I'm either doing wrong or what I can do to troubleshoot?
import com.gargoylesoftware.htmlunit.BrowserVersion
import com.gargoylesoftware.htmlunit.*
isError = 0
def login() {
cancelPage = cancelButton.click()
form = cancelPage.getFormByName("loginForm");
userField = form.getInputByName('j_username');
passwordField = form.getInputByName('j_password');
submitButton = page.getElementById("loginBtnId");
cancelButton = page.getElementById("cancelBtnId");
userField.setValueAttribute(username);
passwordField.setValueAttribute(password);
submitButton = page.getElementById("loginBtnId")
submitButton.click()
}
try
{
if (!url.startsWith("https"))
{
url = "https://" + url;
}
conn = new WebClient(javaScriptTimeout:10000)
conn.waitForBackgroundJavaScript(10000)
conn.waitForBackgroundJavaScriptStartingBefore(3000)
conn.getOptions().setJavaScriptEnabled(true);
conn.getOptions().setCssEnabled(false);
conn.setAlertHandler(new AlertHandler() {
void handleAlert(Page page,String errorMessage) {
println "\nIn handleAlert routine"
isError = isError + 1
if (isError == 1) {
login()
}
}
});
//get page
page = conn.getPage(url)
form = page.getFormByName("loginForm");
//get username and password form input fields and submit button
userField = form.getInputByName('j_username');
passwordField = form.getInputByName('j_password');
submitButton = page.getElementById("loginBtnId");
cancelButton = page.getElementById("cancelBtnId");
submitButton.click()
}
catch (Exception e)
{
println "\nFAIL - Unexpected exception: " + e.getMessage();
for (trace in e.getStackTrace())
{
println "\n\t" + trace;
}
}
The alert handler is only for the alert dialog - to get you informed that there is an alert. Do not call you login code from the alert handler, you have to place this code directly after the click call that opens the alert.
Some more hints:
Maybe this is not a alert box maybe it is a confirm box and you need a confirm handler.
Have a look at the javadoc of the handler classes.
Make yourself familiar with the page your are driving, many modern js libs do not use alert/confirm at all. They use some js/css magic to show something that looks like an dialog but is part of the page dom tree. This has to be handled with the usual HtmlUnit API.
In a page, when I click on a certain button, I get a javascript popup with 'Ok' and 'Cancel' buttons. I want to click 'Ok' button in that popup using Ruby Watir script. So I use the following code. I get the FAIL message since javascript popup comes and goes out within fraction of a second in Firefox browser. So to check whether the script catches the alert, I did print p browser.alert.present? and I get that as false. How to handle such a issue?
if (certain_button_click)
p browser.alert.present? #I get this as 'false'
browser.wait_until(30) {
browser.alert.present?
} rescue nil
p browser.alert.present? #I get this as 'false'
if browser.alert.present?
browser.alert.ok
message = 'Click Ok - PASS'
else
message = 'Click Ok - FAIL'
end
end
Please help. Thanks in advance.
Thanks,
Ashwin
Honestly I can't tell what you are trying to accomplish here, but I see what your code is doing.
Selenium raises an UnhandledAlertError whenever an alert is present, but a non-alert related action is taken with the driver. What your code is doing is rescuing that exception (well, all exceptions, which you should avoid doing when you know which exception you want to avoid). Firefox has different behavior than Chrome in this respect in that it also closes the alert when it raises the exception. So your code is doing exactly what you are telling it to do.
if you use Watir 6.0 you don't have to specify the waits any longer. If you only want to dismiss an alert when it shows up, this code will automatically wait for the alert to show up and click ok when it does. If the alert never shows up it will give a timeout error.
element_causing_alert.click
browser.alert.ok
If you are trying to test that the alert shows up, then you can use this code:
begin
browser.alert.ok
true
rescue Watir::Wait::TimeoutError
false
end
Or if you want to specify the time to wait before timing out:
begin
browser.alert.wait_until(timeout: 5, &:present?).ok
true
rescue Watir::Wait::TimeoutError
false
end
Here's an alternate idea. You can use execute_script in the browser which 'stubs out' the alert call to set a global variable. Then another execute_script which checks that the variable was set.
Example:
def stub_alert
script = <<-JS
window.alert = function(){ window.alerted = true }
JS
browser.execute_script stub_alert
end
def check_for_alert
script = <<-JS
return window.alerted == true
JS
browser.execute_script stub_alert
end
Watir uses selenium under the hood, and there's some tricky things about working with alerts. I've experienced the situation where Selenium's reference to the alert disappeared if I ran any javascript before handling the alert.
I want to prompt user to either logout or stay on page as logged-in. I tried using the following code, but not able to find the correct solution:
window.onbeforeunload = function (e) {
var e = e || window.event;
// For IE and Firefox
if (e) {
e.returnValue = 'Any string';
}
alert(doLogout());
// For Safari
return 'Any string';
};
function doLogout(){
var r=confirm("Press a button!");
alert("confirmResponse: " + r);
return r;
}
When i tried closing the tab/window, it just asks for "This page is asking you to confirm that you want to leave - data you have entered may not be saved". In my code first confirm dialog should be popped up, which is not happening.
Any solutions ?
It won't do alert() because of security reasons. This tactic to prevent user from leaving the page was used too often by "bad guys of the internet" so most browser blocked it. Only thing you can do in onunload or onbeforeunload is pass a string that should be displayed to user, before he makes a decision to stay or leave page. You should put you message in place of 'Any string'. That should be sufficient for the user.