Skip to content
This repository has been archived by the owner on Feb 10, 2019. It is now read-only.

External Validators #87

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions jquery.h5validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@
// Callback stubs
invalidCallback: function () {},
validCallback: function () {},

// Array of External Validator Functions. View the comment for addValidator for more information.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change this so it's not called external, since I'd like this to be the core of how validations work from now on. Thanks for this excellent work. =)

externalValidators: [],
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just validators will do. ;)


// Elements to validate with allValid (only validating visible elements)
allValidSelectors: ':input:visible:not(:button):not(:disabled):not(.novalidate)',
Expand Down Expand Up @@ -280,6 +283,23 @@
validity.valid = false;
validity.tooLong = true;
}

// Iterate through the external validators. If any fail, the field fails.
for (var i = 0;i<settings.externalValidators.length;i++) {
var validator = settings.externalValidators[i].validator;
var selector = settings.externalValidators[i].selector;
var options = settings.externalValidators[i].options;
if ($(this).is(selector)) {
var boundValidator = validator.bind(this);
if (!boundValidator(value)) {
validity.valid = false;
validity.failedValidator = true;
if (options.name) {
validity.failedValidatorName = options.name;
}
}
}
}

if (required && !value) {
validity.valid = false;
Expand Down Expand Up @@ -523,6 +543,26 @@
}
re = new RegExp('^(?:' + pattern + ')$');
$(selector).data('regex', re);
},
/**
* Takes a selector and a function that is used to do external validation of all fields.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to change these descriptions, docs, and error messaging, too! =)

* This is useful for doing validation against a webservice
* (e.g. 'http://example.com/is_value_valid/example_value')
* Each validator will be matched using the corresponding selector against every field attached to h5Validate.
*
* @param {Selector} selector - A jquery selector of the field on which to apply the external validator.
* example: [name="target-field"]
* @param {Function} validator - An external validator function with the following definition:
* @param {String} value - The value of the input being validated.
* @return {Boolean} - The result of the validation (true = pass, false = fail).
* @this {DOM Element} - The dom element being validated.
* @throws {Error} - If the validator is not a function, throw an exception
*/
addValidator: function(selector, validator, options) {
if (!$.isFunction(validator)) {
throw new Error('Expected external validator function. Saw ', validator);
}
defaults.externalValidators.push({selector: selector, validator: validator, options: options || {}} );
}
};

Expand Down
15 changes: 15 additions & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,21 @@ <h2>Bypassing Validation tests (via 'formnovalidate')</h2>
<input id="bypassSubmit" type="submit" formnovalidate="formnovalidate"/>
</form>
</section>

<section>
<h2>External Form Validation Tests</h2>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here.

<form id="externalValidationForm">
<input id="externalValidationFieldPass" type="text" />
<input id="externalValidationFieldFail" type="text" />
<input id="externalValidationFieldExample" type="text" value="example" />
<input id="externalValidationFieldNotExample" type="text" value="notexample" />
<input id="externalValidationFieldNotExampleNotNamed" type="text" value="notexample" />
<input id="externalValidationFieldNotExampleNamed" type="text" value="notexample" />
</form>
<form id="externalValidationFormPass">
<input id="externalValidationFieldUnused" type="text" />
</form>
</section>


<script src="http://code.jquery.com/jquery.js"></script>
Expand Down
122 changes: 122 additions & 0 deletions test/test.h5validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,128 @@
$form.empty().remove();
});

test('Adding an external validator should fail for non functions',function () {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And in the tests...

raises(function() {
$.h5Validate.addValidator('[name="target-field"]',5);
}, Error, 'Should not be able to add an integer as an external validator.');

raises(function() {
$.h5Validate.addValidator('[name="target-field"]','5');
}, Error, 'Should not be able to add a string as an external validator.');

raises(function() {
$.h5Validate.addValidator('[name="target-field"]',null);
}, Error, 'Should not be able to add a null as an external validator.');

raises(function() {
$.h5Validate.addValidator('[name="target-field"]',{});
}, Error, 'Should not be able to add an object as an external validator.');

raises(function() {
$.h5Validate.addValidator('[name="target-field"]',[]);
}, Error, 'Should not be able to add an array as an external validator.');
});

test('Adding an external validator should succeed for functions',function () {
$.h5Validate.addValidator('[name="target-field"]',function(){return true;});
ok(true, 'Should be able to add a function as an external validator without causing an exception.');
});

test('Adding an external validator that returns true should not cause validation to fail.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldPass');
$.h5Validate.addValidator($field,function(){return true;});
$form.h5Validate();
equal($field.h5Validate('isValid'), true, 'Adding an external validator that returns true should not cause validation to fail.');
});

test('Adding an external validator that returns false should cause validation to fail.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldFail');
$.h5Validate.addValidator($field,function(){return false;});
$form.h5Validate();
equal($field.h5Validate('isValid'), false, 'Adding an external validator that returns false should cause validation to fail.');
});

test('Adding an external validator that confirms the value of the input should not cause validation to fail.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldExample');
$.h5Validate.addValidator($field,function(value){return value == 'example';});
$form.h5Validate();
equal($field.h5Validate('isValid'), true, 'Adding an external validator that confirms the value of the input should not cause validation to fail.');
});

test('Adding an external validator that disconfirms the value of the input should cause validation to fail.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldNotExample');
$.h5Validate.addValidator($field,function(value){return value == 'example';});
$form.h5Validate();
equal($field.h5Validate('isValid'), false, 'Adding an external validator that disconfirms the value of the input should cause validation to fail.');
});

test('Adding an external validator to a selector that does not exist should not cause validation to fail.',function () {
var $form = $('#externalValidationFormPass');
$.h5Validate.addValidator('atagthatdoesntexistinhtml',function(){return false;});
$form.h5Validate();
equal($form.h5Validate('allValid'), true, 'Adding an external validator to a selector that does not exist should not cause validation to fail.');
});

test('External validators should be passed the value of the DOM element.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldExample');
$.h5Validate.addValidator($field,function(value) {
equal(value, $field.val(), 'External validators should be passed the value of the DOM element.');
return true;
});
$form.h5Validate();
$field.h5Validate('isValid');
});

test('External validators should be run in the context of the DOM element of the target field.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldExample');
$.h5Validate.addValidator($field,function() {
equal(this, $field.get(0), 'External validators should be run in the context of the DOM element of the target field.');
return true;
});
$form.h5Validate();
$field.h5Validate('isValid');
});

test('If an added validator fails, the validity "failedValidator" field should be true.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldNotExampleNotNamed');
$.h5Validate.addValidator($field,function(value){return value == 'example';});
$field.on('validated',function(event,validity) {
ok(validity.failedValidator, 'If an added validator fails, the validity "failedValidator" field should be true.');
});
$form.h5Validate();
$field.h5Validate('isValid');
});

test('If no validator name is supplied,the validity "failedValidatorName" property should be null.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldNotExampleNotNamed');
$.h5Validate.addValidator($field,function(value){return value == 'example';});
$field.on('validated',function(event,validity) {
equal(validity.failedValidatorName, null, 'If no validator name is supplied,the validity "failedValidatorName" property should be null.');
});
$form.h5Validate();
$field.h5Validate('isValid');
});

test('Supplied validator names should be assigned to the validity "failedValidatorName" property if they exist.',function () {
var $form = $('#externalValidationForm'),
$field = $('#externalValidationFieldNotExampleNamed'),
validatorName = 'exampleValidator';
$.h5Validate.addValidator($field,function(value){return value == 'example';},{name: validatorName});
$field.on('validated',function(event,validity) {
equal(validity.failedValidatorName, validatorName, 'Supplied validator names should be assigned to the validity "failedValidatorName" property if they exist.');
});
$form.h5Validate();
$field.h5Validate('isValid');
});

}
exports.runTests = runTests;
}((typeof exports !== 'undefined') ? exports : window));