How do I test that an alert box on my page was called? Can I grab the text of the alert box and evaluate it?
My click in CasperJS is done like this:
casper.waitForSelector('a[href="javascript:UserLogin()"]',
function success() {
this.test.comment("Submiting the bad login info");
this.test.assertExists('a[href="javascript:UserLogin()"]');
this.click("a#h_login");
},
function fail() {
this.test.assertExists('a[href="javascript:UserLogin()"]');
});
The UserLogin function checks and in this case, returns this:
alert('Login has failed.');
How do I check this?
You have to listen to the remote.alert event:
casper.on('remote.alert', function(message) {
this.echo('alert message: ' + message);
// or if you want to test it
this.test.assertMatch(message, /Login has failed/);
});
An attempt to make it a bit more synchronous:
function testAlert(message) {
this.test.assertMatch(message, /Login has failed/);
}
casper.then(function() {
// temporarily registering listener
this.on('remote.alert', testAlert);
});
casper.waitForSelector('#login', function success() {
this.test.pass('selector was found');
this.click("#login");
}, function fail() {
this.test.fail('selector was found');
});
casper.then(function() {
this.removeListener('remote.alert', testAlert);
});
Version 1.1-beta4 provides the casper.waitForAlert function. With it you can write nicer tests when you need to react to different alerts on the page.
Related
$(".getDetails").click(function() {
// some stuff like fetching response from server
})
when user clicks getDetails button on UI multiple times within fraction of second , jquery generates two calls for click function and my logic fails.
I think solution to this will be to disable the button on first click itself(so that use can't click multiple times). Once i get the response or just before returning
from click method i make it enable. Is there any better solution ?
If no, how can i make button disable as soon as user click button first time. I think it needs to be done before calling click method or some where in html element ?
Java provides synchronized keyword so that only one thread enters at time inside method , i am not sure is similar thing exist in javascript or not ?
Assuming the click handler executes an AJAX request you can set the button as disabled before making the request, then enable it again once the request completes. Try this:
$(".getDetails").click(function(){}
var $btn = $(this).prop('disabled', true);
$.ajax({
url: '/foo'
success: function() {
console.log('It worked!');
},
error: function() {
console.log('It failed!');
},
complete: function() {
$btn.prop('disabled', false);
}
});
});
you can try unbinding click event and after ajax call again bind click to that class
$(".getDetails").click(function(){}
$(".getDetails").unbind('click');
// some stuff like fetching response from server
)
You can use simple flag to prevent firing your logic multiple times:
var flag = true
$(".getDetails").click(function() {
if (flag) {
flag = false;
//your logic...
//when your code ends (in after-AJAX callback for example)
flag = true;
}
});
$(".getDetails").click(function(e){
var $target = $(e.currentTarget);
// assuming the click listener is on the button
$target.prop('disabled',true);
// request, stuff...and when done:
$target.prop('disabled',false);
})
try Prevent Default and return false to avoid any other event propagation
This is solution is like semaphore or monitor
var progress = false;
$(".getDetails").on('click', function(e) {
if(!progress){
progress = true;
// some stuff like fetching response from server
//also after sucessfull fetch make true to false again
}else{
console.log('something in progress');
}
e.preventDefault();
return false;
})
This should make sure that your button will not fire the async request twice, until you have a response.
function doAjaxReq() {
/*
Add your ajax operation here
as a return value of doAjaxReq
like so:
return $.ajax({
url: '/foo',
type: 'POST',
data: data
})
Since i can't use ajax here let's smilulate
it useing a promise.
*/
promise = new Promise(function(res, rej) {
setTimeout(function(){
res({foo: "bar"});
}, 1000)
})
return promise;
}
/*
Inside here you add the click handlder
only once use `elem.one('click'...`
*/
function addClickHandler(elem) {
elem.one('click', function() {
// do your ajax request and when its
// done run `addClickHanlder` again
// i'm using `.then` because of the promise,
// you should be using `.done`.
doAjaxReq().then(function(data) {
console.log(data);
addClickHandler(elem);
});
})
}
addClickHandler($(".getDetails"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="getDetails">Get Details</button>
How to skip part of a code on die? The script has to jump to the next label(for example, they all have name LABEL1)
casper.start('http://google.com');
casper.waitForSelector("input[name='q']",
function success() {
this.echo('Google.com page loaded');
},
function fail() {
this.die('Google.com page WAS NOT loaded'); //meet die() function,
//need to jump on LABEL1 without stopping script
});
casper.then(function(){
this.fillSelectors('body', {
"input[name='q']": 'stackoverflow',
}, true);
this.echo('Filled form with search word - stackoverflow');
});
//here can be random number of casper steps
casper.then(function() {
this.captureSelector("search_results.png", "html");
});
//steps, steps
casper.then(function() {
this.echo("search_results.png");
});
//LABEL1
casper.thenOpen('http://wikipedia.org', function() {
this.echo('HELLO');
});
casper.run();
I can't use suites for this purpose, because I have a custom casper module.
You could probably try emitting a custom event which would execute your required step instead of calling a die(). http://docs.casperjs.org/en/latest/events-filters.html#emitting-you-own-events
I'm trying to get some client side validation working to prevent a form submission occurring if an object has no value. I've been plugging away at this for a while now but cannot get a satisfactory solution.
My form submission Js looks like this:
$(document).ready(function () {
$('#localUsersDateTime').val(setLocalDateTime());
$('#createentry').ajaxForm({
beforeSubmit: checkTextObjHasValue($('#newentry'), 'You need to add some text.'),
dataType: 'json',
success: function (result) {
$('#entries-list').prepend('<li>' + $('#newentry').val() + '</li>');
$('#newentry').val('').blur();
},
error: function (xhr)
{
try {
var json = $.parseJSON(xhr.responseText);
alert(json.errorMessage);
} catch (e) {
alert('Oops, Something very bad has happened');
}
}
});
return false;
});
However when the page loads it runs my checkTextObjHasValue() specified in the beforeSubmit: function so that check needs to only execute on actual form submission.
function checkTextObjHasValue(obj, message) {
if ($(obj).val() === '') {
alert(message);
return false;
}
return true;
}
How can I prevent this beforeSubmit: callback from being executed when just loading the page and only execute on actual form submission?
The beforeSubmit option expects a reference to a function. You were immediately calling a function. Try using this:
beforeSubmit: function () {
return checkTextObjHasValue($('#newentry'), 'You need to add some text.');
},
The added return allows for the submission to cancel if false is actually returned (which is possible in checkTextObjHasValue under a certain condition).
Technically, it could've worked if you returned a function from checkTextObjHasValue, but I think this way is a little cleaner. And it lets you customize it in case you want to validate several fields.
UPDATE:
Like in the documentation for the plugin, you could take this approach:
beforeSubmit: beforeSubmitHandler,
And then define a function separately like this:
function beforeSubmitHandler() {
return checkTextObjHasValue($('#newentry'), 'You need to add some text.');
}
I'm trying to use alertify.js as a confirmation dialog for all my confirm scripts. But it just isn't working like regular JS confirm does. In the code below I never get a return true
function aConf ( mes ) {
alertify.confirm( mes, function (e) {
return e;
});
}
Delete
Of course if I replace aConf with JS' confirm it works. So why is alertify not sending me back it's outcome?
Because confirm is a blocking function (no javascript will run until it returns true/false), and alertify is non-blocking (JS keeps executing). Alertify does not immediately return a true/false, but instead, it probably returns undefined immediately, then it calls a callback function later, after the user clicks OK or Cancel. The return value from that callback function has no effect in your example, because the onclick code has already finished running (because it is non-blocking).
Assuming you are using this: https://github.com/fabien-d/alertify.js/
This is how it actually works with a callback function, not a return value:
alertify.confirm( message, function (e) {
if (e) {
//after clicking OK
} else {
//after clicking Cancel
}
});
For your code sample, you might try something like this:
function performDelete ( a_element ) {
// perform your delete here
// a_element is the <a> tag that was clicked
}
function confirmAction ( a_element, message, action ) {
alertify.confirm(message, function(e) {
if (e) {
// a_element is the <a> tag that was clicked
if (action) {
action(a_element);
}
}
});
}
Delete
EDIT: updated to be a generic confirm dialog that calls a callback function if the user clicks ok.
My problem is better explained in code:
//This code is triggered before ajax ObBegin. But I need f1 to return a boolean to either cancel or continue the event.
f1();
function f1(){
$.modalWindow.Open(); //This is an async method, this is where my problem lies.
//I need to freeze here and wait on a return value from one of the events below.
}
//In the modal window:
//An event which waits for the click event
$('.cancelBtn').click(function(){
//How do I send false back to f1?
closeModalWindow();
});
$('.yesBtn').click(function(){
//How do I send true back to f1?
closeModalWindow();
});
So basically what happens is this:
openModalWindow() opens a modal window that waits on a button click.
I want to pass the value back to f1 and return it.
Is there a way to fix this?
Use jQuery's Deferred objects. There's a good tutorial on it here, but you haven't actually shown enough of your own code for me to demonstrate how to wire it up with $.Deferred.
Here's a very basic demo of how to do this: http://jsfiddle.net/mattball/fNQ8J/. Basically, you have to pass callbacks around for asynchronous execution.
function openModalWindow(callback) {
if (typeof callback !== 'function') callback = $.noop;
$("#dialog-confirm").show().dialog({
resizable: false,
modal: true,
buttons: {
Yes: function() {
$(this).dialog("close");
callback(true);
},
No: function() {
$(this).dialog("close");
callback(false);
}
}
});
}
function f1() {
return $.Deferred(function(dfd) {
openModalWindow(dfd.resolve);
}).promise();
}
$('#clickme').click(function() {
f1().then(function(result) {
alert('f1 async returned: ' + result);
});
});
There's no good way to do this, no. You'll have to refactor f1 so it can deal with asynchronicity.
f1() should be implemented as a callback for someAsyncFunc():
function someAsyncFunc(callback) {
// open your modal window
$(".theBtm").click(function() {
// do your stuff
if (typeof(callback) === "function") {
callback(theValueYouWantToPass);
}
});
}
Called something like this:
someAsyncFunc(function(value) { f1(value); });