Jasmine: Expecting a Form Submission - javascript

I have a jasmine test I am writing for a form validation function.
function checkTotalWeight(){
if(//some condition){
return false;
}
else{
document.Weight.submit();
}
}
I have successfully written tests for my return false conditions, however, I am having trouble getting my test to
See that a submission was made
Prevent the submission from actually happening (ie. "message": "Some of your tests did a full page reload!"
I've tried
var form = $('form');
var submitCallback = jasmine.createSpy().and.returnValue(false);
form.submit(submitCallback);
var check = checkTotalWeight();
expect(submitCallback).toHaveBeenCalled();
which gives me "Expected spy unknown to have been called."
Also, I've tried
$('form').on('submit', function () {
return false;
});
var check = checkTotalWeight();
spyOn(document.Weight, 'submit');
expect(document.Weight.submit).toHaveBeenCalled();
Which gives me "Expected spy submit to have been called."
I haven't had much luck finding anything online along with the lines of "Expecting a form submission with jasmine".
Unfortunately, I cannot change the source code being tested or I would.
Does anyone have any direction?

Related

jQuery form.submit() not always called

I use the following javascript code to do some checks before a form is submitted:
$('form').submit(function(e){
var is_error = false;
// do certain checks and if some of them fail set is_error = true
if(!is_error)
return;
e.preventDefault();
});
This works perfectly and everything is fine actually.
However, I found out that this function is not necessarily always called on a form submit. (I was not able to reproduce this behavior by myself but I saw that on my error logs).
This is what I did to get this information:
I added an hidden input field to the form:
<input id="input-is_used_function" type="hidden" name="is_used_function" value="0" />
And i also adjusted the javascript the following way:
$('form').submit(function(e){
var is_error = false;
// do certain checks and if some of them fail set is_error = true
$('#input-is_used_function').val(1);
if(!is_error)
return;
e.preventDefault();
});
After the submit I logged all transmitted POST vars and I found out that 'is_used_function' is sometimes 0, which means that the jQuery submit function has never been called.
Does somebody has a solution for this or at least a hint on how this behavior happens?
Best,
Freddy

How do I get a function to run with the .onsubmit event?

There is probably a really easy solution to this but I cannot for the life of me work out how to fix this issue, and nothing I have found so far has done the trick.
I'm trying to get the function "validate" to run when the form "apply" is submitted:
function init() {
var applyForm = document.getElementById("apply");
setJobValue();
applyForm.onsubmit = validate;
}
Validate looks like the following:
function validate() {
alert("If this alert is up then validate is running");
var dateOfBirth = document.getElementById("dob").value;
var state = document.getElementById("state").value;
var postcode = document.getElementById("postcode").value;
etc.
The function "setJobValue" is running (so I know init is working) and there are no errors in the console, but what adjustments would I have to make for validate to be called?
Well, what happens is that when you put your code above in the head, the script runs when the HTML gets rendered. So during that time, it allocates different memory and function blocks. So when you call that function again, then it gives you different results and no errors because of the existing references. Well its a bit weird but its the way JS works and it is always recommended to put your JS code at the bottom of the page.
You can directly call validate method from your init method instead.
function init() {
var applyForm = document.getElementById("apply");
setJobValue();
validate();
}
When we assign a function to an event, it will fire at last.
so in your case, This should work
function init() {
var applyForm = document.getElementById("apply");
setJobValue();
applyForm.onsubmit = functionToSave;
}
And call your validation method on the submit button onclick event.

JavaScript: Analytics Track Event won't fire

I've put the function into form validation part, so that only when form is valid, the beacon would be sent. I am sure I am missing something. See code below.
function checkForm() {
var error = "";
if($("#first_name").val()=="") { error+="- Enter your first name.\n";};
if(error=="") {
_gaq.push(['_trackEvent','Form','Submit','Newsletter']);
return true;
} else {
alert("Please correct these form errors before you submit the form:\n\n"+error)
return false;
}
}
EDIT: Thanks everyone for their help! Tested this one, and 100ms doesn't seem to be enough.
Now I am thinking to do this a little more clever way. It would make sense to submit it, once all required fields have text in it, but it should be clever enough to submit more than once and submit only when data is valid!
Try to give a delay (may be about 100 miliseconds or less) using setTimeout() or setInterval() and let the GA datato be submited. Worked for me.
function gaSubmit(param){
_gaq.push(param);
}
function checkForm() {
var error = "";
if($("#first_name").val()=="") { error+="- Enter your first name.\n";};
if(error=="") {
setTimeout(gaSubmit(['_trackEvent','Form','Submit','Newsletter']),100);
return true;
} else {
alert("Please correct these form errors before you submit the form:\n\n"+error)
return false;
}
}
Are you sure if it's not fires? Probably there is some delay in analytics data refresh. If you develop your app on localhost, then you should set _setDomainName property to 'none'
_gaq.push(['_setAccount', 'Your-account-id']);
_gaq.push(['_setDomainName', 'none']);
#see:GA Event Tracking from localhost

How do I detect an attempted submission of invalid HTML forms?

When using HTML form validation, having an invalid input value in a form will halt submission of that form. How can I detect that the user attempted a failed form submission? The form's onsubmit handler does not fire when submission is halted by validation failure.
I'm currently listening for keypress and click events on the submit button to detect submit attempts. Is there a better way of detecting a failed form submission?
A simple way to get around this is to add an event listener to each input in the form to see when it has been prevented from submitting. The 'invalid' event should do everything you need.
Example
Array.prototype.slice.call(document.querySelectorAll("[required]")).forEach(function(input){
input.addEventListener('invalid',function(e){
//Your input is invalid!
})
});
More info here
http://www.html5rocks.com/en/tutorials/forms/constraintvalidation/
I suggest you to use noValidate property. You can turn off default validation, and run it manually within onsubmit method
var form = document.getElementById("myForm");
form.noValidate = true; // turn off default validation
form.onsubmit = function(e) {
e.preventDefault(); // preventing default behaviour
this.reportValidity(); // run native validation manually
// runs default behaviour (submitting) in case of validation success
if (this.checkValidity()) return form.submit();
alert('invalid'); // your code goes here
}
you can check it here: https://jsfiddle.net/titulus_desiderio/Laon29f3/
Building on #Titulus' code above, here's how I would do it in jQuery; you can adapt this to native events if need be.
$('form-selector').on('submit', function(event) {
// Don't do anything if constraint validation isn't supported by the browser.
if (
!('checkValidity' in this) ||
// In the unlikely case this is a property but not actually a function.
// Hypothetically, a botched polyfill could do this; it pays to be careful
// and build resilient code.
typeof this.checkValidity !== 'function'
) {
return;
}
if (this.checkValidity() === true) {
// Valid values code.
} else {
// Invalid values code.
// Leave this until the last possible moment in the handler in case there's
// an error in any of the handler code to reduce the chances of a broken
// form where the submit does nothing. If an exception is thrown before
// this, the browser shouldn't get this far, (hopefully) allowing the basic
// form to still work.
event.preventDefault();
}
});
// Tell the browser to not validate automatically, as that would prevent submit
// from being triggered. We prevent the submission above if form doesn't pass
// validation. This is here in case there's an error in the preceding code, so
// this (hopefully) doesn't get applied in that case and browser validation
// takes place as a fallback.
this.noValidate = true;

$.post() doesn't have time to run?

I'm trying to send data from a form to an external script prior to submitting the form, yet I cannot seem to get the data to reach the external script unless I return false; on the form itself.
$(document).ready(function () {
// Handle Form-Submission
$("#mainForm").submit(function () {
// Reset Error Array
errors = new Array();
/* Validation Code Removed - Not Relevant */
// Check if errors exist
if (errors.length > 0) {
return false;
} else {
$("div.errors").html("");
$.post("post.php",{
"First Name": name_first.val(),
"Last Name": name_last.val(),
"Home State": home_state.val(),
"Primary Email": email_primary.val()
});
}
return false; /* Remove this line, and the $.post won't work. */
});
});
I ran into the exact same problem today. Like Marc says, it's because the ajax call is asynchronous. The simplest fix is to make it synchronous.
Use .ajaxSetup() before any ajax calls like such:
$.ajaxSetup({async: false});
Sending to two end points
I would try something like this instead of using async: true. Though it is notably more complicated, it would not freeze the interface.:
$(document).ready(function(){
// Handle Form-Submission
$("#mainForm").submit(function(e){
e.preventDefault();
var $form = $(this);
if($form.data('submitting')) return; // Avoid double submissions
$(':submit').attr('disabled','disabled'); // Disable the submit button
// Reset Error Array
errors = new Array();
/* Validation Code Removed - Not Relevant */
// Check if errors exist
if (errors.length > 0) {;
$(':submit').removeAttr('disabled'); // Enable the submit button
return false;
} else {
$("div.errors").html("");
$form.data('submitting',true); // Flag that a submission has started
$.post("post.php",{
"First Name":name_first.val(),
"Last Name":name_last.val(),
"Home State":home_state.val(),
"Primary Email":email_primary.val()},
function(){
// remove our special handler and submit normally
$form.unbind('submit').submit();
}
);
}
});
});
Original Answer
It seems your hangup is that you want to use $.post if JavaScript is enabled, but let the form function normally with JavaScript disabled.
However, since none of your JavaScript will run if it is disabled you don't have to worry about altering behavior in the submit function.
You can just leave your return false; statement, or use
$("#mainForm").submit(function(e){
// all your existing code
e.preventDefault();
}
That will keep the form from submitting normally and will instead using your $.post method when JavaScript is enabled. If it is disabled it will submit normally.
preventDefault is preferred to return false if you want event bubbling to continue as normal, but keep the default browser action from continuing. return false is the equivalent of calling e.preventDefault(); e.stopPropagation();

Categories