From 1dc7fb70af9b61a848472a595bfc4320039844f8 Mon Sep 17 00:00:00 2001 From: Icebob Date: Thu, 23 Mar 2017 20:33:06 +0100 Subject: [PATCH 1/6] add `.locale` method to every validator --- src/utils/validators.js | 110 ++++++++++++----------- test/unit/specs/utils/validators.spec.js | 25 +++++- 2 files changed, 84 insertions(+), 51 deletions(-) diff --git a/src/utils/validators.js b/src/utils/validators.js index c44bebac..698cd37a 100644 --- a/src/utils/validators.js +++ b/src/utils/validators.js @@ -1,10 +1,10 @@ -import { isNil, isNumber, isString, isArray } from "lodash"; +import { defaults, isNil, isNumber, isString, isArray, isFunction } from "lodash"; import fecha from "fecha"; -function checkEmpty(value, required) { +function checkEmpty(value, required, messages) { if (isNil(value) || value === "") { if (required) - return [msg(resources.fieldIsRequired)]; + return [msg(messages.fieldIsRequired)]; else return []; } @@ -54,131 +54,131 @@ module.exports = { resources, - required(value, field) { - return checkEmpty(value, field.required); + required(value, field, messages = resources) { + return checkEmpty(value, field.required, messages); }, - number(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + number(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; let err = []; if (isNumber(value)) { if (!isNil(field.min) && value < field.min) - err.push(msg(resources.numberTooSmall, field.min)); + err.push(msg(messages.numberTooSmall, field.min)); if (!isNil(field.max) && value > field.max) - err.push(msg(resources.numberTooBig, field.max)); + err.push(msg(messages.numberTooBig, field.max)); } else - err.push(msg(resources.invalidNumber)); + err.push(msg(messages.invalidNumber)); return err; }, - integer(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + integer(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; if (!(Number(value) === value && value % 1 === 0)) - return [msg(resources.invalidNumber)]; + return [msg(messages.invalidNumber)]; }, - double(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + double(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; if (!isNumber(value) || isNaN(value)) - return [msg(resources.invalidNumber)]; + return [msg(messages.invalidNumber)]; }, - string(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + string(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; let err = []; if (isString(value)) { if (!isNil(field.min) && value.length < field.min) - err.push(msg(resources.textTooSmall, value.length, field.min)); + err.push(msg(messages.textTooSmall, value.length, field.min)); if (!isNil(field.max) && value.length > field.max) - err.push(msg(resources.textTooBig, value.length, field.max)); + err.push(msg(messages.textTooBig, value.length, field.max)); } else - err.push(msg(resources.thisNotText)); + err.push(msg(messages.thisNotText)); return err; }, - array(value, field) { + array(value, field, messages = resources) { if (field.required) { if (!isArray(value)) - return [msg(resources.thisNotArray)]; + return [msg(messages.thisNotArray)]; if (value.length == 0) - return [msg(resources.fieldIsRequired)]; + return [msg(messages.fieldIsRequired)]; } if (!isNil(value)) { if (!isNil(field.min)) if (value.length < field.min) - return [msg(resources.selectMinItems, field.min)]; + return [msg(messages.selectMinItems, field.min)]; if (!isNil(field.max)) if (value.length > field.max) - return [msg(resources.selectMaxItems, field.max)]; + return [msg(messages.selectMaxItems, field.max)]; } }, - date(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + date(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; let m = new Date(value); if (!m) - return [msg(resources.invalidDate)]; + return [msg(messages.invalidDate)]; let err = []; if (!isNil(field.min)) { let min = new Date(field.min); if (m.valueOf() < min.valueOf()) - err.push(msg(resources.dateIsEarly, fecha.format(m), fecha.format(min))); + err.push(msg(messages.dateIsEarly, fecha.format(m), fecha.format(min))); } if (!isNil(field.max)) { let max = new Date(field.max); if (m.valueOf() > max.valueOf()) - err.push(msg(resources.dateIsLate, fecha.format(m), fecha.format(max))); + err.push(msg(messages.dateIsLate, fecha.format(m), fecha.format(max))); } return err; }, - regexp(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + regexp(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; if (!isNil(field.pattern)) { let re = new RegExp(field.pattern); if (!re.test(value)) - return [msg(resources.invalidFormat)]; + return [msg(messages.invalidFormat)]; } }, - email(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + email(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; if (!re.test(value)) - return [msg(resources.invalidEmail)]; + return [msg(messages.invalidEmail)]; }, - url(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + url(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; let re = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g; if (!re.test(value)) - return [msg(resources.invalidURL)]; + return [msg(messages.invalidURL)]; }, - creditCard(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + creditCard(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; /* From validator.js code https://github.com/chriso/validator.js/blob/master/src/lib/isCreditCard.js @@ -186,7 +186,7 @@ module.exports = { const creditCard = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/; const sanitized = value.replace(/[^0-9]+/g, ""); if (!creditCard.test(sanitized)) { - return [msg(resources.invalidCard)]; + return [msg(messages.invalidCard)]; } let sum = 0; let digit; @@ -209,22 +209,32 @@ module.exports = { } if (!((sum % 10) === 0 ? sanitized : false)) - return [msg(resources.invalidCardNumber)]; + return [msg(messages.invalidCardNumber)]; }, - alpha(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + alpha(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; let re = /^[a-zA-Z]*$/; if (!re.test(value)) - return [msg(resources.invalidTextContainNumber)]; + return [msg(messages.invalidTextContainNumber)]; }, - alphaNumeric(value, field) { - let res = checkEmpty(value, field.required); if (res != null) return res; + alphaNumeric(value, field, messages = resources) { + let res = checkEmpty(value, field.required, messages); if (res != null) return res; let re = /^[a-zA-Z0-9]*$/; if (!re.test(value)) - return [msg(resources.invalidTextContainSpec)]; + return [msg(messages.invalidTextContainSpec)]; } }; + +Object.keys(module.exports).forEach(name => { + const fn = module.exports[name]; + if (isFunction(fn)) { + fn.locale = (customMessages) => { + const messages = defaults(customMessages, resources); + return (value, field) => fn(value, field, messages); + }; + } +}); \ No newline at end of file diff --git a/test/unit/specs/utils/validators.spec.js b/test/unit/specs/utils/validators.spec.js index f32d78ff..cee1cc0b 100644 --- a/test/unit/specs/utils/validators.spec.js +++ b/test/unit/specs/utils/validators.spec.js @@ -11,7 +11,7 @@ function check(validator, value, field, errorCount) { return res; } -describe("Validators", () => { +describe.only("Validators", () => { describe("test Validators.required", () => { @@ -427,4 +427,27 @@ describe("Validators", () => { }); }); + + describe("test local custom error messages", () => { + + let field = { + min: 5, + max: 10, + required: true + }; + + let locNumber = v.number.locale({ + fieldIsRequired: "Ezt a mezőt kötelező kitölteni!", + numberTooSmall: "Ez a szám nem lehet kisebb mint {0}!" + }); + + it("should give the custom error message", () => { + expect(locNumber(null, field)[0]).to.be.equal("Ezt a mezőt kötelező kitölteni!"); + expect(locNumber(2, field)[0]).to.be.equal("Ez a szám nem lehet kisebb mint 5!"); + }); + + it("should give the default error message", () => { + expect(locNumber(30, field)[0]).to.be.equal("The number is too big! Maximum: 10"); + }); + }); }); \ No newline at end of file From 560d234629981660a06bfdf7d862705c20a3e6cb Mon Sep 17 00:00:00 2001 From: Icebob Date: Thu, 23 Mar 2017 20:33:25 +0100 Subject: [PATCH 2/6] remove only from test --- test/unit/specs/utils/validators.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/specs/utils/validators.spec.js b/test/unit/specs/utils/validators.spec.js index cee1cc0b..a73ced09 100644 --- a/test/unit/specs/utils/validators.spec.js +++ b/test/unit/specs/utils/validators.spec.js @@ -11,7 +11,7 @@ function check(validator, value, field, errorCount) { return res; } -describe.only("Validators", () => { +describe("Validators", () => { describe("test Validators.required", () => { From d97c917ee08e865fc09814593841a3ce21465812 Mon Sep 17 00:00:00 2001 From: Icebob Date: Thu, 23 Mar 2017 20:42:30 +0100 Subject: [PATCH 3/6] fix parameters of validators --- src/utils/validators.js | 65 +++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/utils/validators.js b/src/utils/validators.js index 698cd37a..1e46d3ba 100644 --- a/src/utils/validators.js +++ b/src/utils/validators.js @@ -1,24 +1,6 @@ import { defaults, isNil, isNumber, isString, isArray, isFunction } from "lodash"; import fecha from "fecha"; -function checkEmpty(value, required, messages) { - if (isNil(value) || value === "") { - if (required) - return [msg(messages.fieldIsRequired)]; - else - return []; - } - return null; -} - -function msg(text) { - if (text != null && arguments.length > 1) - for (let i = 1; i < arguments.length; i++) - text = text.replace(/\{\d+?\}/, arguments[i]); - - return text; -} - let resources = { fieldIsRequired: "This field is required!", invalidFormat: "Invalid format!", @@ -50,15 +32,34 @@ let resources = { invalidTextContainSpec: "Invalid text! Cannot contains special characters" }; + +function checkEmpty(value, required, messages = resources) { + if (isNil(value) || value === "") { + if (required) + return [msg(messages.fieldIsRequired)]; + else + return []; + } + return null; +} + +function msg(text) { + if (text != null && arguments.length > 1) + for (let i = 1; i < arguments.length; i++) + text = text.replace(/\{\d+?\}/, arguments[i]); + + return text; +} + module.exports = { resources, - required(value, field, messages = resources) { + required(value, field, model, messages = resources) { return checkEmpty(value, field.required, messages); }, - number(value, field, messages = resources) { + number(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; let err = []; @@ -75,21 +76,21 @@ module.exports = { return err; }, - integer(value, field, messages = resources) { + integer(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; if (!(Number(value) === value && value % 1 === 0)) return [msg(messages.invalidNumber)]; }, - double(value, field, messages = resources) { + double(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; if (!isNumber(value) || isNaN(value)) return [msg(messages.invalidNumber)]; }, - string(value, field, messages = resources) { + string(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; let err = []; @@ -106,7 +107,7 @@ module.exports = { return err; }, - array(value, field, messages = resources) { + array(value, field, model, messages = resources) { if (field.required) { if (!isArray(value)) @@ -127,7 +128,7 @@ module.exports = { } }, - date(value, field, messages = resources) { + date(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; let m = new Date(value); @@ -151,7 +152,7 @@ module.exports = { return err; }, - regexp(value, field, messages = resources) { + regexp(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; if (!isNil(field.pattern)) { @@ -161,7 +162,7 @@ module.exports = { } }, - email(value, field, messages = resources) { + email(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; @@ -169,7 +170,7 @@ module.exports = { return [msg(messages.invalidEmail)]; }, - url(value, field, messages = resources) { + url(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; let re = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g; @@ -177,7 +178,7 @@ module.exports = { return [msg(messages.invalidURL)]; }, - creditCard(value, field, messages = resources) { + creditCard(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; /* From validator.js code @@ -212,7 +213,7 @@ module.exports = { return [msg(messages.invalidCardNumber)]; }, - alpha(value, field, messages = resources) { + alpha(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; let re = /^[a-zA-Z]*$/; @@ -220,7 +221,7 @@ module.exports = { return [msg(messages.invalidTextContainNumber)]; }, - alphaNumeric(value, field, messages = resources) { + alphaNumeric(value, field, model, messages = resources) { let res = checkEmpty(value, field.required, messages); if (res != null) return res; let re = /^[a-zA-Z0-9]*$/; @@ -234,7 +235,7 @@ Object.keys(module.exports).forEach(name => { if (isFunction(fn)) { fn.locale = (customMessages) => { const messages = defaults(customMessages, resources); - return (value, field) => fn(value, field, messages); + return (value, field, model) => fn(value, field, model, messages); }; } }); \ No newline at end of file From 267073cd0f700b506b5454c6ebfe02d8039b0de3 Mon Sep 17 00:00:00 2001 From: Icebob Date: Thu, 23 Mar 2017 20:45:00 +0100 Subject: [PATCH 4/6] add example to dev --- dev/full/schema.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dev/full/schema.js b/dev/full/schema.js index d82b1e99..6628b68c 100644 --- a/dev/full/schema.js +++ b/dev/full/schema.js @@ -74,7 +74,10 @@ module.exports = { required: true, hint: "Minimum 6 characters", styleClasses: "half-width", - validator: validators.string + validator: validators.string.locale({ + fieldIsRequired: "The password is required!", + textTooSmall: "Password must be at least {1} characters" + }) }, { type: "input", inputType: "date", From 6b44e393215f5d010b41179c4668b79c95bb8515 Mon Sep 17 00:00:00 2001 From: Icebob Date: Thu, 23 Mar 2017 21:28:59 +0100 Subject: [PATCH 5/6] Fix validator messages interpolation --- dev/full/schema.js | 2 +- src/utils/validators.js | 2 +- test/unit/specs/utils/validators.spec.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/full/schema.js b/dev/full/schema.js index 6628b68c..6cb35635 100644 --- a/dev/full/schema.js +++ b/dev/full/schema.js @@ -76,7 +76,7 @@ module.exports = { styleClasses: "half-width", validator: validators.string.locale({ fieldIsRequired: "The password is required!", - textTooSmall: "Password must be at least {1} characters" + textTooSmall: "Password must be at least {1} characters!" }) }, { type: "input", diff --git a/src/utils/validators.js b/src/utils/validators.js index 1e46d3ba..22870008 100644 --- a/src/utils/validators.js +++ b/src/utils/validators.js @@ -46,7 +46,7 @@ function checkEmpty(value, required, messages = resources) { function msg(text) { if (text != null && arguments.length > 1) for (let i = 1; i < arguments.length; i++) - text = text.replace(/\{\d+?\}/, arguments[i]); + text = text.replace("{" + (i - 1) + "}", arguments[i]); return text; } diff --git a/test/unit/specs/utils/validators.spec.js b/test/unit/specs/utils/validators.spec.js index a73ced09..14dc1cb0 100644 --- a/test/unit/specs/utils/validators.spec.js +++ b/test/unit/specs/utils/validators.spec.js @@ -420,10 +420,10 @@ describe("Validators", () => { it("should give the localized error message", () => { v.resources.fieldIsRequired = "A mezőt kötelező kitölteni!"; - v.resources.textTooSmall = "A szöveg túl rövid. {1} helyett {0}"; + v.resources.textTooSmall = "A szöveg túl rövid. Minimum {1} a {0} helyett"; expect(v.number(null, field)[0]).to.be.equal("A mezőt kötelező kitölteni!"); - expect(v.string("Ab", field)[0]).to.be.equal("A szöveg túl rövid. 2 helyett 5"); + expect(v.string("Ab", field)[0]).to.be.equal("A szöveg túl rövid. Minimum 5 a 2 helyett"); }); }); From cd922ee27d0eb2218ac55c3d1ea204d4973cacfb Mon Sep 17 00:00:00 2001 From: Icebob Date: Thu, 23 Mar 2017 21:31:47 +0100 Subject: [PATCH 6/6] simplify code --- src/utils/validators.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/utils/validators.js b/src/utils/validators.js index 22870008..9a9b219c 100644 --- a/src/utils/validators.js +++ b/src/utils/validators.js @@ -233,9 +233,6 @@ module.exports = { Object.keys(module.exports).forEach(name => { const fn = module.exports[name]; if (isFunction(fn)) { - fn.locale = (customMessages) => { - const messages = defaults(customMessages, resources); - return (value, field, model) => fn(value, field, model, messages); - }; + fn.locale = customMessages => (value, field, model) => fn(value, field, model, defaults(customMessages, resources)); } }); \ No newline at end of file