I'm trying to write a rule that conditions on the content of a javascript alert box. That is, I'm trying to fire a conversion script if the alert says "submission successful" vs "some error message". Can I access the string shown in the alert box so I can use it i.e. if alert message == "submission successful" fire the tracking script?
You could override alert so that you could track what is being alerted. For example:
window.alert = (function() {
var existingAlert = window.alert;
return function(message) {
console.log(message); // do your tracking here
existingAlert(message);
};
})();
You would need to be able to run this code before other code called window.alert.
Related
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(....)).
If I have a page overriding window.alert box:
Window.alert = function() {}
can I re-enable the alert box if I have access to the Javascript?
I guess I would save the original alert function off somewhere else and then reassign it back to it.
var originalAlert = window.alert;
window.alert = function(stuff) {
console.log('alert invoked');
}
alert(); // displays a message in the console
var newWindow = window.open();
window.alert = newWindow.alert;
newWindow.close();
alert(); // alerts a message
I don't know that I would open a new window just to get the alert function, but that function is native code, so once it's been closed over, you can't get it back without some crazy hack like this. At least not that I'm aware of.
I want to insert my debugger function inside another JS function and halt the execution.
I know return false/true does the job, but I want my debugger function to do that automatically.
Example:
<script type="javascript">
function validateFirstName () {
//validating first name field
var fn = $('#firstname').val();
if(fn == "") {
$("#errorMsg").html("Please insert first name");
$("#firstname").focus();
return false;
}
debugger(); //I want to stop everything here
// if validation passes, redirect browser:
window.location = 'nextpage.html';
}
function debugger () {
console.log("Some custom message here");
return false;
}
</script>
You'll notice I put my debugger function inside the validateFirstName() function.
I assumed that return false in my debugger() function will stop the validateFirstName() from executing. But it doesn't.
Without adding return false inside the validateFirstName() function, how can I use my debugger() function to stop all execution?
replace
debugger(); //I want to stop everything here
with
return debugger(); //I want to stop everything here
the above example will always stop on true or false.
This will continue to the window.location if it's true and stop if it's false.
if(!debugger())
return;
in your case it seems to be a function inside of a function so you might as well use
if(!debugger())
return false;
Seems what you really want to do is set a breakpoint on the executing code.
In Chrome Browser press Ctrl+Shift+I
Then Go to Sources Tab
Click the Arrow pointing right (looks like a play button) on top of the counting line numbers to see list of websites
Find your website click on the folder
Find whatever script that you want
Now click anywhere in the code to close the side bar
Now finally click on any number on the side thats counting down the lines
That will set a breakpoint which means it will stop on that code if you make the code go there by doing something on your website, or forcing the code to run using the
Console tab or simply in your address bar typing javascript: function_to_call();
You could throw from debugger () like this.
function debugger () {
console.log('Some custom message here');
throw 'Debugging Code';
}
Although this will do what you want it to, I don't recommend it. Basically what's happening is you are throwing an error which isn't being caught in your code (the browser will catch it, but that is probably not as clean).
You could throw an error:
function validateFirstName () {
//validating first name field
var fn = $('#firstname').val();
if(fn==""){
$("#errorMsg").html("Please insert first name");
$("#firstname").focus();
return false;
}
debugger(); //I want to stop everything here
// if validation passes, redirect browser:
window.location='nextpage.html';
}
function debugger () {
throw new Error("Some custom message here");
}
try{
validateFirstName();
}catch(e){
console.log(e);
}
If you are using a modern browser like Chrome, why not just use debugger instead?
that will trigger the debugger in your developer tools.
like this:
debugger; //I want to stop everything here
notice the missing ()
I'm writing some Jasmine tests for some legacy javascript that produces an alert or a confirm at some points in the code.
At the moment where the alert pops up it pauses execution in the browser requiring me to press ok before going on.
I'm sure I'm missing something but is there a way of faking an alert?
Even better is it possible to find out what the message was for the alert?
Thanks for your help.
spyOn(window, 'alert');
. . .
expect(window.alert).toHaveBeenCalledWith('a message');
var oldalert = alert;
alert = jasmine.createSpy();
// do something
expect(alert).toHaveBeenCalledWith('message')
alert = oldalert
Another way is to do this in spec helper.
window.alert = function(){return;};
Or if you need the message.
var actualMessage = '';
window.alert = function(message){actualMessage = message; return;}
You simply create a spy, surprisingly with createSpy(), to mock the function that contains the alert. So you can do something like this:
beforeEach(function() {
functionWithAlert = jasmine.createSpy("functionWithAlert");
functionWithAlert("called as usual");
});
You can also do this to return something
oldFunctionWithAlert = jasmine.createSpy("oldFunctionWithAlert() spy").andCallFake(function() {
console.log("Doing some testing");
return "Test";
});
On a side note, I would suggest you replace the alert if possible with less disruptive alternatives. There are a ton of options out there like JQuery UI dialog.
I work with some very large and confusing JavaScript files that I did not write. Sometimes an alert will come up but I don't know where it's coming from.
You could search all files for the text contained in the alert but if that text is dynamic it won't work.
Is there a way to set a breakpoint in order to intercept an alert?
At the very top of your HTML:
window.alert = function() {
debugger;
}
debugger is a statement that invokes any debugging functionality available. With developer tools open, you'll automatically hit a breakpoint whenever alert is called. You can then inspect the call stack to see exactly what called the custom alert function.
It may or may not be helpful to you, but you can overwrite the alert function to do whatever you want with it. For example, instead of alert boxes, you could have it log the message to the console.
window.alert = function(msg) {
console.log(msg);
}
alert('test');
I agree with Brian Glaz, but in order to get more details (line number) you might try to throw an error when alerting something and outputting the error on the console. this way, the console will point you to the right line number where the alert function was called.
Put this snippet at the top of your document and give it a try :
var originalAlert = window.alert;
window.alert = function(){
try{
throw new Error('alert was called');
} catch(e){
console.warn(e);
}
return originalAlert.apply(window, arguments);
}
Open Chrome push F12 key and go to Sources.
Then choose a script file Ctrl+F and search for alert.
You can put breakpoint on any line you wish