parsleyjs
Version:
Validate your forms, frontend, without writing a single line of javascript!
389 lines (365 loc) • 14.8 kB
JavaScript
import $ from 'jquery';
import ParsleyForm from '../../src/parsley/form';
import Parsley from '../../src/parsley';
describe('ParsleyForm', () => {
it('should be a function', () => {
expect(ParsleyForm).to.be.a('function');
});
it('should bind parsleyFields children', () => {
$('body').append(
'<form id="element">' +
'<input id="field1" type="text"/>' +
'<div id="field2"></div>' +
'<textarea id="field2"></textarea>' +
'</form>');
var parsleyForm = $('#element').parsley();
expect(parsleyForm.fields.length).to.be(2);
});
it('should bind parsleyFields children, and not excluded ones', () => {
$('body').append(
'<form id="element">' +
'<input id="field1" type="text"/>' +
'<div id="field2"></div>' +
'<textarea id="field2"></textarea>' +
'<div data-parsley-validate></div>' + // ParsleyForm, not a valid child
'<input id="field3" disabled />' + // Disabled, excluded by custom options below
'<input id="field-excluded" data-parsley-excluded="true" />' + // Excluded with 'excluded' option
'<input type="submit"/>' + // Excluded field, not valid
'</form>');
var parsleyForm = $('#element').parsley({excluded: '[disabled], input[type=button], input[type=submit], input[type=reset]'});
expect(parsleyForm.fields.length).to.be(2);
});
it('should properly reset excluded', () => {
$('body').append(
'<form id="element">' +
'<input id="field" required class="foo"/>' +
'</form>');
var parsleyForm = $('#element').parsley();
parsleyForm.validate();
expect($('.parsley-error').length).to.be(1);
parsleyForm.options.excluded = ".foo";
parsleyForm.validate();
expect($('.parsley-error').length).to.be(0);
});
it('should properly bind options for form and children fields', () => {
$('body').append(
'<form id="element" data-parsley-trigger="change">' +
'<input id="field1" type="text" data-parsley-required="true" />' +
'<div id="field2"></div>' +
'<textarea id="field3" data-parsley-notblank="true"></textarea>' +
'</form>');
var parsleyForm = $('#element').parsley();
expect(parsleyForm.fields.length).to.be(2);
expect($('#field1').parsley().options.trigger).to.be('change');
expect($('#field1').parsley().options.required).to.eql(true);
expect($('#field1').parsley().options.notblank).to.be(undefined);
expect($('#field3').parsley().options.notblank).to.eql(true);
expect($('#field3').parsley().options.required).to.be(undefined);
});
it('should properly store validation state after `validate()`', () => {
$('body').append(
'<form id="element" data-parsley-trigger="change">' +
'<input id="field1" type="text" data-parsley-required="true" />' +
'<div id="field2"></div>' +
'<textarea id="field3" data-parsley-notblank="true"></textarea>' +
'</form>');
var parsleyForm = $('#element').parsley();
parsleyForm.validate();
expect(parsleyForm.validationResult).to.be(false);
$('#field1').val('foo');
$('#field3').val('foo');
expect(parsleyForm.validate()).to.be(true);
});
it('should handle group validation', () => {
$('body').append(
'<form id="element">' +
'<input id="field1" type="text" data-parsley-group="foo" data-parsley-required="true" />' +
'<div id="field2"></div>' +
'<textarea id="field3" data-parsley-required="true"></textarea>' +
'</form>');
var parsleyForm = $('#element').parsley();
expect(parsleyForm.isValid()).to.be(false);
$('#field1').val('value');
expect(parsleyForm.isValid()).to.be(false);
expect(parsleyForm.isValid({group: 'foo'})).to.be(true);
$('#field3').attr('data-parsley-group', 'bar');
expectWarning(() => {
expect(parsleyForm.isValid('bar')).to.be(false);
});
});
it('should handle group validation with controls with multiple group names', () => {
$('body').append(
'<form id="element">' +
'<input id="field1" type="text" data-parsley-group=\'["foo", "bar"]\' data-parsley-required="true" />' +
'<input id="field2" type="text" data-parsley-group=\'["bar", "baz"]\' data-parsley-required="true" />' +
'<textarea id="field3" data-parsley-group=\'["baz", "qux"]\' data-parsley-required="true"></textarea>' +
'</form>');
var parsleyForm = $('#element').parsley();
expect(parsleyForm.isValid()).to.be(false);
$('#field1').val('value');
$('#field2').val('value');
expect(parsleyForm.isValid()).to.be(false);
// group name only on one required field, with value
expect(parsleyForm.isValid('foo')).to.be(true);
// group name on multiple required fields, all with values
expect(parsleyForm.isValid('bar')).to.be(true);
// group name on multiple required fields, one missing a value
expect(parsleyForm.isValid('baz')).to.be(false);
// group name on single required field, without value
expect(parsleyForm.isValid('qux')).to.be(false);
});
it('should send submit button values, even for async validations', () => {
var deferred = null;
window.Parsley.addValidator('custom', () => {
deferred = $.Deferred();
return deferred.promise();
});
$('body').append(
'<form id="element">' +
'<input id="field1" type="text" name="nick" data-parsley-custom data-parsley-required />' +
'<div id="field2" name="comment"></div>' +
'<input type="submit" name="foo" value="bar" />' +
'<input type="submit" name="foo" value="other" />' +
'<button name="foo" value="but">ok</button>' +
'</form>');
var parsleyForm = $('#element').parsley();
$('#element input:last').click();
// Form should not be submitted at this point, coz field is required
expect(deferred).to.be(null);
$('#field1').val('something');
var values = [];
$('#element').on('submit', evt => {
expect(evt.parsley).to.be(true);
values.push($('form input[type!=submit][name="foo"]').val());
evt.preventDefault();
});
$('#element button').click();
expect(values).to.eql([]);
deferred.resolve();
expect(values).to.eql(['but']);
$('#element input[value="other"]').click();
deferred.resolve();
expect(values).to.eql(['but', 'other']);
$('#element').submit(); // Similar to pressing 'enter'
deferred.resolve();
expect(values).to.eql(['but', 'other', 'bar']);
window.Parsley.removeValidator('custom');
});
it('should not validate when triggered by a button with formnovalidate', () => {
var $form = $('<form id="element"><input type="string" required /><input type="submit" formnovalidate /><form>').appendTo($('body'));
$form.on('submit', e => {
e.preventDefault();
});
var callbacks = [];
$.each(['validate', 'error', 'success', 'validated', 'submit'], (i, cb) => {
$form.parsley().on('form:' + cb, () => {
callbacks.push(cb);
});
});
$form.parsley();
$form.find('input[type=submit]').click();
expect(callbacks.join()).to.be('');
});
it('should have a force option for validate and isValid methods', () => {
$('body').append(
'<form id="element">' +
'<input id="field1" type="email" />' +
'<input id="field3" data-parsley-notblank="true" />' +
'</form>');
expect($('#element').parsley().isValid()).to.be(true);
expect($('#element').parsley().isValid({force: true})).to.be(false);
expect($('#element').parsley().validate()).to.be(true);
expectWarning(() => {
expect($('#element').parsley().validate(undefined, true)).to.be(false);
});
});
it('should properly bind dynamically added fields', () => {
$('body').append('<form id="element" data-parsley-trigger="change"></form>');
$('#element').append('<input type="email" id="email" required />');
var fieldInstance = $('#email').psly();
expect(fieldInstance.__class__).to.be('ParsleyField');
var formInstance = $('#element').psly();
// form corectly have its field, and field have finaly its parent form
expect(formInstance.fields[0].$element.attr('id')).to.be('email');
expect(fieldInstance.parent.__class__).to.be('ParsleyForm');
});
it('should fire the right callbacks in the right order', () => {
var $form = $('<form id="element"><input type="string" required /><form>').appendTo($('body'));
$form.on('submit', e => {
e.preventDefault();
});
var callbacks = [];
$.each(['validate', 'error', 'success', 'validated', 'submit'], (i, cb) => {
$form.parsley().on('form:' + cb, () => {
callbacks.push(cb);
});
});
$form.parsley();
$form.submit();
$form.find('input').val('Hello');
$form.submit();
expect(callbacks.join()).to.be('validate,error,validated,validate,success,validated,submit');
});
it('should fire "form:validate.parsley" to give the opportunity for changes before validation occurs', () => {
var $form = $('<form id="element"><input type="string" required /><form>').appendTo($('body'));
$form.parsley().on('form:validate', function () {
this.$element.find('input').remove();
});
expect($form.parsley().validate()).to.be(true);
});
it('should stop event propagation on form submit', done => {
$('body').append('<form id="element"><input type="text" required/></form>');
var parsleyInstance = $('#element').parsley()
.on('form:validated', () => {
done();
});
$('#element').on('submit', () => {
// It sould never pass here!
expect(true).to.be(false);
})
.submit();
});
it('should have the validationResult be changeable', () => {
var submitted = false;
$('<form id="element"></form>')
.appendTo('body')
.parsley()
.on('form:success', form => {
form.validationResult = false;
})
.on('form:error', form => {
form.validationResult = true;
})
.on('form:submit', form => {
submitted = true;
return false;
});
$('#element').submit();
expect(submitted).to.be(false);
$('#element').append('<input required>').submit();
expect(submitted).to.be(true);
});
it('should fire form:submit.event and be interruptable when validated', done => {
$('<form id="element"></form>')
.appendTo('body')
.parsley()
.on('form:submit', () => {
done();
return false;
});
$('#element').submit();
});
it('should deprecate interruptions with submitEvent.preventDefault()', () => {
expectWarning(() => {
$('<form id="element"></form>')
.appendTo('body')
.parsley()
.on('form:validate', (form) => {
form.submitEvent.preventDefault();
})
.on('form:submit', (form) => {
throw new Error('Form should not have been submitted');
});
$('#element').submit();
});
});
it('should fire field:reset event if fields are removed or excluded', () => {
var parsleyInstance;
var steps = [];
var step = 'init';
var parsleyForm = $('<form id="element"><input type="text" required></form>')
.appendTo('body')
.parsley()
.on('field:reset', function () {
steps.push('form: ' + step);
expect(this).to.be(parsleyInstance);
})
;
parsleyInstance = $('#element input').parsley()
.on('field:reset', function () {
steps.push('field: ' + step);
expect(this).to.be(parsleyInstance);
});
parsleyForm.validate();
parsleyForm.validate();
parsleyForm.options.excluded = '[required]';
step = 'excluded';
parsleyForm.validate();
parsleyForm.validate();
parsleyForm.options.excluded = '';
step = 'not excluded';
parsleyForm.validate();
parsleyForm.validate();
var $i = $('#element input').detach();
step = 'detached';
parsleyForm.validate();
parsleyForm.validate();
$i.appendTo('form');
step = 'reattached';
parsleyForm.validate();
parsleyForm.validate();
$i.remove();
step = 'removed';
parsleyForm.validate();
parsleyForm.validate();
expect(steps).to.eql(['field: excluded', 'form: excluded', 'field: detached', 'form: detached', 'field: removed', 'form: removed']);
});
it('should handle validators returning promises', done => {
var called = 0;
var shouldSubmit = false;
var form = $('<form id="element"><input data-parsley-custom value="x"/></form>')
.appendTo('body')
.parsley();
var deferred;
window.Parsley.addValidator('custom', () => {
called++;
deferred = $.Deferred();
return deferred.promise();
});
$('#element').on('submit', evt => {
evt.preventDefault();
expect(evt.parsley).to.be(true); // Sanity check
expect(shouldSubmit).to.be(true);
window.Parsley.removeValidator('custom');
done();
});
$('#element').submit();
expect(called).to.eql(1);
deferred.reject();
var promise = form.whenValidate();
expect(called).to.eql(2);
expect(promise.state()).to.eql('pending');
deferred.reject();
expect(promise.state()).to.eql('rejected');
$('#element').submit();
expect(called).to.eql(3);
shouldSubmit = true;
deferred.resolve();
});
it('should handle priority correctly', () => {
var calls = [];
var form = $('<form id="element"><input value="0" data-parsley-custom1 data-parsley-custom2 data-parsley-custom3 data-parsley-custom4/></form>')
.appendTo('body')
.parsley()
.on('form:submit', evt => { return false; });
for (const i of [1, 2, 3, 4])
window.Parsley.addValidator(`custom${i}`, {
priority: i <= 2 ? 100 : 10 - i,
validateNumber: function(value, requirement) {
calls.push(i);
return value > i;
}
});
$('#element').submit();
$('#element input').val('3');
$('#element').submit();
$('#element input').val('5');
$('#element').submit();
expect(calls).to.eql([2, 1, 2, 1, 3, 2, 1, 3, 4]);
for (const i of [1, 2, 3, 4])
window.Parsley.removeValidator(`custom${i}`);
});
afterEach(() => {
$('#element').remove();
});
});