From 7322f7af60b50cfed9df17affa43611b57d525df Mon Sep 17 00:00:00 2001 From: Pelle Wessman Date: Wed, 13 Mar 2024 19:38:31 +0100 Subject: [PATCH] Promise variant of the two .validate() + validatePastFirstError is now respected + field.validate() now always returns an error and that is tested --- lib/fields.js | 25 ++++++++++++++++++++++++- lib/forms.js | 22 ++++++++++++++++++++++ test/test-fields.js | 45 +++++++++++++++++++++++++++++++++++++++++++-- test/test-form.js | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 3 deletions(-) diff --git a/lib/fields.js b/lib/fields.js index a7c6959..51782df 100644 --- a/lib/fields.js +++ b/lib/fields.js @@ -30,7 +30,28 @@ exports.string = function (options) { var b = assign({}, f); // clone field object: b.value = raw_data; b.data = b.parse(raw_data); - b.validate = function (form, callback) { + b.validate = function (form, rawCallback) { + var callback = rawCallback; + var returnValue; + + if (!callback) { + if (typeof Promise !== 'function') { + throw new Error('Callback is required when Promises are unsupported'); + } + returnValue = new Promise(function (resolve) { + callback = function (err, bound_field) { + if (err) { + resolve({ + error: true, + message: err, + field: bound_field + }); + } else { + resolve({ error: false }); + } + }; + }); + } var forceValidation = some(b.validators || [], function (validator) { return validator.forceValidation; }); @@ -61,6 +82,8 @@ exports.string = function (options) { callback(err, b); }); } + + return returnValue; }; return b; }; diff --git a/lib/forms.js b/lib/forms.js index 4ccac92..030ffae 100644 --- a/lib/forms.js +++ b/lib/forms.js @@ -49,6 +49,26 @@ exports.create = function (fields, options) { }, {}); b.validate = function () { var callback = arguments.length > 1 ? arguments[1] : arguments[0]; + var returnValue; + + if (!callback) { + if (typeof Promise !== 'function') { + throw new Error('Callback is required when Promises are unsupported'); + } + returnValue = new Promise(function (resolve) { + callback = function (err, form) { + if (form.isValid()) { + resolve({ error: false }); + } else { + resolve({ + error: true, + message: String(err || ''), + form: form + }); + } + }; + }); + } asyncForEach(keys(b.fields), function (k, asyncCallback) { b.fields[k].validate(b, function (err, bound_field) { @@ -58,6 +78,8 @@ exports.create = function (fields, options) { }, function (err) { callback(err, b); }); + + return returnValue; }; b.isValid = function () { var form = this; diff --git a/test/test-fields.js b/test/test-fields.js index fd47d66..5c4921f 100644 --- a/test/test-fields.js +++ b/test/test-fields.js @@ -58,7 +58,7 @@ var testField = function (field) { }); test(field + ' validate', function (t) { - t.plan(10); + t.plan(11); var f = fields[field]({ label: 'test label' }); f.validators = [ @@ -79,6 +79,8 @@ var testField = function (field) { return 'some data parsed'; }; f.bind('some data').validate('form', function (err, bound) { + t.equal(err, 'Error: validation error'); + t.equal(bound.label, 'test label'); t.equal(bound.value, 'some data'); t.equal(bound.data, 'some data parsed'); @@ -88,6 +90,46 @@ var testField = function (field) { }); }); + test(field + ' promised validate', function (t) { + if (typeof Promise !== 'function') { + return t.end(); + } + + t.plan(13); + + var f = fields[field]({ label: 'test label' }); + f.validators = [ + function (form, fieldObject, callback) { + t.equal(fieldObject.data, 'some data parsed'); + t.equal(fieldObject.value, 'some data'); + callback(null); + }, + function (form, fieldObject, callback) { + t.equal(fieldObject.data, 'some data parsed'); + t.equal(fieldObject.value, 'some data'); + callback(new Error('validation error')); + } + ]; + + f.parse = function (data) { + t.equal(data, 'some data'); + return 'some data parsed'; + }; + return f.bind('some data').validate('form').then(function (result) { + t.ok(result, 'gets a result'); + t.ok(result.error, 'is an error'); + t.equal(result.message, 'Error: validation error'); + + var bound = result.field; + + t.equal(bound.label, 'test label'); + t.equal(bound.value, 'some data'); + t.equal(bound.data, 'some data parsed'); + t.equal(bound.error, 'Error: validation error'); + t.notEqual(bound, f, 'bind returns a new field object'); + }); + }); + test(field + ' validate multiple errors', function (t) { t.plan(1); @@ -144,7 +186,6 @@ var testField = function (field) { t.equal(fieldObject.data, 'val'); t.notOk(fieldObject.error); }); - t.end(); }); test(field + ' validate no validators', function (t) { diff --git a/test/test-form.js b/test/test-form.js index 26455a2..4853ce8 100644 --- a/test/test-form.js +++ b/test/test-form.js @@ -81,6 +81,46 @@ test('validate', function (t) { }); var data = { field1: 'data one', field2: 'data two' }; form.bind(data).validate(function (err, f) { + t.equal(err, 'validation error'); + + t.equal(f.fields.field1.value, 'data one'); + t.equal(f.fields.field1.data, 'data one'); + t.equal(f.fields.field1.error, undefined); + t.equal(f.fields.field2.value, 'data two'); + t.equal(f.fields.field2.data, 'data two'); + t.equal(f.fields.field2.error, 'validation error'); + + t.deepEqual(f.data, { field1: 'data one', field2: 'data two' }); + t.notEqual(form, f, 'bind returns new form object'); + + t.notOk(f.isValid()); + t.end(); + }); +}); + +test('promised validate', function (t) { + if (typeof Promise !== 'function') { + return t.end(); + } + t.plan(14); + var form = forms.create({ + field1: forms.fields.string(), + field2: forms.fields.string({ + validators: [function (formObject, field, callback) { + t.equal(field.data, 'data two'); + t.equal(field.value, 'data two'); + callback('validation error'); + }] + }) + }); + var data = { field1: 'data one', field2: 'data two' }; + return form.bind(data).validate().then(function (result) { + t.ok(result, 'gets a result'); + t.ok(result.error, 'is an error'); + t.equal(result.message, 'validation error'); + + var f = result.form; + t.equal(f.fields.field1.value, 'data one'); t.equal(f.fields.field1.data, 'data one'); t.equal(f.fields.field1.error, undefined);