This repository has been archived by the owner on Feb 10, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 125
External Validators #87
Open
christianlent
wants to merge
5
commits into
ericelliott:master
Choose a base branch
from
christianlent:external
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
88d89f8
Per-selector external validation
709dcbd
Fixed some external validation tests and added a few more.
e27e6ea
Renamed addExternalValidator to addValidator
4a827d1
Refactored some builtin validators to use new "validators" array
christianlent 4480079
Better default failure flags
christianlent File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,6 +92,9 @@ | |
// Callback stubs | ||
invalidCallback: function () {}, | ||
validCallback: function () {}, | ||
|
||
// Array of External Validator Functions. View the comment for addValidator for more information. | ||
externalValidators: [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just |
||
|
||
// Elements to validate with allValid (only validating visible elements) | ||
allValidSelectors: ':input:visible:not(:button):not(:disabled):not(.novalidate)', | ||
|
@@ -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; | ||
|
@@ -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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 || {}} ); | ||
} | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -302,6 +302,128 @@ | |
$form.empty().remove(); | ||
}); | ||
|
||
test('Adding an external validator should fail for non functions',function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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)); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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. =)