From f23082edbc3193e0b3275620fc7ed7f47bef1f05 Mon Sep 17 00:00:00 2001 From: Tim van der Horst Date: Thu, 20 Oct 2016 17:02:38 +1000 Subject: [PATCH] Allow custom `prettify` function to be defined via global options Additionally, `prettiy` can be further overridden in validator options for `numericality` and `equality` validators. --- specs/validate-helpers-spec.js | 22 +++++++++++ specs/validate-spec.js | 56 +++++++++++++++++++++++++++ specs/validators/equality-spec.js | 9 +++++ specs/validators/numericality-spec.js | 9 +++++ validate.js | 32 +++++++++------ 5 files changed, 117 insertions(+), 11 deletions(-) diff --git a/specs/validate-helpers-spec.js b/specs/validate-helpers-spec.js index 16afb74..d47644d 100644 --- a/specs/validate-helpers-spec.js +++ b/specs/validate-helpers-spec.js @@ -154,6 +154,15 @@ describe("validate", function() { expect(validate.stringifyValue("barfoo")).toEqual("foobar"); expect(validate.prettify).toHaveBeenCalledWith("barfoo"); }); + + it("calls custom prettify from options", function() { + var options = {prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("foobar"); + spyOn(validate, "prettify").and.returnValue("baz"); + expect(validate.stringifyValue("barfoo", options)).toEqual("foobar"); + expect(options.prettify).toHaveBeenCalledWith("barfoo"); + expect(validate.prettify).not.toHaveBeenCalled(); + }); }); describe('prettify', function() { @@ -433,6 +442,19 @@ describe("validate", function() { }]); }); + it("calls custom prettify from options", function() { + var errors = [{ + attribute: "foo", + error: "can't be blank" + }] + , options = {prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("foobar"); + spyOn(validate, "prettify").and.returnValue("baz"); + expect(convertErrorMessages(errors, options)[0].error).toEqual("Foobar can't be blank"); + expect(options.prettify).toHaveBeenCalledWith("foo"); + expect(validate.prettify).not.toHaveBeenCalled(); + }); + it("doesn't modify the input", function() { var errors = [{ attribute: "foo", diff --git a/specs/validate-spec.js b/specs/validate-spec.js index 2e0503b..20fc034 100644 --- a/specs/validate-spec.js +++ b/specs/validate-spec.js @@ -243,6 +243,62 @@ describe("validate", function() { {} ); }); + + it("calls custom prettify in global options", function() { + var constraints = {foo: {presence: true}} + , options = {format: "flat", prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("foobar"); + spyOn(validate, "prettify").and.returnValue("baz"); + expect(validate({}, constraints, options)).toEqual(["Foobar can't be blank"]); + expect(options.prettify).toHaveBeenCalledWith("foo"); + expect(validate.prettify).not.toHaveBeenCalled(); + }); + + it("calls custom prettify in global options inside numericality validator", function() { + var constraints = {foo: {numericality: {greaterThan: 0}}} + , options = {format: "flat", prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("foobar"); + spyOn(validate, "prettify").and.returnValue("baz"); + expect(validate({foo: 0}, constraints, options)).toEqual(["Foobar must be foobar 0"]); + var args = options.prettify.calls.allArgs(); + expect(args).toContain(["foo"]); + expect(args).toContain(["greaterThan"]); + expect(validate.prettify).not.toHaveBeenCalled(); + }); + + it("calls custom prettify in global options inside equality validator", function() { + var constraints = {bar: {equality: {attribute: "foo"}}} + , options = {format: "flat", prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("foobar"); + spyOn(validate, "prettify").and.returnValue("baz"); + expect(validate({foo: 'a', bar: 'b'}, constraints, options)).toEqual(["Foobar is not equal to foobar"]); + expect(options.prettify.calls.allArgs()).toContain(["bar"]); + expect(validate.prettify).not.toHaveBeenCalled(); + }); + + it("calls custom prettify in numericality options", function() { + var constraints = {foo: {numericality: {greaterThan: 0, prettify: function() {}}}} + , options = {format: "flat", prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("foobar"); + spyOn(constraints.foo.numericality, "prettify").and.returnValue("grooter than"); + spyOn(validate, "prettify").and.returnValue("baz"); + expect(validate({foo: 0}, constraints, options)).toEqual(["Foobar must be grooter than 0"]); + expect(options.prettify).toHaveBeenCalledWith("foo"); + expect(constraints.foo.numericality.prettify).toHaveBeenCalledWith("greaterThan"); + expect(validate.prettify).not.toHaveBeenCalled(); + }); + + it("calls custom prettify in equality options", function() { + var constraints = {bar: {equality: {attribute: "foo", prettify: function() {}}}} + , options = {format: "flat", prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("foobar"); + spyOn(constraints.bar.equality, "prettify").and.returnValue("qux"); + spyOn(validate, "prettify").and.returnValue("baz"); + expect(validate({foo: 'a', bar: 'b'}, constraints, options)).toEqual(["Foobar is not equal to qux"]); + expect(options.prettify.calls.allArgs()).toContain(["bar"]); + expect(constraints.bar.equality.prettify).toHaveBeenCalledWith("foo"); + expect(validate.prettify).not.toHaveBeenCalled(); + }); }); describe("format", function() { diff --git a/specs/validators/equality-spec.js b/specs/validators/equality-spec.js index 3ba450f..0dfac51 100644 --- a/specs/validators/equality-spec.js +++ b/specs/validators/equality-spec.js @@ -101,4 +101,13 @@ describe('validators.equality', function() { , value = "foo"; expect(equality(value, options)).toBe(message); }); + + it("calls custom prettify from options", function() { + var options = {attribute: "fooBar", prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("qux"); + spyOn(validate, "prettify").and.returnValue("baz"); + expect(equality("foo", options, "foo", {foo: "foo"})).toEqual("is not equal to qux"); + expect(options.prettify).toHaveBeenCalledWith("fooBar"); + expect(validate.prettify).not.toHaveBeenCalled(); + }); }); diff --git a/specs/validators/numericality-spec.js b/specs/validators/numericality-spec.js index 4a127a2..e2754a2 100644 --- a/specs/validators/numericality-spec.js +++ b/specs/validators/numericality-spec.js @@ -382,4 +382,13 @@ describe("validators.numericality", function() { expect(numericality("foo", {message: "some error"})).toEqual("some error"); }); + + it("calls custom prettify from options", function() { + var options = {greaterThan: 0, prettify: function() {}}; + spyOn(options, "prettify").and.returnValue("grooter than"); + spyOn(validate, "prettify").and.returnValue("greeter than"); + expect(numericality(0, options)).toEqual(["must be grooter than 0"]); + expect(options.prettify).toHaveBeenCalledWith("greaterThan"); + expect(validate.prettify).not.toHaveBeenCalled(); + }); }); diff --git a/validate.js b/validate.js index 9d470c4..bbb55d7 100644 --- a/validate.js +++ b/validate.js @@ -411,8 +411,9 @@ .toLowerCase(); }, - stringifyValue: function(value) { - return v.prettify(value); + stringifyValue: function(value, options) { + var prettify = options && options.prettify || v.prettify; + return prettify(value); }, isString: function(value) { @@ -628,7 +629,8 @@ convertErrorMessages: function(errors, options) { options = options || {}; - var ret = []; + var ret = [] + , prettify = options.prettify || v.prettify; errors.forEach(function(errorInfo) { var error = v.result(errorInfo.error, errorInfo.value, @@ -645,10 +647,12 @@ if (error[0] === '^') { error = error.slice(1); } else if (options.fullMessages !== false) { - error = v.capitalize(v.prettify(errorInfo.attribute)) + " " + error; + error = v.capitalize(prettify(errorInfo.attribute)) + " " + error; } error = error.replace(/\\\^/g, "^"); - error = v.format(error, {value: v.stringifyValue(errorInfo.value)}); + error = v.format(error, { + value: v.stringifyValue(errorInfo.value, options) + }); ret.push(v.extend({}, errorInfo, {error: error})); }); return ret; @@ -816,7 +820,7 @@ return options.message || errors; } }, - numericality: function(value, options) { + numericality: function(value, options, attribute, attributes, globalOptions) { // Empty values are fine if (!v.isDefined(value)) { return; @@ -834,7 +838,10 @@ lessThan: function(v, c) { return v < c; }, lessThanOrEqualTo: function(v, c) { return v <= c; }, divisibleBy: function(v, c) { return v % c === 0; } - }; + } + , prettify = options.prettify || + (globalOptions && globalOptions.prettify) || + v.prettify; // Strict will check that it is a valid looking number if (v.isString(value) && options.strict) { @@ -891,7 +898,7 @@ errors.push(v.format(msg, { count: count, - type: v.prettify(name) + type: prettify(name) })); } } @@ -1052,7 +1059,7 @@ }, { PATTERN: /^[a-z0-9\u007F-\uffff!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9\u007F-\uffff!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}$/i }), - equality: function(value, options, attribute, attributes) { + equality: function(value, options, attribute, attributes, globalOptions) { if (!v.isDefined(value)) { return; } @@ -1072,10 +1079,13 @@ var otherValue = v.getDeepObjectValue(attributes, options.attribute) , comparator = options.comparator || function(v1, v2) { return v1 === v2; - }; + } + , prettify = options.prettify || + (globalOptions && globalOptions.prettify) || + v.prettify; if (!comparator(value, otherValue, options, attribute, attributes)) { - return v.format(message, {attribute: v.prettify(options.attribute)}); + return v.format(message, {attribute: prettify(options.attribute)}); } },